Ok. So the bug is in rfft. Thanks for filing the issue, Andreas. What confused me is then probably that I had expected the JIT compiler to compile the loop only after it had learned the runtime type of X.
Thanks, Emil On Thursday, January 15, 2015 at 2:23:13 AM UTC+1, [email protected] wrote: > > Your typeof() in f1 prints the run-time type of the array, the type of the > actual array returned by rfft(), but the code is generated using the > compile time type of the return from rfft(). But as Andreas shows, the > compile time type is incorrectly Any. Using Any the compiler has to > generate runtime type checking and often lots of copying so its slow and > allocates. For f2 you have told the compiler to assume the return type is > the right type so it can generate better code. > > Cheers > Lex > > On Wednesday, January 14, 2015 at 5:39:14 PM UTC+10, [email protected] > wrote: >> >> Hi all, >> >> In the code below I define two functions, f1 and f2, that take a >> three-dimensional array of Float64, computes the real FFT (rfft) and loops >> once over the computed values of the rfft. In f1, a lot of time is spent in >> the simple for loop, and many, many bytes are allocated. In f2, very little >> time is spent in the for loop, and no bytes are allocated, as would be >> expected. The only difference between the two functions is "X = rfft(x)" >> in f1 and "X = rfft(x) :: Array{Complex{Float64}, 3}" in f2. For both >> functions, typeof(X) says that X is an Array{Complex{Float64}, 3}, so the >> extra type annotation in f2 should not be necessary. >> >> I encountered this problem in Julia version 0.3.6 and it persists in >> version 0.4.0-dev+2666. In 0.4.0 the macro @code_warntype can be used to >> reveal that X is of type ANY in f1 but Array{Complex{Float64}, 3} in f2. >> This seems to contradict the output of typeof(X) and is very confusing to >> me. >> >> Cheers, >> Emil >> >> ### Code >> >> function f1(x :: Array{Float64, 3}) >> @time X = rfft(x) >> println("typeof(X) = $(typeof(X))") >> @time for i = 1 : length(X) >> X[i] *= X[i] >> end >> X >> end >> >> function f2(x :: Array{Float64, 3}) >> @time X = rfft(x) :: Array{Complex{Float64}, 3} >> println("typeof(X) = $(typeof(X))") >> @time for i = 1 : length(X) >> X[i] *= X[i] >> end >> X >> end >> >> println("Compiling...") >> f1(rand(2,2,2)) >> f2(rand(2,2,2)) >> >> println("f1...") >> f1(rand(128,128,128)) >> println("f2...") >> f2(rand(128,128,128)) >> >> @code_warntype f1(rand(2,2,2)) >> @code_warntype f2(rand(2,2,2)) >> >> ### Output >> >> Compiling... >> elapsed time: 0.165980813 seconds (5783476 bytes allocated) >> typeof(X) = Array{Complex{Float64},3} >> elapsed time: 0.008426071 seconds (319840 bytes allocated) >> elapsed time: 9.8616e-5 seconds (3560 bytes allocated) >> typeof(X) = Array{Complex{Float64},3} >> elapsed time: 6.28e-7 seconds (0 bytes allocated) >> f1... >> elapsed time: 0.022922817 seconds (17042840 bytes allocated) >> typeof(X) = Array{Complex{Float64},3} >> elapsed time: 0.419889359 seconds (144836816 bytes allocated, 16.67% gc >> time) >> f2... >> elapsed time: 0.023057751 seconds (17042840 bytes allocated) >> typeof(X) = Array{Complex{Float64},3} >> elapsed time: 0.002572673 seconds (0 bytes allocated) >> >> [output of @code_warntype is omitted] >> >
