【问题标题】:Making a for-loop in Matlab faster by using arrayfun?使用 arrayfun 使 Matlab 中的 for 循环更快?
【发布时间】:2011-06-21 10:08:45
【问题描述】:

目前我有以下部分代码:

for i = 2:N-1
  res(i) = k(i)/m(i)*x(i-1) -(c(i)+c(i+1))/m(i)*x(N+i) +e(i+1)/m(i)*x(i+1);
end

其中变量 k、m、c 和 e 是大小为 N 的向量,x 是大小为 2*N 的向量。有没有什么方法可以使用 arrayfun 之类的东西更快地做到这一点!?我想不通:(我特别想通过稍后在 GPU 上运行来使其更快,因此,arrayfun 也会有帮助,因为 matlab 不支持并行化 for 循环,我不想买夹克包裹... 非常感谢!

【问题讨论】:

    标签: arrays matlab parallel-processing


    【解决方案1】:

    您不必使用arrayfun。如果使用一些智能索引,它就可以工作:

        clear all
    
        N=20;
        k=rand(N,1);
        m=rand(N,1);
        c=rand(N,1);
        e=rand(N,1);
        x=rand(2*N,1);
    
        % for-based implementation
        %Watch out, you are not filling the first element of forres!
        forres=zeros(N-1,1); %Initialize array first to gain some speed.
        for i = 2:N-1
          forres(i) = k(i)/m(i)*x(i-1) -(c(i)+c(i+1))/m(i)*x(N+i) +e(i+1)/m(i)*x(i+1);
        end
    
        %vectorized implementation
        parres=k(2:N-1)./m(2:N-1).*x(1:N-2) -(c(2:N-1)+c(3:N))./m(2:N-1).*x(N+2:2*N-1) +e(3:N)./m(2:N-1).*x(3:N);
    
        %compare results; strip the first element from forres
        difference=forres(2:end)-parres %#ok<NOPTS>
    

    【讨论】:

    • 我假设 (x(i)-x(i-1))^3 到达 (x(2:N-1)-x(1:N-2)).^3?
    • 是的,你明白了。策略是用 for 循环中的索引范围替换运行索引i。即对于1:Ni 变为1:Ni+1 变为1+1:N+1
    • 相同的索引“技巧”基本上是使用arrayfun所需要的。在 GPU 上使用 arrayfun 通常比一系列矢量化操作快得多。
    【解决方案2】:

    首先,MATLAB 通过PARFOR 支持并行 for 循环。但是,这并没有太多机会加速这种计算,因为与您正在读取和写入的数据量相比,计算量很小。

    要为 GPUArray "arrayfun" 重构事物,您需要使循环体中的所有数组引用都引用循环迭代,并使循环在整个范围内运行。您应该能够通过偏移一些数组并使用虚拟值填充来做到这一点。例如,您可以在所有数组前面加上NaN,并将x(i-1) 替换为新变量x_1 = [x(2:N) NaN]

    【讨论】:

    • 好的,我想尝试一下:但是我在这里看到的问题是,当创建这么多“虚拟”变量时,我可能很快就会用完内存,复制到 GPU并且对所有不同变量的内存访问可能会很慢!
    • 你说的很对,你可能有问题。不幸的是,arrayfun 在它允许的范围内非常不灵活。如果你真的想要极致的速度,你可以编写少量的 CUDA 代码并在 MATLAB 中使用 parallel.gpu.CUDAKernel 来执行它。
    • 是的,谢谢,我已经考虑过这个问题,但只是想要一个“快速”的解决方案,而 user599884 的建议帮助我创建了这样一个快速的解决方案,使 for 循环更快。与在 GPU 上运行的 user599884 解决方案相比,您是否认为 CUDA 编写的代码真的会加快速度,只需将x = gpuArray(x), k=gpuArray(k) 等放在...
    • 是的,在 GPU 上,arrayfun 或手写内核通常会击败矢量化代码。您可以通过忽略索引偏移并无论如何使用 arrayfun 来粗略估计多少。
    • Edric,您是否认为将其完全作为 CUDA-mex-file 来完成,它可以完成 mex 文件中的所有操作(例如将数据复制到 GPU 等...)或者是 PTX 内核充足的?!我想知道这两种变体之间是否会有很大的不同。
    猜你喜欢
    • 2012-04-26
    • 2016-05-30
    • 1970-01-01
    • 2015-04-20
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2020-02-23
    相关资源
    最近更新 更多