SSE, principal problema de desempenho linha vs coluna principal

Por questões pessoais e divertidas, estou codificando uma geom lib usando o SSE (4.1).

Passei as últimas 12 horas tentando entender um problema de desempenho ao lidar com a matriz armazenada linha maior vs coluna principal.

Eu sei que as matrizes Dirext / OpenGL são armazenadas em linhas principais, por isso seria melhor manter minhas matrizes armazenadas em ordem de linhas principais, para que não haja conversão ao armazenar / carregar matrizes de / para GPU / shaders.

Mas, fiz alguns perfis e obtive resultados mais rápidos com o colomun major.

Para transformar um ponto com uma matriz de transfrom na linha principal, é P '= P * M. e na coluna principal, é P' = M * P. Portanto, na coluna principal, é simplesmente um produto de 4 pontos, portanto, apenas 4 instruções SSE4.1 (_mm_dp_ps) quando estiver na linha principal, devo fazer esses produtos de 4 pontos na matriz transposta.

Resultado de desempenho em vetores de 10 milhões

(30/05/2014 @ 08: 48: 10) Log: [5] (Vec.Mul.Matrix) = 76.216653 ms (transformação principal de linha)

(30/05/2014 @ 08: 48: 10) Log: [6] (Matrix.Mul.Vec) = 61.554892 ms (transformação principal da coluna)

Eu tentei várias maneiras de fazer a operação Vec * Matrix, usando _MM_TRANSPOSE ou não, e a maneira mais rápida que encontrei é esta:

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
                );
}

minha classe Vec4 é simplesmente um __m128 m_val; em C ++ otimizado, a construção do vetor é feita com eficiência no registro SSE.

Meu primeiro palpite é que essa multiplicação não é ótima. Eu sou novo no SSE, então estou um pouco confuso sobre como otimizar isso, minha intuição me diz para usar as instruções de reprodução aleatória, mas gostaria de entender por que seria mais rápido. Será carregado 4 shuffle __m128 mais rápido que a atribuição (__m128 m_val = _mm_set_ps (w, z, y, x);)

Dehttps://software.intel.com/sites/landingpage/IntrinsicsGuide/ Não encontrei informações de desempenho em mm_set_ps

Edição: Eu verifiquei o método de criação de perfil, cada teste é feito da mesma maneira, portanto, não há diferenças no cache de memória. Para evitar o cache local, estou fazendo uma operação para uma matriz de vetores de erros aleatórios, a semente é a mesma para cada teste. Apenas 1 teste em cada execução para aumentar o desempenho do cache de memória.

questionAnswers(2)

yourAnswerToTheQuestion