Performance 有可能加快这个MATLAB脚本的速度吗?

Performance 有可能加快这个MATLAB脚本的速度吗?,performance,matlab,matrix,Performance,Matlab,Matrix,我遇到了一些性能问题,因此我想加速那些运行缓慢的脚本。但是我没有更多的关于如何加速它们的想法。因为我发现我经常被索引阻塞。我发现抽象思维对我来说很难 剧本是 tic, n = 1000; d = 500; X = rand(n, d); R = rand(n, n); F = zeros(d, d); for i=1:n for j=1:n F = F + R(i,j)* ((X(i,:)-X(j,:)

我遇到了一些性能问题,因此我想加速那些运行缓慢的脚本。但是我没有更多的关于如何加速它们的想法。因为我发现我经常被索引阻塞。我发现抽象思维对我来说很难

剧本是

    tic,
    n = 1000;
    d = 500;
    X = rand(n, d);
    R = rand(n, n);
    F = zeros(d, d);
    for i=1:n
        for j=1:n
           F = F + R(i,j)* ((X(i,:)-X(j,:))' * (X(i,:)-X(j,:)));
        end
    end
    toc
讨论和解决方案代码 这里可以推荐一些使用
bsxfun
的方法。另外,请继续阅读,了解如何在这样的问题上获得
30x+
加速

方法#1(原始向量化方法)

为了适应
X
行之间的两种减法运算以及随后的元素级乘法运算,基于
bsxfun
的简单方法将产生一个4D中间数组,它将对应于
((X(i,:)-X(j,:)”*(X(i,:)-X(j,:)
)。在那之后,需要乘以
R
得到最终输出
F
。这将如下面所示实现-

v1 = bsxfun(@minus,X,permute(X,[3 2 1]));
v2 = bsxfun(@times,permute(v1,[1 3 2]),permute(v1,[1 3 4 2]));
F = reshape(R(:).'*reshape(v2,[],d^2),d,[]);
方法#2(不是那么天真的矢量化方法)

前面提到的方法进入4D,这可能会减慢速度。因此,您可以通过重塑形状将中间数据保留到3D。下面列出了这一点-

sub1 = bsxfun(@minus,X,permute(X,[3 2 1]));
sub1_2d = reshape(permute(sub1,[1 3 2]),n^2,[])
mult1 = bsxfun(@times,sub1_2d,permute(sub1_2d,[1 3 2]))
F = reshape(R(:).'*reshape(mult1,[],d^2),d,[])
方法#3(混合方法)

现在,您可以基于方法#2(
矢量化减法
+
循环乘法
)创建一个混合方法。这种方法的好处是,它使用
快速矩阵乘法
来执行乘法,并将复杂性从早期的O(n^2)降低到O(n),这将使它更加高效。感谢@Dev iL提出这个想法!这是密码-

sub1 = bsxfun(@minus,X,permute(X,[3 2 1]));
sub1 = bsxfun(@times,sub1,permute(sqrt(R),[1 3 2]));

F = zeros(d);
for k = 1:size(sub1,3)
    blk = sub1(:,:,k);    
    F = F + blk.'*blk;
end

标杆管理 比较原始方法和方法3的基准代码

运行时结果

------------------------------ With Original Approach
Elapsed time is 29.728571 seconds.
------------------------------ With Proposed Approach #3
Elapsed time is 0.839726 seconds.

那么,谁准备好进行30x+加速了

好吧,你也许可以按照Divakar的建议去做,但要以“分块”的方式。这样的话,外部仍会有2个
for
循环,但实际计算将使用更高效的
bsxfun
完成。此外,如果您不需要双精度的
double
,可以尝试将矩阵转换为更小的数据类型(例如
single
)-这也有助于解决内存问题…@mining查看刚刚添加的方法#3?此外,如果精度下降不会影响您,则可以研究转换为
单个
。@Dev-iL谢谢!实现了这一点,似乎它给了一个巨大的加速!不客气,我很高兴知道我的想法不仅对我有意义:)。更重要的是,从这个答案中的
bsxfun
deep magic可以学到很多东西。@mining Awesome!事实上,我从这个问题中学到了很多,所以也谢谢你把它带到Stackoverflow!嗯,这看起来很熟悉。你到底在实施什么?也许我们可以用一些数学来加快速度。嗨,@knedlsepp,我正在尝试实现这篇论文。
------------------------------ With Original Approach
Elapsed time is 29.728571 seconds.
------------------------------ With Proposed Approach #3
Elapsed time is 0.839726 seconds.