2012-06-18 1 views
6

처음 SSE 내장 함수로 작업하고 있으며 16 바이트 메모리 정렬을 보장 한 후에도 세그먼트 화 오류가 발생합니다. 나는이 작업을 수행 할 때잘못된 메모리 정렬로 인해 SSE 내장 함수로 작업하는 동안 세그먼트 오류가 발생했습니다.

float *V = (float*) memalign(16,dx*sizeof(float)); 

:

How to allocate 16byte memory aligned data

이 내 배열을 선언하는 방법이다 :이 게시물을 내 이전 질문에 대한 확장

__m128 v_i = _mm_load_ps(&V[i]); //It works 

그러나 내가 이렇게하면 :

__m128 u1 = _mm_load_ps(&V[(i-1)]); //There is a segmentation fault 
,

하지만 내가 할 경우 :

__m128 u1 = _mm_loadu_ps(&V[(i-1)]); //It works again 

그러나 나는 _mm_loadu_ps를 사용하여 제거하고 단지 _mm_load_ps를 사용하여 작동하도록 할 싶습니다.

저는 Intel icc 컴파일러를 사용하고 있습니다.

어떻게이 문제를 해결할 수 있습니까?

UPDATE :

다음 코드에서 두 작업을 사용하여 :

void FDTD_base (float *V, float *U, int dx, float c0, float c1, float c2, float c3,  float c4) 
    { 
     int i, j, k; 
        for (i = 4; i < dx-4; i++) 
        { 

          U[i] = (c0 * (V[i]) //center 
            + c1 * (V[(i-1)] + V[(i+1)]) 
            + c2 * (V[(i-2)] + V[(i+2)]) 
            + c3 * (V[(i-3)] + V[(i+3)]) 
            + c4 * (V[(i-4)] + V[(i+4)])); 
        } 

     } 

SSE 버전 :

  for (i=4; i < dx-4; i+=4) 
     { 
      v_i = _mm_load_ps(&V[i]); 
      __m128 center = _mm_mul_ps(v_i,c0_i); 

      __m128 u1 = _mm_loadu_ps(&V[(i-1)]); 
      u2 = _mm_loadu_ps(&V[(i+1)]); 

      u3 = _mm_loadu_ps(&V[(i-2)]); 
      u4 = _mm_loadu_ps(&V[(i+2)]); 

      u5 = _mm_loadu_ps(&V[(i-3)]); 
      u6 = _mm_loadu_ps(&V[(i+3)]); 

      u7 = _mm_load_ps(&V[(i-4)]); 
      u8 = _mm_load_ps(&V[(i+4)]); 

      __m128 tmp1 = _mm_add_ps(u1,u2); 
      __m128 tmp2 = _mm_add_ps(u3,u4); 
      __m128 tmp3 = _mm_add_ps(u5,u6); 
      __m128 tmp4 = _mm_add_ps(u7,u8); 

      __m128 tmp5 = _mm_mul_ps(tmp1,c1_i); 
      __m128 tmp6 = _mm_mul_ps(tmp2,c2_i); 
      __m128 tmp7 = _mm_mul_ps(tmp3,c3_i); 
      __m128 tmp8 = _mm_mul_ps(tmp4,c4_i); 

      __m128 tmp9 = _mm_add_ps(tmp5,tmp6); 
      __m128 tmp10 = _mm_add_ps(tmp7,tmp8); 

      __m128 tmp11 = _mm_add_ps(tmp9,tmp10); 
      __m128 tmp12 = _mm_add_ps(center,tmp11); 

      _mm_store_ps(&U[i], tmp12); 
    } 

_mm_load_ps()를 사용하여이 일을보다 효율적인 방법이 있나요를?

+0

아키텍처에서 'sizeof (float)'란 무엇입니까? – ecatmur

+0

@ecatmur : 저는 64 비트 컴퓨터에서 일하고 있습니다. 질문에 대답하지 않는 – PGOnTheGo

+0

; 다양한 64 비트 ABI가 있습니다. – ecatmur

