我了解到,在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)阵列广播为什么适用于*而不适用于+
是什么驱动了*和.*在性能/分配上的差异?
发布于 2022-06-24 17:29:32
对于编写*时,a * 2不是广播操作,而是向量乘以标量乘法,这是向量空间中的有效操作,请参见https://en.wikipedia.org/wiki/Scalar_multiplication。
对于+,当您编写a + 1时,您要求添加向量和标量,这不是通常在向量空间中支持的操作。您必须广播+才能达到预期的结果。在https://en.wikipedia.org/wiki/Vector_space中,向量空间必须满足八个公理。标量和向量的加法不是其中之一。
关于性能-在我的笔记本电脑上,两种操作(广播乘法和非广播乘法)具有相同的性能特性:
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.运行@time而不是使用BenchmarkTools.jl是不可靠的,因为某些操作的一次运行可能有很大的运行时变异性(例如,您的处理器可能忙于其他一些任务,或者GC可能被触发)。
https://stackoverflow.com/questions/72747183
复制相似问题