在 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)); 
...