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]
>>
>

Reply via email to