Julia 向量化运算符

apo*_*sis 5 vector operator-overloading vectorization julia array-broadcasting

据我所知,在 Julia 中,大多数运算符都可以通过在其前面加上.. 然而我不明白为什么其中一些值得两种方式:

julia> a = rand(1_000_000);

julia> @time a*2;
  0.051112 seconds (183.93 k allocations: 17.849 MiB, 7.14% gc time, 89.16% compilation time)

julia> @time a*2;
  0.002070 seconds (2 allocations: 7.629 MiB)

julia> @time a.*2;
  0.026533 seconds (8.87 k allocations: 8.127 MiB, 93.23% compilation time)

julia> @time a.*2;
  0.001575 seconds (4 allocations: 7.630 MiB)

julia> a + 0.1;
ERROR: MethodError: no method matching +(::Vector{Float64}, ::Float64)
Run Code Online (Sandbox Code Playgroud)

为什么数组广播对 有效*但无效+

*是什么导致了和之间的性能/分配差异.*

Bog*_*ski 7

*您编写的a * 2不是广播运算而是向量乘标量乘法(这是向量空间中的有效运算)时,请参阅https://en.wikipedia.org/wiki/Scalar_multiplication

\n

因为+当您编写时,a + 1您要求添加向量和标量,这不是向量空间中通常支持的操作。您必须进行广播+才能达到预期的效果。您在https://en.wikipedia.org/wiki/Vector_space中列出了向量空间必须满足的八个公理。标量和向量的相加不是其中之一。

\n

关于性能 - 在我的笔记本电脑上,两种操作(广播和非广播乘法)具有相同的性能特征:

\n
julia> using BenchmarkTools\n\njulia> @benchmark $a * 2\nBenchmarkTools.Trial: 2346 samples with 1 evaluation.\n Range (min \xe2\x80\xa6 max):  1.373 ms \xe2\x80\xa6 8.099 ms  \xe2\x94\x8a GC (min \xe2\x80\xa6 max):  0.00% \xe2\x80\xa6 61.16%\n Time  (median):     1.513 ms             \xe2\x94\x8a GC (median):     0.00%\n Time  (mean \xc2\xb1 \xcf\x83):   2.127 ms \xc2\xb1 1.101 ms  \xe2\x94\x8a GC (mean \xc2\xb1 \xcf\x83):  19.42% \xc2\xb1 22.16%\n\n  \xe2\x96\x88\xe2\x96\x86\xe2\x96\x84\xe2\x96\x83\xe2\x96\x82\xe2\x96\x81\xe2\x96\x81      \xe2\x96\x81\xe2\x96\x81\xe2\x96\x81            \xe2\x96\x83\xe2\x96\x82\xe2\x96\x81\n  \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x87\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x86\xe2\x96\x87\xe2\x96\x87\xe2\x96\x85\xe2\x96\x85\xe2\x96\x86\xe2\x96\x86\xe2\x96\x85\xe2\x96\x85\xe2\x96\x85\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x86\xe2\x96\x86\xe2\x96\x87\xe2\x96\x85\xe2\x96\x86\xe2\x96\x86\xe2\x96\x84\xe2\x96\x85\xe2\x96\x85\xe2\x96\x85\xe2\x96\x83\xe2\x96\x85\xe2\x96\x84\xe2\x96\x83\xe2\x96\x85\xe2\x96\x85\xe2\x96\x85\xe2\x96\x85\xe2\x96\x84\xe2\x96\x84\xe2\x96\x83\xe2\x96\x83\xe2\x96\x83 \xe2\x96\x88\n  1.37 ms     Histogram: log(frequency) by time     5.99 ms <\n\n Memory estimate: 7.63 MiB, allocs estimate: 2.\n\njulia> @benchmark $a .* 2\nBenchmarkTools.Trial: 2333 samples with 1 evaluation.\n Range (min \xe2\x80\xa6 max):  1.377 ms \xe2\x80\xa6 7.586 ms  \xe2\x94\x8a GC (min \xe2\x80\xa6 max):  0.00% \xe2\x80\xa6 62.77%\n Time  (median):     1.528 ms             \xe2\x94\x8a GC (median):     0.00%\n Time  (mean \xc2\xb1 \xcf\x83):   2.137 ms \xc2\xb1 1.104 ms  \xe2\x94\x8a GC (mean \xc2\xb1 \xcf\x83):  19.25% \xc2\xb1 22.06%\n\n  \xe2\x96\x88\xe2\x96\x86\xe2\x96\x84\xe2\x96\x83\xe2\x96\x83\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81   \xe2\x96\x81\xe2\x96\x82\xe2\x96\x81\xe2\x96\x81            \xe2\x96\x84\xe2\x96\x82\xe2\x96\x81\xe2\x96\x81 \xe2\x96\x81                        \xe2\x96\x81\n  \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x87\xe2\x96\x87\xe2\x96\x87\xe2\x96\x87\xe2\x96\x85\xe2\x96\x86\xe2\x96\x84\xe2\x96\x86\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x86\xe2\x96\x87\xe2\x96\x86\xe2\x96\x86\xe2\x96\x86\xe2\x96\x87\xe2\x96\x87\xe2\x96\x86\xe2\x96\x83\xe2\x96\x84\xe2\x96\x85\xe2\x96\x86\xe2\x96\x87\xe2\x96\x86\xe2\x96\x86\xe2\x96\x86\xe2\x96\x85\xe2\x96\x85\xe2\x96\x81\xe2\x96\x83\xe2\x96\x81\xe2\x96\x85\xe2\x96\x83 \xe2\x96\x88\n  1.38 ms     Histogram: log(frequency) by time     5.98 ms <\n\n Memory estimate: 7.63 MiB, allocs estimate: 2.\n
Run Code Online (Sandbox Code Playgroud)\n

运行@time而不是使用 BenchmarkTools.jl 并不可靠,因为某些操作的单次运行可能会产生很大的运行时间变化(例如,您的处理器可能正忙于某些其他任务或可能会触发 GC)。

\n