在 matlab 中高效操作大型非稀疏数组
Efficient manipulation of large, non-sparse arrays in matlab
我有一个包含 200
个元素的行向量 q
和另一个行向量 dij
,它是 pdist
函数的输出,当前 48216200
元素,但我希望能够更高。我想做的操作本质上是:
t=sum(q'*dij,2);
然而,由于它试图分配一个 200x48211290
数组,它抱怨说这需要 70GB 的内存。因此我这样做:
t = zeros(numel(q),1);
for i=1:numel(q)
qi = q(i);
factor = qi*dij;
t(i)=sum(factor);
end
但是,这需要太多时间。太多的时间,我的意思是它需要大约 36s
,这比 pdist
函数所需的时间长几个数量级。有没有一种方法可以在不显式分配这么多内存的情况下加快此操作?我在这里假设,如果第一种方法可以分配内存(作为向量操作),它会更快。
加法用乘法distributive property即可:
t = q'*sum(dij);
为了测试 Cris 在第一个 post 评论中所说的内容,我创建了 3 个“.m”文件,如下所示:
vec.m :
res=sum(sin(d.*q')./(d.*q'));
forloop.m
for i=1:200
res(i)=sum(sin(d.*q(i))./(d.*q(i)));
end
和test.m:
clc
clear all
d=rand(4e6,1);
q=rand(200,1);
res=zeros(1,200);
forloop;
vec;
forloop;
vec;
forloop;
vec;
然后我使用了 matlab 运行 和时间分析器,
结果非常令人惊讶! :
3 calls to forloop : ~10.5 S
3 call to vec : 15.5 S !!!
此外,当我将数据转换为单一数据时,结果是:
... forloop : 7.5 S
... vec : 8.5 S
我不确切知道为什么 for 循环在这些情况下更快,但是对于您的问题,您可以通过在循环中生成较少的变量并使用垂直向量来加快速度(我认为)。最后将您的数据转换为单个值:
q=single(rand(200,1));
...
我有一个包含 200
个元素的行向量 q
和另一个行向量 dij
,它是 pdist
函数的输出,当前 48216200
元素,但我希望能够更高。我想做的操作本质上是:
t=sum(q'*dij,2);
然而,由于它试图分配一个 200x48211290
数组,它抱怨说这需要 70GB 的内存。因此我这样做:
t = zeros(numel(q),1);
for i=1:numel(q)
qi = q(i);
factor = qi*dij;
t(i)=sum(factor);
end
但是,这需要太多时间。太多的时间,我的意思是它需要大约 36s
,这比 pdist
函数所需的时间长几个数量级。有没有一种方法可以在不显式分配这么多内存的情况下加快此操作?我在这里假设,如果第一种方法可以分配内存(作为向量操作),它会更快。
加法用乘法distributive property即可:
t = q'*sum(dij);
为了测试 Cris 在第一个 post 评论中所说的内容,我创建了 3 个“.m”文件,如下所示:
vec.m :
res=sum(sin(d.*q')./(d.*q'));
forloop.m
for i=1:200
res(i)=sum(sin(d.*q(i))./(d.*q(i)));
end
和test.m:
clc
clear all
d=rand(4e6,1);
q=rand(200,1);
res=zeros(1,200);
forloop;
vec;
forloop;
vec;
forloop;
vec;
然后我使用了 matlab 运行 和时间分析器, 结果非常令人惊讶! :
3 calls to forloop : ~10.5 S
3 call to vec : 15.5 S !!!
此外,当我将数据转换为单一数据时,结果是:
... forloop : 7.5 S
... vec : 8.5 S
我不确切知道为什么 for 循环在这些情况下更快,但是对于您的问题,您可以通过在循环中生成较少的变量并使用垂直向量来加快速度(我认为)。最后将您的数据转换为单个值:
q=single(rand(200,1));
...