第一次和第二次调用函数的性能

时间:2015-01-02 16:12:04

标签: compilation julia dynamic-compilation

考虑以下一段代码(Julia)

bar(x) = for i = 1:9999 x+x*x-x+x end # Define the "bar" function
print("First try: "); @time bar(0.5)
print("Second try: "); @time bar(0.5)
bar(x) = for i = 1:9999 x+x*x-x+x end # Redefine the same "bar" function
print("Third try: "); @time bar(0.5)
print("Fourth try: "); @time bar(0.6)

输出

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)

为什么第二个(和第四个)尝试比第一个(和第三个)尝试快得多(并占用更少的内存)?

1 个答案:

答案 0 :(得分:3)

只是为了扩展保罗的答案:加速的很大一部分来自朱莉娅的类型推理和多次派遣。假设您第一次使用float计算函数:JIT(只是及时编译器)计算出参数的类型并写入适当的LLVM代码。如果您随后使用整数计算相同的函数,则会编译不同的LLVM代码。在以下时间调用该函数,它将根据参数的类型调度不同的LLVM代码。这就是为什么在定义函数时编译通常没有意义的原因。

您可以阅读有关此here的更多信息(文档中有多个对多个调度的引用!)

考虑一下,例如:

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)