답변

11

sizeof(float)이 4이므로 V의 네 번째 항목 만 올바르게 정렬됩니다. _mm_load_ps은 한 번에 4 개의 플로트를로드합니다. 인수, 즉 첫 번째 부동 소수점에 대한 포인터는 16 바이트로 정렬되어야합니다.

예에서 i은 4의 배수라고 가정합니다. 그렇지 않으면 _mm_load_ps(&V[i])이 실패합니다. _mm_shuffle_ps는 두 개의 값을 가질 수 있기 때문에이 조금 까다 롭습니다 것을

__m128 v_im1; 
__m128 v_i = _mm_load_ps(&V[0]); 
__m128 v_ip1 = _mm_load_ps(&V[4]); 

for (i = 4 ; i < dx ; i += 4) { 

    /* Get the three vectors in this 'frame'. */ 
    v_im1 = v_i; v_i = v_ip1; v_ip1 = _mm_load_ps(&V[i+4]); 

    /* Get the u1..u8 from the example code. */ 
    __m128 u3 = _mm_shuffle_ps(v_im1 , v_i , 3 + (4<<2) + (0<<4) + (1<<6)); 
    __m128 u4 = _mm_shuffle_ps(v_i , v_ip1 , 3 + (4<<2) + (0<<4) + (1<<6)); 

    __m128 u1 = _mm_shuffle_ps(u3 , v_i , 1 + (2<<2) + (1<<4) + (2<<6)); 
    __m128 u2 = _mm_shuffle_ps(v_i , u4 , 1 + (2<<2) + (1<<4) + (2<<6)); 

    __m128 u5 = _mm_shuffle_ps(v_im1 , u3 , 1 + (2<<2) + (1<<4) + (2<<6)); 
    __m128 u6 = _mm_shuffle_ps(u4 , v_ip1 , 1 + (2<<2) + (1<<4) + (2<<6)); 

    __m128 u7 = v_im1; 
    __m128 u8 = v_ip1; 

    /* Do your computation and store. */ 
    ... 

    } 

참고 :

업데이트

이 내가로드를 정렬하는 셔플을 사용하여 위의 슬라이딩 윈도우의 예를 구현 제안하는 방법이다 각 인수에서 다른 중복 값을 가진 값을 다시 사용하려면 먼저 u3u4을 만들어야합니다.

참고도 값 u1,이 u3u5는 이전 반복에서 u2, u4u6로부터 회수 할 수있다.

참고, 마지막으로, 내가 위의 코드를 확인하지 않았습니다! _mm_shuffle_ps에 대한 설명서를 읽고 세 번째 인수 인 selector가 각 사례에 대해 올바른지 확인하십시오.

+0

Pedro : 당신 말이 맞아요. 내 예에서는 4의 배수입니다. 그러나 세분화 오류를 극복하려면 어떻게해야합니까? – PGOnTheGo

+0

@Hello_PG : 당신이하고 싶은 일에 달려 있습니다. 'V'의 모든 요소에 대해 4 개의 그룹으로 SIMD 연산을 수행해야합니까? 'V [0..3]','V [4..7]','V [8..11]'? 또는 길이 4의 슬라이딩 윈도우가 있습니까? 'v [0..3]','V [1..4]','V [2..5]'? 전자의 경우,'i'에 대해서'for' 루프를 사용하고, 반복 할 때마다'i'를'4 '씩 증가시킬 수 있습니다. 후자의 경우, 효율적이지 않은 정렬되지 않은'_mm_loadu_ps'가 붙어 있습니다. – Pedro

+0

내 코드에는 슬라이딩 윈도우 개념이 포함됩니다. 기본적으로 1D 스텐실입니다.이 네 개의 요소를 추적해야합니다. _mm_load_ps 및 _mm_loadu_ps를 사용하여 코드를 업데이트했습니다. 업데이트 된 게시물에서 코드를 찾으십시오. 이 문제를 해결하는 가장 좋은 방법입니까? – PGOnTheGo

관련 문제