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, emilhe...@gmail.com 
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