I'm toying around with Julia, and I have run into a question about the compiler/JIT compilation scheme that Julia uses. If I write a function such as
function f(x)
return mapreduce(*,+,x,x)
end
Then since this function works on abstract arrays, its shape can't be known until it's used, so it can't be compiled. Then if use this in a function, g, whose inputs are arrays of arrays of floats like so:
function g(y)
return mapreduce(f,+,y)
end
Or alternatively
function g2(y)
res = 0
for x in y
res = res + f(x)
end
return res
end
Then, when we use g, say g([[1,2],[3,4]]), eventually f will be called. Say it's called on [1,2] first. Then it's compiled, and evaluated. As far as I can tell, since f([3,4]) is on the exact same type as f([1,2]), f will be reused (since the inputs are both 2 dimensional arrays of numbers). However, when I type @code_llvm(f([1,2])) and @code_llvm(f([3,4])) I see that the names of the functions are different (they do have a common prefix, something like julia_f_ and then its followed by a number). Also, if I call @code_llvm(f([1,2])) again, I get yet another name.
Does Julia indeed allow g to reuse the compiled version of f for each application? Does this depend on the length of the arrays involved; i.e. in g([w1,...,wn]) does each wi have to have the same length for f to be reused?