C++ 理解SSE3矩阵乘法优化

C++ 理解SSE3矩阵乘法优化,c++,sse,C++,Sse,关于 haddps不会对向量中的所有四个元素求和。需要两个haddps指令才能获得完整的水平和 如果我们对向量的元素进行编号,{c0,c1,c2,c3},第一个haddps产生{c0+c1,c2+c3,c0+c1,c2+c3}。第二个生成的haddps不是向量中所有四个元素的总和。需要两个haddps指令才能获得完整的水平和 如果我们对向量的元素进行编号,{c0,c1,c2,c3},第一个haddps产生{c0+c1,c2+c3,c0+c1,c2+c3}。第二个生成的{c0+c1+c2+c3,}

关于


haddps
不会对向量中的所有四个元素求和。需要两个
haddps
指令才能获得完整的水平和


如果我们对向量的元素进行编号,
{c0,c1,c2,c3}
,第一个
haddps
产生
{c0+c1,c2+c3,c0+c1,c2+c3}
。第二个生成的haddps不是向量中所有四个元素的总和。需要两个
haddps
指令才能获得完整的水平和


如果我们对向量的元素进行编号,
{c0,c1,c2,c3}
,第一个
haddps
产生
{c0+c1,c2+c3,c0+c1,c2+c3}
。第二个生成的
{c0+c1+c2+c3,}

足够公平,但是
\u mm\u store\u ss
将只存储向量的第一个元素?当我阅读MSDN上的文档时,我不清楚。这很公平,但是
\u mm\u store\u ss
将只存储向量的第一个元素?当我阅读MSDN上的文档时不清楚。这似乎适用于4x4矩阵?我需要它用于1024x1024到4K x 4K矩阵,只需使用MKL/Goto BLAS/ATLAS即可。对于大型矩阵乘法,您需要执行多级缓存阻塞,但如果以前从未执行过,则需要几周的时间来实现和调整。SIMD只提供缓存阻塞性能提升的一小部分。这似乎适用于4x4矩阵?我需要它用于1024x1024到4K x 4K矩阵,只需使用MKL/Goto BLAS/ATLAS即可。对于大型矩阵乘法,您需要执行多级缓存阻塞,但如果以前从未执行过,则需要几周的时间来实现和调整。SIMD只提供缓存阻塞性能提升的一小部分。
template<>
void SeqMatrixMult4(int size, float** m1, float** m2, float** result)
{
    Transpose(size, m2);
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            __m128 c = _mm_setzero_ps();

            for (int k = 0; k < size; k += 4) {
                c = _mm_add_ps(c, _mm_mul_ps(_mm_load_ps(&m1[i][k]), _mm_load_ps(&m2[j][k])));
            }
            c = _mm_hadd_ps(c, c);
            c = _mm_hadd_ps(c, c);
            _mm_store_ss(&result[i][j], c);
        }
    }
    Transpose(size, m2);
}
long long start, end;
__m128 v1, v2, vMul, vRes;
vRes = _mm_setzero_ps();

start = wall_clock_time();
transpose_matrix(m2);
for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
        float tmp = 0;
        for (int k = 0; k < SIZE; k+=4) {
            v1 = _mm_load_ps(&m1[i][k]);
            v2 = _mm_load_ps(&m2[j][k]);
            vMul = _mm_mul_ps(v1, v2);

            vRes = _mm_add_ps(vRes, vMul);
        }
        vRes = _mm_hadd_ps(vRes, vRes);
        _mm_store_ss(&result[i][j], vRes);
    }
}
end = wall_clock_time();
fprintf(stderr, "Optimized Matrix multiplication took %1.2f seconds\n", ((float)(end - start))/1000000000);

// reverse the transposition
transpose_matrix(m2);