Compilation 函数的第一次调用与第二次调用的性能

Compilation 函数的第一次调用与第二次调用的性能,compilation,julia,dynamic-compilation,Compilation,Julia,Dynamic Compilation,考虑以下代码(Julia) 输出是 First try: elapsed time: 0.002738996 seconds (88152 bytes allocated) Second try: elapsed time: 3.827e-6 seconds (80 bytes allocated) Third try: elapsed time: 0.002907554 seconds (88152 bytes allocated) Fourth try: elapsed time: 2.39

考虑以下代码(Julia)

输出是

First try: elapsed time: 0.002738996 seconds (88152 bytes allocated)
Second try: elapsed time: 3.827e-6 seconds (80 bytes allocated)
Third try: elapsed time: 0.002907554 seconds (88152 bytes allocated)
Fourth try: elapsed time: 2.395e-6 seconds (80 bytes allocated)

为什么第二次(和第四次)尝试比第一次(和第三次)尝试快得多(占用的内存更少)?据我所知,朱莉娅有一个即时编译器。因此,第一次(和第三次)运行是编译代码(以及为此所需的分配),第二次(和第四次)运行只是运行先前编译的代码,据我所知,Julia有一个即时编译器。因此,第一次(和第三次)运行是编译代码(以及为此所需的分配),第二次(和第四次)运行只是运行先前编译的代码,只是为了扩展Paul的答案:很大一部分加速来自Julia的类型推断和多重分派。假设第一次使用浮点值计算函数:JIT(实时编译器)计算出参数的类型并编写适当的LLVM代码。如果使用整数计算同一函数,则编译不同的LLVM代码。在下面调用函数时,它将根据参数的类型分派不同的LLVM代码。这就是为什么在定义函数时编译通常没有意义的原因

例如,您可以阅读更多关于这方面的内容(文档中有大量关于多个分派的引用!)

例如,考虑:

bar(x) = for i = 1:9999 x+x*x-x+x end

print("First try with floats: "); @time bar(0.5)
print("Second try with floats: "); @time bar(0.5)

print("First try with integers: "); @time bar(1)
print("Second try with integers: "); @time bar(1)
其中:

First try with floats: elapsed time: 0.005570773 seconds (102440 bytes allocated)
Second try with floats: elapsed time: 5.762e-6 seconds (80 bytes allocated)    
First try with integers: elapsed time: 0.003584026 seconds (86896 bytes allocated)    
Second try with integers: elapsed time: 6.402e-6 seconds (80 bytes allocated)

只是扩展一下Paul的答案:很大一部分加速来自Julia的类型推断和多重分派。假设第一次使用浮点值计算函数:JIT(实时编译器)计算出参数的类型并编写适当的LLVM代码。如果使用整数计算同一函数,则编译不同的LLVM代码。在下面调用函数时,它将根据参数的类型分派不同的LLVM代码。这就是为什么在定义函数时编译通常没有意义的原因

例如,您可以阅读更多关于这方面的内容(文档中有大量关于多个分派的引用!)

例如,考虑:

bar(x) = for i = 1:9999 x+x*x-x+x end

print("First try with floats: "); @time bar(0.5)
print("Second try with floats: "); @time bar(0.5)

print("First try with integers: "); @time bar(1)
print("Second try with integers: "); @time bar(1)
其中:

First try with floats: elapsed time: 0.005570773 seconds (102440 bytes allocated)
Second try with floats: elapsed time: 5.762e-6 seconds (80 bytes allocated)    
First try with integers: elapsed time: 0.003584026 seconds (86896 bytes allocated)    
Second try with integers: elapsed time: 6.402e-6 seconds (80 bytes allocated)

据我所知,朱莉娅有一个即时编译器。因此,第一次(和第三次)运行是编译代码(以及为此所需的分配),第二次(和第四次)运行只是运行先前编译的代码。非主题:如果重新运行代码而不修改它,会发生什么?Python创建.pyc文件(类似于编译的源代码)。如果pyc文件仍然与源文件匹配,则不必再次重新编译它(当然,不是再次编译所有文件)。=>好的。这完全有道理。我本以为编译会在函数定义时发生,而不是在第一次运行时发生。我想你可以从你的评论中得出答案。谢谢@PaulJulia,据我所知,她有一个及时的编译器。因此,第一次(和第三次)运行是编译代码(以及为此所需的分配),第二次(和第四次)运行只是运行先前编译的代码。非主题:如果重新运行代码而不修改它,会发生什么?Python创建.pyc文件(类似于编译的源代码)。如果pyc文件仍然与源文件匹配,则不必再次重新编译它(当然,不是再次编译所有文件)。=>好的。这完全有道理。我本以为编译会在函数定义时发生,而不是在第一次运行时发生。我想你可以从你的评论中得出答案。谢谢你,保罗