2014-12-18 5 views
2

intrinsics에 C에서 _mm_load_si128을 사용하려고하면 세그먼트 화 오류가 발생합니다. 데이터가 16 비트 정렬되어야하며 유니온이이를 올바르게 수행한다는 것을 알았습니다. 그러나 이것은 내 문제를 해결하지 못합니다.sse segfault on _mm_load_si128

#include <xmmintrin.h> 

int main(void){ 
    const int N = 8; 
    short int matrice1[] = { 
     10, 11, 12, 13, 14, 15, 16, 17, 
     20, 21, 22, 23, 24, 25, 26, 27, 
     30, 31, 32, 33, 34, 35, 36, 37, 
     40, 41, 42, 43, 44, 45, 46, 47, 
     50, 51, 52, 53, 54, 55, 56, 57, 
     60, 61, 62, 63, 64, 65, 66, 67, 
     70, 71, 72, 73, 74, 75, 76, 77, 
     80, 81, 82, 83, 84, 85, 86, 87 
    }; 

    transpose_simd(matrice1, N); 

return 0; 
} 

union Line{ 
    short int* row; 
    __m128i sRow; 
}; 

void transpose_simd(short int * matrice1, int N){ 
    short int i, n, j; 

    union Line line1, line2; //matrix line 

    __m128i sLine1, sLine2; //sse version of the matrix line 
    __m128i sLine3, sLine4; 

    /* 
    There will be a loop surrounding the following code, but first I kept it simple 
    */ 
      // THE NEXT LINE GIVES A SEGMENTATION FAULT 
      sLine1 = _mm_load_si128((__m128i*) line1.row); //loads 1 matrix line (8 shorts of 16 bits = 128) 
      sLine2 = _mm_load_si128((__m128i*) line2.row); 

      sLine3 = _mm_unpackhi_epi16 (sLine1, sLine2); //shuffle the first 4 elements 
      sLine4 = _mm_unpackhi_epi16 (sLine1, sLine2); //shuffle the last 4 elements 

      _mm_store_si128((__m128i*)line1.row, sLine3); 
      _mm_store_si128((__m128i*)line2.row, sLine4); 
} 

그래서 답변에서 해결책을 얻었습니다. 정확하게 두 개의 루프를 구현 한 후 잘 작동된다 노조가 오프셋 유지하지만 정렬을 설정하지 않는 한

void transpose_simd(short int * matrice1, short int* matrice2, int N){ 
    short int i=0, n=0; 

    short int* __attribute__ ((aligned (16))) line1; //ligne de matrice 
    short int* __attribute__ ((aligned (16))) line2; 

    __m128i sLine1, sLine2; //ligne en version sse 
    __m128i sLine3, sLine4; 

    /* 
    There will be a loop surrounding the following code, but first I kept it simple 
    */ 

      line1 = matrice1 + N*i; 
      line2 = matrice1 + N*(N/2 + i); 

      sLine1 = _mm_loadu_si128((__m128i*) line1); //charge 1 ligne (8 nombres de 16 bits = 128, "coup de bol") 
      sLine2 = _mm_loadu_si128((__m128i*) line2); 

      sLine3 = _mm_unpacklo_epi16 (sLine1, sLine2); //shuffle les 4 premiers chiffres de line1, voir p74 
      sLine4 = _mm_unpackhi_epi16 (sLine1, sLine2); //shuffle les 4 premiers chiffres de line1, voir p74 

      _mm_storeu_si128((__m128i*) (matrice2 + N*2*i), sLine3); 
      _mm_storeu_si128((__m128i*) (matrice2 + N*(2*i+1)), sLine4); 

} 

기본적으로 __attribute__ ((aligned (16))), 내 변수를 정렬합니다. 또한 더 많은 보안을 위해 정렬되지 않은 호환 함수 _mm_storeu_si128 및 _mm_loadu_si128이 사용됩니다. 그러나 이러한 메서드의 정렬 종속 버전보다 느린 지 여부는 알 수 없습니다.

+0

왜 'line1.row'의 * 값 *을 포인터로 캐스팅하고 있습니까? 왜 그렇게 생각하니? –

+0

오 이런, 네 말이 맞아. 내 컴퓨터로 돌아 가면 바로 시도하겠습니다. – Vulpo

+0

노조를 사용하지 않아 혼란스러워졌습니다. 몇 분 안에 코드를 게시 할 것입니다. – Vulpo

답변

5

네가 맞습니다. 데이터가 정렬되지 않았고 사용중인 내장 함수가 정렬 된 데이터 액세스를위한 것입니다.

_mm_load_si128 대신 _mm_loadu_si128을 사용하거나 align 속성을 사용하여 16 바이트로 배열을 정렬하십시오.

추신 : 정렬 된로드/저장을 사용하는 동안주의해야합니다. Union이 데이터를 정렬하지 않습니다. align 속성을 사용하여이를 명시 적으로 수행해야합니다.