Arrays 使用arrayfun在Matlab中快速生成for循环?
目前,我有以下代码部分:Arrays 使用arrayfun在Matlab中快速生成for循环?,arrays,matlab,parallel-processing,Arrays,Matlab,Parallel Processing,目前,我有以下代码部分: 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 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不支持循环的并行化,我不想买夹克包。。。
非常感谢!首先,MATLAB确实支持并行for loops via。但是,这不太可能加快这种计算,因为与您正在读取和写入的数据量相比,计算量很小
为GPUArray“”重新构造内容的步骤,您需要使循环体中的所有数组引用都引用循环,并使循环在整个范围内运行。您应该能够通过偏移一些数组并使用伪值填充来实现这一点。例如,您可以使用
NaN
预先填充所有数组,并替换x(i-1)
使用一个新变量x_1=[x(2:N)NaN]
您不必使用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>
全部清除
N=20;
k=兰特(N,1);
m=兰特(N,1);
c=兰特(N,1);
e=兰特(N,1);
x=兰特(2*N,1);
%基于对象的实现
%小心,你不是在填充forres的第一个元素!
forres=0(N-1,1);%首先初始化数组以获得一些速度。
对于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);
结束
%矢量化实现
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);
%比较结果;从forres中剥离第一个元素
差异=力量(2:结束)-招架%#确定
我假设一个(x(I)-x(I-1))^3
到达(x(2:N-1)-x(1:N-2))。^3
?是的,你得到了。策略是用for循环中的索引范围替换运行索引I
。即对于1:N
,I
变为1:N
,I+1
变为1+1“把戏"基本上都是使用arrayfun
所需的。在GPU上使用arrayfun
通常比一系列矢量化操作快得多。好吧,我想试试:但我在这里看到的问题是,当创建这么多“虚拟”变量时,我可能很快就会耗尽内存,而且,复制到GPU的速度会更快对所有不同变量的内存访问可能会非常慢!你是对的,你可能会遇到问题。不幸的是,arrayfun在它允许的范围内非常不灵活。如果你真的想要最高的速度,你可以编写少量的CUDA代码,并使用MATLAB中的parallel.gpu.CUDAKernel来执行它。是的,谢谢,我已经考虑过这一点,但只是想要一个“快速”的解决方案以及user599884的建议,帮助我创建了这样一个快速的解决方案,使for循环更快。你认为CUDA编写的代码真的会比GPU上运行的user599884解决方案更快吗?只需简单地将x=gpuArray(x),k=gpuArray(k)
等等。是的,在GPU上,arrayfun或手工编写的内核通常比矢量化的代码要好。忽略索引偏移量并使用arrayfun来查看速度有多快,您可以粗略估计速度有多快。Edric,您认为完全像CUDA mex文件那样做也值得吗(比如将数据复制到GPU等)或者一个PTX内核就足够了吗?!我想知道这两个变体之间是否会有很大的区别。