【问题标题】:Armadillo matrix transpose犰狳矩阵转置
【发布时间】:2015-11-05 13:44:32
【问题描述】:

我有一个巨大的 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 ) 是一个 void 函数,所以我必须先创建我的矩阵的副本,然后才能计算新的w

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

但这当然不是我们想要的结果,因为我需要一个完整的矩阵副本,而我一开始就想避免这种情况(RAM 问题!)。 那么,如何以高效(=快速且低内存要求)的方式对矩阵进行转置以计算新的w

如果我像 in 那样明智地做到这一点

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;

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

【问题讨论】:

    标签: c++ matrix transpose armadillo


    【解决方案1】:

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

    如果您之后不需要将矩阵恢复为未转置的形式,则该问题的一个简单解决方案是转置整个方程: w = w - A A^T w &lt;==&gt; 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 向量只是一维设置为一的矩阵。无论如何,这些考虑在向量级别上比在矩阵级别上要严格得多。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 也许我应该补充一点,我的矩阵 A 的行数 m 远大于列数 n。如果我在元素方面这样做,我需要两个从 0 到 m 的 for 循环,我猜这远非最佳。
      • 如果矩阵以行主要顺序存储,那么与先转置相比,元素明智绝对是更快的方式。如果矩阵按列主要顺序存储,则任何一种方式都有缺陷,而另一种方式更好,但您简单地尝试做的事情仍然远不如正确地做。
      • 矩阵存储在列主序中。在这种情况下你有什么建议? “做对了”是什么意思?
      • 你能转换成行大订单吗?如果不是,是否是物理转置(因此转置将按列主要顺序排列,相当于原始的行主要顺序排列)?正确地做到这一点显然涉及只有一个副本并仅按一个顺序访问它。在访问之前转换为有效的行主要订单可能是值得的。
      • 不幸的是,犰狳文档没有提到转换为行主要顺序。据我所知,转置矩阵也是列主要顺序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多