每個矩陣I具有3維陣列朱莉婭乘以沿着昏暗
x = rand(6,6,2^10)
我想由矢量乘以沿着第三維中的每個矩陣。是否有一個更清潔的方式來做到這一點比:
y = rand(6,1)
z = zeros(6,1,2^10)
for i in 1:2^10
z[:,:,i] = x[:,:,i] * y
end
每個矩陣I具有3維陣列朱莉婭乘以沿着昏暗
x = rand(6,6,2^10)
我想由矢量乘以沿着第三維中的每個矩陣。是否有一個更清潔的方式來做到這一點比:
y = rand(6,1)
z = zeros(6,1,2^10)
for i in 1:2^10
z[:,:,i] = x[:,:,i] * y
end
如果使用矩陣工作,也可適當將x
視爲矩陣的向量而不是3D陣列。那麼你可以做
x = [rand(6,6) for _ in 1:2^10]
y = [rand(6)]
z = x .* y
z
現在是一個載體的載體。
如果z
預先分配,這將是
z .= x .* y
而且,如果你想它的真快,使用這顯示在我的電腦上10倍的加速比StaticArrays
using StaticArrays
x = [@SMatrix rand(6, 6) for _ in 1:2^10]
y = [@SVector rand(6)]
z = x .* y
載體,運行在12us。
mapslices(i->i*y, x, (1,2))
也許是「清潔」,但它會慢一些。
讀爲:將函數「times by y」應用於前兩個維度的每個切片。
function tst(x,y)
z = zeros(6,1,2^10)
for i in 1:2^10
z[:,:,i] = x[:,:,i] * y
end
return z
end
tst2(x,y) = mapslices(i->i*y, x, (1,2))
time tst(x,y);
0.002152秒(4.10ķ分配:624.266 KB)
@time tst2(x,y);
0.005720秒(13.36ķ分配:466.969 KB)
我會同意這個解決方案更「乾淨」,但另一方面我也不清楚發生了什麼。 –
也許...雖然我會同意@DNF,如果你只是想迭代這個維度,那麼矩陣的矢量將更具可讀性。 –
sum(x.*y',2)
是一個簡潔的解決方案。
它也具有良好的速度和記憶性能。訣竅是將矩陣向量乘法看作由向量元素縮放的矩陣列的線性組合。我們對x [:,i:]使用相同的尺度y [i],而不是對矩陣x [:,:i]做每個線性組合。在代碼:
const x = rand(6,6,2^10);
const y = rand(6,1);
function tst(x,y)
z = zeros(6,1,2^10)
for i in 1:2^10
z[:,:,i] = x[:,:,i]*y
end
return z
end
tst2(x,y) = mapslices(i->i*y,x,(1,2))
tst3(x,y) = sum(x.*y',2)
標杆得出:使用
julia> using BenchmarkTools
julia> z = tst(x,y); z2 = tst2(x,y); z3 = tst3(x,y);
julia> @benchmark tst(x,y)
BenchmarkTools.Trial:
memory estimate: 688.11 KiB
allocs estimate: 8196
--------------
median time: 759.545 μs (0.00% GC)
samples: 6068
julia> @benchmark tst2(x,y)
BenchmarkTools.Trial:
memory estimate: 426.81 KiB
allocs estimate: 10798
--------------
median time: 1.634 ms (0.00% GC)
samples: 2869
julia> @benchmark tst3(x,y)
BenchmarkTools.Trial:
memory estimate: 336.41 KiB
allocs estimate: 12
--------------
median time: 114.060 μs (0.00% GC)
samples: 10000
所以tst3
sum
具有更好的性能(〜7倍以上tst
和15X〜在tst2
)。
按@DNF的建議使用StaticArrays
也是一種選擇,並且將它與此處的解決方案進行比較將會很好。
'reducedim(+,x。* y',2)'和'sum(x。* y',2)'是否有區別? – DNF
不是。嗯,是的,'sum'比較好。我將編輯以反映這一點。謝謝。 –
順便說一句,要真正優化,將索引的順序改爲(6,2^10,6),並使用循環和'@ inbounds'手動編碼操作可以獲得另一個** 10x **。這是爲了使內存佈局和索引計算更容易。 –
'_'如何在理解中工作? –
這只是一個虛擬變量。例如,我可以使用'i',但通常讓'_'表示一個一次性使用的變量,它不被進一步使用,並且哪個名稱不重要。 – DNF