Is there a need to use the “.” for vector math when adding and multiplying?
a = [1 2 3]
b = [3 4 5]
# Which is better for performance? They both do the same thing.
c = 1/2 * a + b
d = 1/2 .* a .+ b
Is there a need to use the “.” for vector math when adding and multiplying?
a = [1 2 3]
b = [3 4 5]
# Which is better for performance? They both do the same thing.
c = 1/2 * a + b
d = 1/2 .* a .+ b
The second should be about 2x faster. The second will compile to roughly
d=Vector{Float64}(undef, length(a))
for i in eachindex(a,b)
d[i] = .5*a[i]+b[i]
end
while the first will use 2 loops and allocate an intermediate vector.
If you don’t want to have ot use lots of dots, you could write this as
@. d = 1/2 * a+b
(or d = @. 1/2 * a+b
if d
is not preallocated)
Awesome. Thank
And here I am after using Julia for quite a while now, not knowing that 1/2 .* a
is better than 1/2*a
… Always room for improvement.
Note that this only matters when a
is a collection, and the .
can be fused with another operation. 1/2 * a
will be just as fast as 1/2 .* a
. The only difference is if you add another operation that broadcasting can fuse.
You’re not saying that this:
c = 1/2 * a .+ b
will be as fast as this:
c = 1/2 .* a .+ b
are you?
No.
Basically in any expression with dots, you can imagine all dots on the same level being fused together into one element-wise function going over all involved iterables just once. It’s a syntax transformation basically. You can do the same if you write broadcast(f, iterables...)
but that’s not nice syntax
When is (*)(x::Real, y::AbstractArray)
not equivalent to its broadcasted version? Shouldn’t 1/2 * a .+ b
fuse automatically? I believe there are always cases where this shouldn’t be done, but for the standard number types this should be okay, no?
The problem is that broadcasting happens on the syntax level. When you write 1/2 *a .+b
it gets lowered to
temp1 = 1/2 *a
return broadcast(+, a, b)
The reason broadcasting needs to be explicit is that lowering happens before type inference, so decisions about broadcast fusing can’t depend on types.
That’s explained here: More Dots: Syntactic Loop Fusion in Julia
Thanks! I guess I read that already at the time, but forgot about it again.