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)
为什么数组广播对 有效*但无效+?
*是什么导致了和之间的性能/分配差异.*?
当*您编写的a * 2不是广播运算而是向量乘标量乘法(这是向量空间中的有效运算)时,请参阅https://en.wikipedia.org/wiki/Scalar_multiplication。
因为+当您编写时,a + 1您要求添加向量和标量,这不是向量空间中通常支持的操作。您必须进行广播+才能达到预期的效果。您在https://en.wikipedia.org/wiki/Vector_space中列出了向量空间必须满足的八个公理。标量和向量的相加不是其中之一。
关于性能 - 在我的笔记本电脑上,两种操作(广播和非广播乘法)具有相同的性能特征:
\njulia> 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.\nRun Code Online (Sandbox Code Playgroud)\n运行@time而不是使用 BenchmarkTools.jl 并不可靠,因为某些操作的单次运行可能会产生很大的运行时间变化(例如,您的处理器可能正忙于某些其他任务或可能会触发 GC)。