2017-05-05 68 views
6

每個矩陣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 

回答

6

如果使用矩陣工作,也可適當將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。

+0

'_'如何在理解中工作? –

+1

這只是一個虛擬變量。例如,我可以使用'i',但通常讓'_'表示一個一次性使用的變量,它不被進一步使用,並且哪個名稱不重要。 – DNF

7

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)

+0

我會同意這個解決方案更「乾淨」,但另一方面我也不清楚發生了什麼。 –

+0

也許...雖然我會同意@DNF,如果你只是想迭代這個維度,那麼矩陣的矢量將更具可讀性。 –

3

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 

所以tst3sum具有更好的性能(〜7倍以上tst和15X〜在tst2)。

按@DNF的建議使用StaticArrays也是一種選擇,並且將它與此處的解決方案進行比較將會很好。

+1

'reducedim(+,x。* y',2)'和'sum(x。* y',2)'是否有區別? – DNF

+0

不是。嗯,是的,'sum'比較好。我將編輯以反映這一點。謝謝。 –

+0

順便說一句,要真正優化,將索引的順序改爲(6,2^10,6),並使用循環和'@ inbounds'手動編碼操作可以獲得另一個** 10x **。這是爲了使內存佈局和索引計算更容易。 –