Hi Glen,

Thanks for the investigation. I am afraid the for loop in map!() is not the 
source of the issue. Consider the folowing:

_f(a,f) = (a - f) / a

function mape4(A, F)
# A - actual target values
# F - forecasts (model estimations)

  tmp = similar(A)
  map!(_f, tmp, A, F)
  100 * sumabs(tmp) / length(A)

end

function mape4a(A, F)

    tmp = similar(A)
    for i in eachindex(A)
        tmp[i] = _f(A[i], F[i])
    end
    100 * sumabs(tmp) / length(A)
end

@time mape4(A,F)
  0.452273 seconds (20.00 M allocations: 343.323 MB, 9.80% gc time)
832.852597807525

@time mape4a(A,F)
  0.040240 seconds (7 allocations: 38.147 MB, 1.93% gc time)
832.852597807525

The for loop in mape4a() does not do 4 * 5 milion allocations, neither 
should do the loop in map!(). Is this possibly a bug ?

Thanks,
Jan

Dňa štvrtok, 22. októbra 2015 19:43:31 UTC+2 Glen O napísal(-a):
>
> I'm uncertain, but I think I may have figured out what's going on.
>
> The hint lies in the number of allocations - map! has 20 million 
> allocations, while broadcast! has just 5. So I had a look at how the two 
> functions are implemented.
>
> map! is implemented in perhaps the simplest way you can think of - for 
> i=1:length(A) dest[i]=f(A[i],B[i]); end - which means that it has to store 
> four values per iteration - i, A[i], B[i], and f(A[i],B[i]). Thus, 4 times 
> 5 million allocations.
>
> broadcast! is using a cache to store values, instead, and I believe it's 
> generating instructions using a macro instead of a regular loop, thus 
> avoiding the assignments for i. As such, it doesn't need to store anything 
> except for the initial caches, and after that it just overwrites the 
> existing values. Unfortunately, that's as much as I can figure out from 
> broadcast!, because it uses a lot of macros and a lot of relatively opaque 
> structure.
>
> I'm also not entirely sure how it avoids the assignments necessary in the 
> function call.
>
> On Friday, 23 October 2015 01:54:14 UTC+10, Ján Dolinský wrote:
>>
>> Hi,
>>
>> I am exploring Julia's map() and broadcast() functions. I did a simple 
>> implementation of MAPE (mean absolute percentage error) using broadcast() 
>> and map(). Interestingly, the difference in performance was huge.
>>
>> A = rand(5_000_000)
>> F = rand(5_000_000)
>>
>> _f(a,f) = (a - f) / a
>>
>> function mape3(A, F)
>> # A - actual target values
>> # F - forecasts (model estimations)
>>
>>   tmp = similar(A)
>>   broadcast!(_f, tmp, A, F)
>>   100 * sumabs(tmp) / length(A)
>>
>> end
>>
>> function mape4(A, F)
>> # A - actual target values
>> # F - forecasts (model estimations)
>>
>>   tmp = similar(A)
>>   map!(_f, tmp, A, F)
>>   100 * sumabs(tmp) / length(A)
>>
>> end
>>
>> @time mape3(A,F) # after JIT warm-up
>>   0.038686 seconds (8 allocations: 38.147 MB, 2.25% gc time)
>> 876.4813057521973
>>
>> @time mape4(A,F) # after JIT warm-up
>>   0.457771 seconds (20.00 M allocations: 343.323 MB, 11.29% gc time)
>> 876.4813057521973
>>
>> I wonder why map() is so much slower ?
>>
>> Thanks,
>> Jan
>>
>

Reply via email to