矢量*矩阵产品效率问题

正如Z boson 推荐的那样 ,我使用的是列主矩阵格式,以避免使用点积。 但是,在将矢量与矩阵相乘时,我没有看到避免它的可行方法。 矩阵乘法技巧需要有效提取行(或列,如果我们转置产品)。 为了将矢量乘以矩阵,我们因此转置:

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

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

这可以从原始post(我的第一个关于SO) 高效的4×4矩阵向量乘法 – sse-horizo​​ntal-add-and-dot-prod中理解 。 其余讨论适用于4×4矩阵。

这里有两种做矩阵时间向量的方法(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 

在效率方面,这两种forms都不比另一种forms更好。 这只是一个符号问题(并引起混乱,当你参加比赛时有用)。

值得注意的是,对于矩阵*矩阵行主要与列主要存储无关。

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