我有一个三维数组
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
答案 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
也是一个选项,将它与此处的解决方案进行比较会很好。