在Julia语言中,函数编译是如何重用的?

在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

我在玩弄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\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