在Julia语言中,函数编译是如何复用的?
我在玩弄 Julia,我遇到了一个关于 Julia 使用的编译器/JIT 编译方案的问题。如果我写了一个函数,比如
function f(x)
return mapreduce(*,+,x,x)
end
那么由于这个函数作用于抽象数组,所以它的形状直到被使用才能知道,所以它不能被编译。然后,如果在函数中使用它,g,其输入是浮点数组的数组,如下所示:
function g(y)
return mapreduce(f,+,y)
end
或者替代地
function g2(y)
res = 0
for x in y
res = res + f(x)
end
return res
end
然后,当我们使用时g,比如说g([[1,2],[3,4]]),最终f会被调用。说它首先被调用[1,2]。然后对其进行编译和评估。据我所知,因为f([3,4])与 完全相同的类型f([1,2]),f将被重用(因为输入都是二维数字数组)。但是,当我输入时@code_llvm(f([1,2])),@code_llvm(f([3,4]))我看到函数的名称是不同的(它们确实有一个共同的前缀,例如julia_f_,然后是一个数字)。此外,如果我@code_llvm(f([1,2]))再次打电话,我会得到另一个名字。
Julia 确实允许为每个应用程序g重用编译版本f吗?这是否取决于所涉及数组的长度?即g([w1,...,wn])每个wi都必须具有相同的长度f才能重复使用?
回答
我不太了解 Julia 的内部结构,但也许这提供了一些f仅编译一次的证据:
function f(x)
mapreduce(*, +, x, x)
end
function g(y)
mapreduce(f, +, y)
end
julia> @time g([[1, 2], [3, 4]])
0.099061 seconds (322.72 k allocations: 19.687 MiB, 99.94% compilation time)
30
julia> @time g([[1, 2], [3, 4]])
0.000021 seconds (11 allocations: 672 bytes)
30
第一次g运行,99.94%的时间都花在了编译上。第二次g运行,0%的时间花在编译上。请注意,如果您想从@time宏中获取编译时间,则需要 Julia v1.6+ 。