Advantages of explicitly using "map" or "broadcast" wrappers?

For example, if I have four vectors A, B, C, and D, and my goal is to find the index of the rows with A>-10, B>15, C>500 and D>200.

In Matlab I can achieve that by doing the below:
Index1 = A>-10 && B>15 && C>500 && D>200

In comparison, I would have to write a more complex syntax in Julia as below:

Index1 = map(A, B, C, D) do a,b,c,d
        a>-10 && b>=15 && c>500 && d>200
end

I’m wondering why Julia is making it so complex? what is the advantage of doing it this way?

Thanks!

Wouldn’t explicit broadcast

julia> A = 1000randn(10);  B = 1000randn(10);  C = 1000randn(10);  D = 1000randn(10);

julia> mask = @. A > -10 && B > 15 && C > 500 && D > 200
10-element BitVector:
 0
 0
 0
 0
 0
 1
 0
 0
 0
 0

work as well?

5 Likes

Many thanks! As a former Matlab user, I find this one easier to understand.

It’s a bonus to learn of the @. thing :+1:

(also note that in matlab this kind of array masks is necessary to get not-crappy performance, but in julia it is often faster to just write out the for loop. Whether that is more or less clear than masks depends on the context)

4 Likes

You can do the same in Julia, and as a bonus, it is faster even in this vectorized form. But if you want to up your game, you can get it 4X faster in Julia with 4X less memory by writing a one-liner loop:

A, B, C, D = [1000randn(1000) for i=1:4]

using BenchmarkTools
@btime out = @. ($A > -10) & ($B > 15) & ($C > 500) & ($D > 200)
  2.556 μs (3 allocations: 4.41 KiB)

@btime [($A[i]>-10) & ($B[i]>15) & ($C[i]>500) & ($D[i]>200) for i=1:length($A)]
  775.962 ns (1 allocation: 1.06 KiB)

In MATLAB, for comparison:

A = 1000*randn(1000,1);  
B = 1000*randn(1000,1);  
C = 1000*randn(1000,1);  
D = 1000*randn(1000,1);

out = @() (A > -10) & (B > 15) & (C > 500) & (D > 200);
timeit(out)

ans =

   3.1057e-06
1 Like

Many thanks!

This thread is becoming very interesting. There are so many way of writing this code cleanly and fast!

Julia is truly amazing.

1 Like