SSE,主要行vs主要列的性能问题
SSE, row major vs column major performance issue
对于个人和有趣的事情,我正在使用SSE(4.1)编写一个geom库。
我花了最后12小时试图理解处理行主要vs列主要存储矩阵时的性能问题。
我知道直接/OpenGL矩阵存储行主要,所以它会更好,我保持我的矩阵存储在行主要顺序,所以我将没有转换时存储/加载矩阵到/从GPU/着色器。
但是,我做了一些分析,并且我得到了列major更快的结果。
用一个变换矩阵变换一个点,在行主要中,它是p ' = p * M,在列主要中,它是p ' = M * p。所以在列major中,它只是4个点积,所以只有4个SSE4.1指令(_mm_dp_ps),当在行major中,我必须在转置矩阵上做这4个点积。
在10M矢量上的性能结果
(30/05/2014@08:48:10) Log: [5] (vec . mull . matrix) = 76.216653 ms (row major transform)
(30/05/2014@08:48:10) Log: [6] (matrix . mull . vec) = 61.554892 ms (column major transform)
我尝试了几种方法来做Vec *矩阵操作,使用_mm_转置与否,我发现最快的方法是:
mssFloat Vec4::operator|(const Vec4& v) const //-- Dot Product
{
return _mm_dp_ps(m_val, v.m_val, 0xFF ).m128_f32[0];
}
inline Vec4 operator*(const Vec4& vec,const Mat4& m)
{
return Vec4( Vec4( m[0][0],m[1][0],m[2][0],m[3][0]) | vec
, Vec4( m[0][1],m[1][1],m[2][1],m[3][1]) | vec
, Vec4( m[0][2],m[1][2],m[2][2],m[3][2]) | vec
, Vec4( m[0][3],m[1][3],m[2][3],m[3][3]) | vec
);
}
我的类Vec4只是一个__m128 m_val,在优化的c++中,向量构造都是在SSE寄存器上有效地完成的。
我的第一个猜测是,这个乘法不是最优的。我是SSE的新手,所以我有点困惑如何优化它,我的直觉告诉我使用shuffle指令,但我想知道为什么它会更快。它是否会比赋值更快地加载4 shuffle __m128 (__m128 m_val = _mm_set_ps(w, z, y, x);)
从https://software.intel.com/sites/landingpage/IntrinsicsGuide/我找不到mm_set_ps的性能信息
编辑:我仔细检查了分析方法,每个测试都以相同的方式完成,所以没有内存缓存差异。为了避免本地缓存,我对随机化bug向量数组进行操作,每个测试的种子都是相同的。每次执行只进行一次测试,以避免内存缓存带来的性能提升。
不要使用_mm_dp_ps
进行矩阵乘法!我已经在SSE的高效4x4矩阵向量乘法中详细解释了这一点:水平加法和点积-重点是什么?(顺便说一下,这是我在SO上的第一篇文章)。
你不需要任何比SSE更有效的东西(甚至不需要SSE2)。使用这个代码做4x4矩阵乘法有效。如果矩阵是按行为主顺序存储的,那么gemm4x4_SSE(A,B,C)
也是如此。如果矩阵按列主顺序存储,则按gemm4x4_SSE(B,A,C)
存储
void gemm4x4_SSE(float *A, float *B, float *C) {
__m128 row[4], sum[4];
for(int i=0; i<4; i++) row[i] = _mm_load_ps(&B[i*4]);
for(int i=0; i<4; i++) {
sum[i] = _mm_setzero_ps();
for(int j=0; j<4; j++) {
sum[i] = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(A[i*4+j]), row[j]), sum[i]);
}
}
for(int i=0; i<4; i++) _mm_store_ps(&C[i*4], sum[i]);
}
我们实际上分析了3x4矩阵伪乘法(就好像它是4x4仿射),并发现在SSE3和AVX中,只要两种布局都优化到极限,列主布局和行主布局的差异很小(<10%)。
基准https://github.com/buildaworldnet/IrrlichtBAW/blob/master/examples_tests/19.SIMDmatrixMultiplication/main.cpp
- 在类中使用随机生成器时出现性能问题
- Qt OpenGL 渲染到纹理性能问题
- 剪辑性能问题
- OpenCV - 基本操作 - 性能问题 [模式:发布]
- 使用 #define 进行跟踪日志记录以避免性能问题
- 在 Qt C++ 中在自定义项委托上绘制文本时的性能问题
- std::函数有性能问题,如何避免?
- 使用 const double* const 作为模板参数 - 代码性能问题
- 在C 中读取大型CSV文件性能问题
- MPI 二进制文件 I/O 基本功能和性能问题
- 使用STD :: MAP在数据及其性能问题中查找重复项.我可以预先分配吗?
- C 功能性能问题
- 在C 性能问题中使用Getter返回地图
- 初始化每个班级成员时的性能问题
- 事件(开始,结束),1天的最大事件.C++ 中的性能问题
- 在X64模式下从C /CLI调用MASM PROC会产生意外的性能问题
- OpenGL:MESA3D屏幕上的软件渲染性能问题
- 是包含容器性能问题的STL关联容器
- 任何性能问题都在qt框架中使用了stackedwidget的最大页面数
- SHGetFileInfo性能问题