2012-06-18 26 views
6

SSE intrinsics ile ilk defa çalışıyorum ve 16bayt bellek hizalaması sağlandıktan sonra bile bölümleme hatasıyla karşılaşıyorum. Bunu yapmak çalıştığınızdaHatalı bellek hizalaması nedeniyle SSE içeriğiyle çalışırken parçalanma hatası

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

:

How to allocate 16byte memory aligned data

Bu benim dizi beyan nasıl geçerli: Bu mesaj benim daha önceki soruya bir uzantısıdır

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

Ama Bunu yaptığımda:

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

Ama bunu yaparsam:

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

Ancak _mm_loadu_ps kullanarak ortadan kaldırmak ve sadece _mm_load_ps kullanarak iş yapmak isteyen istiyoruz.

Intel icc derleyicisiyle çalışıyorum.

Bu sorunu nasıl çözebilirim?

GÜNCELLEME:

aşağıdaki kodda hem operasyon kullanıyor:

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 sürümü:

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

sadece _mm_load_ps() kullanarak bunu yapmanın daha etkili bir yolu var mı?

+0

Mimarinizdeki "sizeof (float)" nedir? – ecatmur

+0

@ecatmur: 64 bit makinede çalışıyorum. Bu soruya cevap vermeyen – PGOnTheGo

+0

; Çok sayıda farklı 64 bit ABI var. – ecatmur

cevap

11

sizeof(float) 4'ten beri, yalnızca V'daki her dördüncü giriş düzgün şekilde hizalanacaktır. _mm_load_ps'un bir seferde dört şamandıra yüklediğini unutmayın. Argüman, yani birinci kayan noktaya işaretçi, 16 bayta hizalanmalıdır.

Örnekte, i örneğinin dördün katları olduğu varsayılıyor, aksi halde _mm_load_ps(&V[i]) başarısız olur. _mm_shuffle_ps sadece iki değerleri alabilir çünkü bu biraz zor olduğunu

__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. */ 
    ... 

    } 

Not:

Güncelleme

Bu benim hizalanmış yükleri ve shuffles kullanarak yukarıdaki sürgülü pencere örneğini uygulayan öneririm nasıl Her argümandan, bu yüzden farklı çakışmalara sahip diğer değerler için bunları kullanmak için ilk olarak u3 ve u4 yapmamız gerekiyor.

de dikkat değerleri u1, u3 ve u5 önceki tekrarında u2, u4 ve u6 elde edilebilir.

Son olarak, numaralı telefon numaramın yukarıdaki kodun kodunu doğrulamamasına dikkat edin! _mm_shuffle_ps belgelerini okuyun ve üçüncü bağımsız değişkenin, her bir durum için doğru olduğunu kontrol edin.

+0

Pedro: Haklısınız. Benim örneğimde 4'lük bir kat. Ama bölütleme hatasını nasıl aşabilirim? – PGOnTheGo

+0

@Hello_PG: Ne yapmak istediğinize bağlı. "V" nin tüm öğeleri üzerinde SIMD işlemlerini dörtlü gruplar halinde yapmak zorunda mısınız? V [0..3] ',' V [4..7] ',' V [8..11] '? Veya dördüncü uzunlukta bir sürgülü pencereniz var mı? v [0..3] ',' V [1..4] ',' V [2..5] '? Eski durumda, her iterasyonda 'i' ile 'i' değerini arttırmak için '' '' '' '' '' 'i' i '' üzerinden kullanabilirsiniz. İkinci durumda, daha az etkin olmayan hizalanmış '_mm_loadu_ps' ile sıkışmışsınız. – Pedro

+0

Kodumda sürgülü bir pencere konsepti var. Temelde komşu 4 elementleri izlememi gerektiren bir 1D şablonudur. Kodu hem _mm_load_ps hem de _mm_loadu_ps..u kullanarak güncelledim. Güncellenmiş gönderiimde kodu bulun. Bunun üstesinden gelmenin en iyi yolu bu mu? – PGOnTheGo