犰狳矩阵转置

Armadillo matrix transpose

我有一个巨大的 m*n 矩阵 A(其中行数 m 远大于列数 n),它作为 armadillo mat 存储在我的 C++ 程序中类型。现在我有一个向量 w,我必须为其计算 w=w-A*A^T*w,其中 A^T 表示矩阵 A 的转置。

由于矩阵 A 非常大并且消耗大量内存,通常使用犰狳 w=w-A*A.t()*w 的快速方法不起作用,因为犰狳在这种情况下会消耗大量内存(参见 github).他们解决这个问题的方法是引入函数inplace_trans( A, method ),它可以使用消耗更少内存但需要更多时间的方法"lowmem"。

我现在的问题是,inplace_trans( A, method ) 是一个空函数,所以我必须先创建矩阵的副本,然后才能计算新的 w:

mat Q = A;
inplace_trans(Q, 'lowmmem');
w=w-A*Q*w;

然而,这当然不是想要的结果,因为我需要矩阵的完整副本,而我一开始就想避免这种情况(RAM 问题!)。 那么,我怎样才能以高效(=快速和低内存要求)的方式获得矩阵的转置以计算新的 w?

如果我像

那样明智地做到这一点
mat A(m,n); //huge matrix, initialized before
vec temp(m);
temp.fill(0.0);
for (unsigned long int ii=0; ii<m; ii++){

    for (unsigned long int ll=0; ll<m; ll++){
        temp(ii)+=dot(A.row(ii),A.row(ll))*w(ll);
    }
}
w=w-temp;

我必须对行数 m 进行两次迭代,这是非常昂贵的。

编辑: 目前最快的方法如下:

vec temp(m);
inplace_trans(A, "lowmem");
temp = A * w;
inplace_trans(A, "lowmem");
temp = A * temp;

我必须转置矩阵两次,因为之后我需要将它恢复到原来的状态。我不敢相信这应该是最快的方法,因为它需要很多操作,恕我直言。

您可以直接计算 A*A.t()*w,工作量更少,缓存未命中率也大大降低,如果逐个元素计算,则只需 A 的一个副本。我不知道犰狳给了你什么功能来帮助你快速完成。但是简单地访问矩阵的行应该足以使它在不使用过多内存的情况下变得实用。

在您的编辑中,您已经正确地暗示,从复杂性的角度来看,执行两次 matrix-vector 乘法当然更可取,而不是先计算 A*A.t() 然后将结果应用于w。但是,您的问题似乎是您必须转置矩阵两次。

如果您之后不需要将矩阵恢复为未转置形式,则该问题的一个简单解决方案是转置整个方程: w = w - A A^T w <==> w^T = w^T - w^T A A^T。在这种情况下,您可以先应用 A,然后再应用 A.t()。如果你能以某种方式将 w 定义为一个行向量,那么这将简单地等于

vec temp = w * A;
inplace_trans(A, "lowmem");
temp = temp * A;
w -= temp;

从概念上讲,行向量和列向量之间的存储应该没有区别,元素在内存中应该都是连续的。您将不得不看一下犰狳在行向量和列向量之间产生的显着差异,但是 afaik 向量只是一维设置为一的矩阵。无论如何,这种考虑在向量级别上比在矩阵级别上要宽松得多。