朱莉娅将每个矩阵乘以暗淡

时间:2017-05-05 09:45:06

标签: julia matrix-multiplication

我有一个三维数组

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

3 个答案:

答案 0 :(得分:7)

mapslices(i->i*y, x, (1,2))可能是"更清洁"但它会慢一些。

读作:应用函数"乘以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 k分配:624.266 KB)

@time tst2(x,y);   0.005720秒(13.36 k分配:466.969 KB)

答案 1 :(得分:7)

如果您正在处理矩阵,可能需要将x视为矩阵向量而不是3D数组。然后你可以做

x = [rand(6,6) for _ in 1:2^10]
y = [rand(6)]
z = x .* y

z现在是矢量的载体。

如果预先分配z,那将是

z .= x .* y

而且,如果你真的想要它,请使用StaticArrays

的向量
using StaticArrays

x = [@SMatrix rand(6, 6) for _ in 1:2^10]
y = [@SVector rand(6)]
z = x .* y

这显示我的计算机上的速度提高了10倍,运行时间为12us。

答案 2 :(得分:4)

sum(x.*y',2)是一个简洁的简洁解决方案。

它还具有良好的速度和内存属性。诀窍是将矩阵向量乘法视为由向量元素缩放的矩阵列的线性组合。不是对矩阵x [:,:,i]进行每个线性组合,而是对x [:,i,:]使用相同的比例y [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的{​​{1}}具有更好的效果(比sum高约7倍,比tst高约15倍。)

根据@DNF的建议使用tst2也是一个选项,将它与此处的解决方案进行比较会很好。