正如Z boson 推荐的那样 ,我使用的是列主矩阵格式,以避免使用点积。 但是,在将矢量与矩阵相乘时,我没有看到避免它的可行方法。 矩阵乘法技巧需要有效提取行(或列,如果我们转置产品)。 为了将矢量乘以矩阵,我们因此转置:
(b * A)^T = A^T * b^T
A
是矩阵, b
是行向量,在被转置之后变为列向量。 它的行只是单个标量,矢量*矩阵乘积实现成为(非转置)矩阵A
和b
的列点积的低效实现。 有没有办法避免执行这些点产品? 我认为可以做到的唯一方法是涉及行提取,这对于列主矩阵格式来说是低效的。
这可以从原始post(我的第一个关于SO) 高效的4×4矩阵向量乘法 – sse-horizontal-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指令比水平指令更快,这是一个应该被问到的单独问题,但简而言之,水平指令实际上是串行而不是并行,并分解成几个微操作(这就是为什么具有讽刺意味的是, dppd
比dpps
快。
以上就是c/c++开发分享矢量*矩阵产品效率问题相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/523035.html