【问题标题】:vector * matrix product efficiency issue向量*矩阵乘积效率问题
【发布时间】:2014-11-06 10:42:30
【问题描述】:

就像 Z boson recommended 一样,我使用列主矩阵格式以避免必须使用点积。不过,在将向量与矩阵相乘时,我看不到避免这种情况的可行方法。矩阵乘法技巧需要有效地提取行(或列,如果我们转置产品)。因此,为了将向量乘以矩阵,我们转置:

(b * A)^T = A^T * b^T

A是矩阵,b是行向量,经过转置后变成列向量。它的行只是单个标量,向量 * 矩阵乘积实现成为(非转置)矩阵Ab 列的点积的低效实现。有没有办法避免执行这些点积?我认为可以做到这一点的唯一方法是行提取,这对于列主矩阵格式效率低下。

【问题讨论】:

  • 这个问题比较适合programmers.stackexchange.com
  • @Claptrap 为什么?我愿意改进/改变问题。
  • @Claptrap:我不确定为什么程序员会更适合...
  • 你不能交换循环嵌套吗? (即保持N个部分和,而不是顺序计算每个完整的输出值)。
  • @OliCharlesworth 只是不要说数学家。他们可能只是翻白眼,对我们这些可怜的外行/杂工说些听不懂的话。

标签: c++ c matrix sse simd


【解决方案1】:

这可以从关于这个的原始帖子中理解(我在 SO 上的第一篇文章) efficient-4x4-matrix-vector-multiplication-with-sse-horizontal-add-and-dot-prod 。其余的讨论适用于 4x4 矩阵。

这里有两种方法来做矩阵时间向量(v = Mu,其中 v 和 u 是列向量)

method 1) v1 = dot(row1, u), v2 = dot(row2, u), v3 = dot(row3, u), v4 = dot(row4, u)
method 2) v = u1*col1 + u2*col2 + u3*col3 + u4*col4.

第一种方法在数学课上更熟悉,而第二种方法对 SIMD 计算机更有效。第二种方法使用矢量化数学(如 numpy),例如

u1*col1 = (u1x*col1x, u1y*col1y, u1z*col1z, u1w*col1w).

现在让我们看看向量时间矩阵(v = uM,其中 v 和 u 是行向量)

method 1) v1 = dot(col1, u), v2 = dot(col2, u), v3 = dot(col3, u), v4 = dot(col4, u)
method 2) v = u1*row1 + u2*row2 + u3*row3 + u4*row4.

现在列和行的角色已经交换,但方法 2 仍然是在 SIMD 计算机上使用的有效方法。

要在 SIMD 计算机上有效地执行矩阵时间向量,矩阵应按列优先顺序存储。要在 SIMD 计算机上高效执行向量时间矩阵,矩阵应按行优先顺序存储。

据我了解,OpenGL 使用列主要排序并执行矩阵时间向量,而 DirectX 使用行主要排序并执行向量时间矩阵。 如果您有三个矩阵变换,您首先按 M1 顺序执行 M2 然后 M3 与矩阵时间向量,您将其写为

v = M3*M2*M1*u //u and v are column vectors - OpenGL form

用你写的向量时间矩阵

v = u*M1*M2*M3 //u and v are row vectors - DirectX form

就效率而言,两种形式都不比另一种更好。这只是一个符号问题(并且会引起混乱,这在您有竞争时很有用)。

请务必注意,对于 matrix*matrix,行优先与列优先存储是不相关的。

如果您想知道为什么垂直 SIMD 指令比水平指令更快,这是一个应该提出的单独问题,但简而言之,水平指令实际上是串行而不是并行运行的,并且被分解为几个微操作 (这就是为什么具有讽刺意味的是dppddpps 快)。

【讨论】:

  • 简而言之,如果矩阵按列优先顺序排列,不进行转置、提取行或进行点积,则无法应用该技巧?
  • 一次做超过 1 个点积(比如,一次 4 个),即你在矩阵乘法代码中所做的,以避免点积指令。
  • @user1095108,是的,没错。如果您不能更改矩阵的顺序,那么您必须进行转置或采用点积。在这种情况下,方法 1 更快。您是在谈论 4x4 矩阵吗?你的目标是什么?
  • 你写了“你几乎不想用 SSE 做两个向量的点积。相反,你确实一次做四个点积”,我认为这个规则每次都可以有效地应用(显然不是)。我尝试将您的规则应用于矩阵 2x2 到 4x4 的向量矩阵 (b * A) 乘法(我确实注意到,它可以应用于 colmatrix 和 matrixmatrix 乘法的无问题),但不能。但是向量*矩阵乘积也需要在通用矩阵库中得到支持,即使它们很少被计算。
  • @user1095108,您可以使用“我的规则”,只需先进行转置即可。但是欢迎您尝试横向指令,看看它们是否对这种特殊情况有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
相关资源
最近更新 更多