You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何更优地编写SIMD代码以实现变换矩阵的求逆?

如何更优地编写SIMD代码以实现变换矩阵的求逆?

最近我在给光线追踪项目写一个数学库,正琢磨着怎么把矩阵求逆这类吃性能的重型运算优化得更到位。

查了不少资料后,我发现了一个针对变换矩阵求逆的实用技巧——不用直接去逆一个完整的4x4变换矩阵,而是把它拆成缩放矩阵旋转矩阵和平移矩阵这三个独立的部分。之后分别对这三个矩阵求逆,再把它们按正确的顺序组合起来,就能得到原变换矩阵的逆矩阵了,这种方式比直接逆大矩阵高效得多。

核心的思路是利用这三类特殊矩阵的求逆特性,每一步都能充分发挥SIMD的并行优势:

  • 缩放矩阵的逆:直接对每个缩放分量取倒数就行,用SIMD指令可以一次性处理所有分量;
  • 旋转矩阵的逆:旋转矩阵是正交矩阵,它的逆就是自身的转置,直接调换行列就能快速得到,完全不用复杂计算;
  • 平移矩阵的逆:把平移分量取反,再结合旋转矩阵的逆来调整平移的坐标系,同样可以用SIMD批量操作。

下面是我基于AVX指令集实现的基础数据结构,保证内存对齐以适配SIMD操作:

#include <immintrin.h>

// 对齐16字节的4维向量,兼容SIMD指令操作
typedef union u_vec4s
{
    float       a[4];
    __m128      simd;
    struct
    {
        float   x;
        float   y;
        float   z;
        float   w;
    };
}__attribute((aligned(16))) t_vec4s;

// 对齐16字节的4x4矩阵,按列存储方便SIMD列操作
typedef union u_mat4s
{
    float       m[4][4];
    t_vec4s     cols[4];
    __m128      col_simd[4];
}__attribute((aligned(16))) t_mat4s;

用这种拆分的方式,整个求逆过程的运算量会大幅降低,尤其适合光线追踪这种需要大量矩阵运算的场景,能明显提升整体渲染性能。

备注:内容来源于stack exchange,提问作者Astranged T'fyer

火山引擎 最新活动