在Julia语言中,函数编译是如何重用的?
我在玩弄Julia,遇到了一个关于Julia使用的编译器/JIT编译方案的问题。如果我写一个函数,比如在Julia语言中,函数编译是如何重用的?,julia,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
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\u llvm(f([1,2])
和@code\u llvm(f([3,4])
时,我发现函数的名称是不同的(它们确实有一个共同的前缀,类似于julia\u f
,然后后跟一个数字)。另外,如果我再次调用@code\ulvm(f([1,2])
,我会得到另一个名字
Julia是否真的允许
g
为每个应用程序重用f
的编译版本?这是否取决于所涉及阵列的长度;i、 e.在g([w1,…,wn])
中,每个wi
是否必须具有相同的长度才能重复使用f
?我对Julia内部结构了解不多,但这可能提供了一些证据,证明f
只编译一次:
function f(x)
mapreduce(*, +, x, x)
end
function g(y)
mapreduce(f, +, y)
end
第一次运行
g
时,99.94%的时间用于编译。第二次运行g
时,0%的时间用于编译。请注意,如果要从@time
宏中获取编译时间,则需要Julia v1.6+。我认为这只是一个打印问题(或者可能是通过@code\u llvm
查看实现的副作用)。这些内部函数名不能准确地反映Julia在实践中所做的事情。这并不能完全回答问题,但可能会有所帮助:
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