2012-11-19 124 views
2

我已经在matlab中编写了一个小循环来生成一个随机NxN矩阵。循环是for循环中的计算速度

tic 
for i=1:10000 
    u=rand(1,10000); 
    tau(i,:)=d.*(u(1,:)-0.5); 
end 
toc 

我第一次尝试循环程序只有一次,

u=rand(1,10000); 
    tau=d.*(u(1,:)-0.5); 

这给了我头在0.000169秒。我认为循环将花费大约1.69s。它没有,它花了555.018280s与球迷疯狂。

有没有
a)速度与迭代次数没有线性关系的原因是什么?
b)原因为什么它需要所以更长的时间做很多次例程
c)一种方法来加速这一个(我实际上想生成更大的矩阵),例如一个更好的循环或方式比如说给我一个同样类型的1'000'000x1'000'000的矩阵?

+2

尝试预先分配'tau'。 – Junuxx

+1

有一个名为“加速MATLAB应用程序”的网络研讨会。有关于大矩阵的一些信息以及如何处理它们。 https://www.mathworks.com/company/events/webinars/wbnr49643.html?id=49643&p1=961666025&p2=961666043 – HebeleHododo

回答

7

你必须先预分配的矩阵tau,即

tau = zeros(10000,10000); 

否则MATLAB将继续在地区哪里有足够的可用内存(重新分配它=>找到足够自由的空间区域+硬拷贝)。

一般情况下,你会获得更好的性能矢量化的全过程:

u=rand(10000,10000); 
tau=d.*(u-0.5); 

编辑:首先,听罗迪的在下面的评论中明智的建议。 (在任何情况下,我想假设rand(a,b)将运行比a连续执行rand(1,b)快一点)。

+1

更好地防止双内存分配(注意,“u”是800兆字节):'tau = d *(兰特(10000)-0.5)'。或者,如果size(d)== [1 10000]',使用'tau = bsxfun(@times,d,rand(10000)-0.5)'。峰值内存仍然相同,但是,在分配之后,释放了800MB的1.6GB峰值。或者:之后只需发出一个清晰的u。 –

+0

@RodyOldenhuis因此,重点是做'tau = d。*(rand(10000,10000)-0.5);',对吗?顺便说一句,是'bsxfun'版本更快吗? – Acorbe

+0

可能不会更快,但它适用于'd'的大小只适用于循环解决方案('size(d)== [1 10000]') –

0

一个明显的可能性是内存访问量。测试循环的内存可能完全处于高速缓存中,但由完整循环写入的内存需要大量内存访问。

这是一个可测试的假设:编写整个矩阵的时间,而不是算术。

如果我理解Matlab索引,可能会更快地切换维度,以便写入同一列中的块而不是同一行中的块。将u转换为循环外的列向量也可能有所帮助。一般来说,应尽可能按记忆顺序进行大矩阵访问。