For *
when you write a * 2
is not a broadcasting operation but vector times scalar multiplication, which is a valid operation in vector space, see https://en.wikipedia.org/wiki/Scalar_multiplication.
For +
when you write a + 1
you ask for addition of vector and scalar, which is not operation that is normally supported in vector spaces. You have to broadcast +
to achieve the desired result. You have a list of eight axioms that vector space must meet in https://en.wikipedia.org/wiki/Vector_space. Adding of scalar and vector is not one of them.
Regarding performance - on my laptop both operations (broadcasted and non broadcasted multiplication) have the same performance characteristic:
julia> using BenchmarkTools
julia> @benchmark $a * 2
BenchmarkTools.Trial: 2346 samples with 1 evaluation.
Range (min … max): 1.373 ms … 8.099 ms ┊ GC (min … max): 0.00% … 61.16%
Time (median): 1.513 ms ┊ GC (median): 0.00%
Time (mean ± σ): 2.127 ms ± 1.101 ms ┊ GC (mean ± σ): 19.42% ± 22.16%
█▆▄▃▂▁▁ ▁▁▁ ▃▂▁
███████▇██▇▇█████▇▆▇▇▅▅▆▆▅▅▅██████▆▆▇▅▆▆▄▅▅▅▃▅▄▃▅▅▅▅▄▄▃▃▃ █
1.37 ms Histogram: log(frequency) by time 5.99 ms <
Memory estimate: 7.63 MiB, allocs estimate: 2.
julia> @benchmark $a .* 2
BenchmarkTools.Trial: 2333 samples with 1 evaluation.
Range (min … max): 1.377 ms … 7.586 ms ┊ GC (min … max): 0.00% … 62.77%
Time (median): 1.528 ms ┊ GC (median): 0.00%
Time (mean ± σ): 2.137 ms ± 1.104 ms ┊ GC (mean ± σ): 19.25% ± 22.06%
█▆▄▃▃▁▁▁▁ ▁▂▁▁ ▄▂▁▁ ▁ ▁
█████████▇█████████▇▇▇▇▇▅▆▄▆██████▆▇▆▆▆▇▇▆▃▄▅▆▇▆▆▆▅▅▁▃▁▅▃ █
1.38 ms Histogram: log(frequency) by time 5.98 ms <
Memory estimate: 7.63 MiB, allocs estimate: 2.
Running @time
instead of using BenchmarkTools.jl is not reliable as single run of some operation can have a large variability of run time (e.g. your processor might be busy with some other tasks or GC can be triggered).