我正在开发一个项目,我需要在这个项目中计算大量的内部产品。我知道我们应该总是尝试在matlab中对操作进行矢量化,但我不知道该怎么做...
假设我们有两个大小为A
的{{1}}和B
矩阵,其中N x d
是要在N
维中计算的内积的数量。
使用for循环很容易实现,但我怀疑存在更有效的方法。 for循环实现可能如下所示:
d
有没有人有想法如何对此进行矢量化?我想innerprods=zeros(N,1);
for i=1:N
innerprods(i)=A(i,:)*B(i,:)';
end
应该在某个时候发挥作用,但我无法弄清楚如何使用它...
提前致谢!
答案 0 :(得分:5)
简单来说:
sum(A.*B,2)
一个简单的测试(R2013a WinVista 32bit Core duo):
N = 8e3;
A = rand(N);
B = rand(N);
tic
out = zeros(N,1);
for ii = 1:N
out(ii) = A(ii,:)*B(ii,:)';
end
toc
tic
out2 = sum(A.*B,2);
toc
all(out-out2 < 1e5*eps) % note difference in precision
时报
loop 5.6 sec
multsum 0.8 sec
Avg time loop: 2.00906 seconds
Avg time multSum: 0.18114 seconds
Avg time bsxfun: 0.18203 seconds
Avg time reshapeMultSum: 0.18088 seconds
主要外卖点:
bsxfun()
完全冗余,虽然开销不大(预期); sum(A.*B,2)
。测试套件(100次试验的平均时间,固定矩阵大小8e3,结果等于1e5 * eps):
N = 8e3;
A = rand(N);
B = rand(N);
tic
for r = 1:100
out = zeros(N,1);
for ii = 1:N
out(ii) = A(ii,:)*B(ii,:)';
end
end
sprintf('Avg time loop: %.5f seconds', toc/100)
tic
for r = 1:100; out2 = sum(A.*B,2); end
sprintf('Avg time multSum: %.5f seconds', toc/100)
tic
for r = 1:100; out3 = sum(reshape(bsxfun(@times,A(:),B(:)),N,N),2); end
sprintf('Avg time bsxfun: %.5f seconds', toc/100)
tic
for r = 1:100; out4 = sum(reshape(A(:).*B(:),N,N),2); end
sprintf('Avg time reshapeMultSum: %.5f seconds', toc/100)
答案 1 :(得分:2)
您对bsxfun
的怀疑是完全合理的!您可以使用以下带有bsxfun
的单行和良好的旧colon operator来有效地计算内部产品:
innerprods=sum(reshape(bsxfun(@times,A(:),B(:)),N,d),2);
有关此处发生的事情的更详细说明:
bsxfun(@times,A(:),B(:)) --> element-wise product, returns Nd x 1 vector
reshape( ^^^ , N, d) --> reshape into N x d matrix
sum( ^^^ , 2) --> sum over columns to get N x 1 vector
编辑:我做了一些时间来了解性能差异。我使用matlab R2010b(不要问......)。该图显示了在您的问题中使用循环的一些实证结果以及我建议的N=500
和不同维数的单线程。使用循环比使用bsxfun
的方法慢2到8倍。由于更好的并行化,matlab的较新版本的速度差异可能更大。