2014-02-11 12 views
2

저는 SIMD 프로그래밍의 초보자입니다.SIMD 내장 함수를 사용하여 효율적인 행 열 변환

이제
__m128i a = {a1, a2, a3, a4} 
__m128i b = {b1, b2, b3, b4} 
__m128i c = {c1, c2, c3, c4} 
__m128i d = {d1, d2, d3, d4} 

나는 다음과 같이 사이를 초기화하고 싶습니다 :

__m128i x1 = {a1, b1, c1, d1} 
__m128i x2 = {a2, b2, c2, d2} 
__m128i x3 = {a3, b3, c3, d3} 
__m128i x4 = {a4, b4, c4, d4} 

다음과 같이 I 데이터와 4 개 SIMD 변수 ( __m128i)가 고려 다음과 같이 내 데이터를 처리하고 싶습니다

아무도 나에게 어떻게 효율적으로이 작업을 수행 할 수 있습니까?

답변

3

질문에 오타가 있고 실제로 4x4 트랜스 포즈를하고 싶다고 가정합니다.

#include "emmintrin.h" 

inline void Transpose_4_4(
    __m128i &v0,    // a1, a2, a3, a4 => a1, b1, c1, d1 
    __m128i &v1,    // b1, b2, b3, b4 => a2, b2, c2, d2 
    __m128i &v2,    // c1, c2, c3, c4 => a3, b3, c3, d3 
    __m128i &v3)    // d1, d2, d3, d4 => a4, b4, c4, d4 
{ 
    __m128i w0 = _mm_unpacklo_epi32(v0, v1); 
    __m128i w1 = _mm_unpackhi_epi32(v0, v1); 
    __m128i w2 = _mm_unpacklo_epi32(v2, v3); 
    __m128i w3 = _mm_unpackhi_epi32(v2, v3); 
    v0 = _mm_unpacklo_epi64(w0, w2); 
    v1 = _mm_unpackhi_epi64(w0, w2); 
    v2 = _mm_unpacklo_epi64(w1, w3); 
    v3 = _mm_unpackhi_epi64(w1, w3); 
} 

데모 :

// 
// tranpose_4_4.cpp 
// 

#include <stdio.h> 
#include <emmintrin.h> 

inline void Transpose_4_4(
    __m128i &v0,    // a1, a2, a3, a4 => a1, b1, c1, d1 
    __m128i &v1,    // b1, b2, b3, b4 => a2, b2, c2, d2 
    __m128i &v2,    // c1, c2, c3, c4 => a3, b3, c3, d3 
    __m128i &v3)    // d1, d2, d3, d4 => a4, b4, c4, d4 
{ 
    __m128i w0 = _mm_unpacklo_epi32(v0, v1); 
    __m128i w1 = _mm_unpackhi_epi32(v0, v1); 
    __m128i w2 = _mm_unpacklo_epi32(v2, v3); 
    __m128i w3 = _mm_unpackhi_epi32(v2, v3); 
    v0 = _mm_unpacklo_epi64(w0, w2); 
    v1 = _mm_unpackhi_epi64(w0, w2); 
    v2 = _mm_unpacklo_epi64(w1, w3); 
    v3 = _mm_unpackhi_epi64(w1, w3); 
} 

int main(void) 
{ 
    int32_t buff[4][4] __attribute__ ((aligned(16))); 
    int i, j; 
    int k = 0; 

    // init buff 
    for (i = 0; i < 4; ++i) 
    { 
     for (j = 0; j < 4; ++j) 
     { 
      buff[i][j] = k++; 
     } 
    } 

    // print buff 
    printf("\nBEFORE:\n"); 
    for (i = 0; i < 4; ++i) 
    { 
     for (j = 0; j < 4; ++j) 
     { 
      printf("%4d", buff[i][j]); 
     } 
     printf("\n"); 
    } 

    // transpose 
    Transpose_4_4(*(__m128i *)buff[0], *(__m128i *)buff[1], *(__m128i *)buff[2], *(__m128i *)buff[3]); 

    // print buff 
    printf("\nAFTER:\n"); 
    for (i = 0; i < 4; ++i) 
    { 
     for (j = 0; j < 4; ++j) 
     { 
      printf("%4d", buff[i][j]); 
     } 
     printf("\n"); 
    } 

    return 0; 
} 

컴파일 및 실행 : 그렇다면하면, 당신은 다음과 같이 4 × 4 8 개 지침 전치 할 수

$ g++ -Wall -msse3 transpose_4_4.cpp && ./a.out 

BEFORE: 
    0 1 2 3 
    4 5 6 7 
    8 9 10 11 
    12 13 14 15 

AFTER: 
    0 4 8 12 
    1 5 9 13 
    2 6 10 14 
    3 7 11 15 
$ 
+0

@sunzhuoshi을 : 당신의 편집이 잘못되었습니다 - 위의 코드는 테스트를 거쳤으며 올바른 결과를 제공합니다. –

+1

네, 맞습니다. 신중하게 테스트하지 않으려 고 미안합니다. @ 폴 R – sunzhuoshi