2012-06-18 20 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(フロート)'は何ですか? – ecatmur

+0

@ecatmur:64ビットマシンで作業しています。 – PGOnTheGo

+0

質問には答えません。さまざまな64ビットABIがあります。 – ecatmur

答えて

11

sizeof(float)は4なので、Vの4番目のエントリのみが正しくアライメントされます。 _mm_load_psは一度に4つのフロートを読み込むことに注意してください。引数、すなわち第1のフロートへのポインタは16バイトに整列される必要がある。

あなたの例では、iが4の倍数であると仮定しています。そうでないと、_mm_load_ps(&V[i])は失敗します。 _mm_shuffle_psは、2つの値しか取ることができますので、これは少しトリッキーであることを

__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を作る必要があるからです。

も注意値u1u3、及びu5は、前の反復でu2u4u6からも回収することができます。

注意、最終的には、私が持っているは、上記のコードを検証しません! _mm_shuffle_psのドキュメントを読み、第三引数、セレクタは、それぞれの場合に適切であることを確認。

+0

ペドロ:そうです。私は私の例では4の倍数です。しかし、どうやって分割違反を克服するのですか? – PGOnTheGo

+0

@Hello_PG:それはあなたがしたいことにかかっています。 'V 'のすべての要素に対してSIMD演算を4つのグループで実行する必要がありますか? 'V [0..3]'、 'V [4..7]'、 'V [8..11]'?または、長さ4のスライディングウィンドウを持っていますか? 'v [0..3]'、 'V [1..4]'、 'V [2..5]'?前者の場合、各繰り返しで 'i'を' 4 'だけインクリメントして、 'i'の上に' for'ループを使用することができます。後者の場合、効率の悪い '_mm_loadu_ps'の不整合があります。 – Pedro

+0

私のコードにはスライディングウィンドウの概念があります。基本的に1Dステンシルです。それは、隣接する4つの要素を追跡する必要があります。 _mm_load_psと_mm_loadu_psの両方を使用してコードを更新しました。私の更新されたポストでコードを見つけてください。これはそれに取り組むための最善の方法ですか? – PGOnTheGo

関連する問題