2011-11-09 9 views
0

openmpを使用してこれらのループを並列化する最良の方法を見つけるのに少し問題があります。入れ子になったforループと組み込み関数でopenmpを使用する際の問題

for(i = 0; i < m/16*16; i+=16){ 
    #pragma omp parallel for 
     for(j = 0; j < m; j++){ 

      C_column_start = C+i+j*m; 

      c_1 = _mm_loadu_ps(C_column_start); 
      c_2 = _mm_loadu_ps(C_column_start+4); 
      c_3 = _mm_loadu_ps(C_column_start+8); 
      c_4 = _mm_loadu_ps(C_column_start+12); 

      for (k=0; k < n; k+=2){ 

       A_column_start = A+k*m; 

       a_1 = _mm_loadu_ps(A_column_start+i); 
       a_2 = _mm_loadu_ps(A_column_start+i+4); 
       a_3 = _mm_loadu_ps(A_column_start+i+8); 
       a_4 = _mm_loadu_ps(A_column_start+i+12); 

       b_1 = _mm_load1_ps(A_column_start+j); 

       mul_1 = _mm_mul_ps(a_1, b_1); 
       mul_2 = _mm_mul_ps(a_2, b_1); 
       mul_3 = _mm_mul_ps(a_3, b_1); 
       mul_4 = _mm_mul_ps(a_4, b_1); 

       c_4 = _mm_add_ps(c_4, mul_4); 
       c_3 = _mm_add_ps(c_3, mul_3); 
       c_2 = _mm_add_ps(c_2, mul_2); 
       c_1 = _mm_add_ps(c_1, mul_1); 

       A_column_start+=m; 

       a_1 = _mm_loadu_ps(A_column_start+i); 
       a_2 = _mm_loadu_ps(A_column_start+i+4); 
       a_3 = _mm_loadu_ps(A_column_start+i+8); 
       a_4 = _mm_loadu_ps(A_column_start+i+12); 

       b_1 = _mm_load1_ps(A_column_start+j); 

       mul_1 = _mm_mul_ps(a_1, b_1); 
       mul_2 = _mm_mul_ps(a_2, b_1); 
       mul_3 = _mm_mul_ps(a_3, b_1); 
       mul_4 = _mm_mul_ps(a_4, b_1); 

       c_4 = _mm_add_ps(c_4, mul_4); 
       c_3 = _mm_add_ps(c_3, mul_3); 
       c_2 = _mm_add_ps(c_2, mul_2); 
       c_1 = _mm_add_ps(c_1, mul_1); 

      } 


      _mm_storeu_ps(C_column_start, c_1); 
      _mm_storeu_ps(C_column_start+4, c_2); 
      _mm_storeu_ps(C_column_start+8, c_3); 
      _mm_storeu_ps(C_column_start+12, c_4); 

     } 

    } 

しかし、これは現在、私にはほとんどスピードアップを与えることはありません:私はここで行うように私は最大のスピードアップは、中央のループを並列化から来るであろうと推測しています。あらゆるヒントはすばらしいでしょう。私は今かなりの間詰まっています。

+1

外部ループを並列化しようとしましたか? –

+0

しました。それは私にどんなスピードアップも与えていない。 –

答えて

2

まず、ループは並列化可能ですか?値mの範囲は何ですか?すべての3つのネストされたループが並列化され、mが十分に大きい場合

は、(少なくとも16またはそう言う)、次いで最も外側のループを並列化することは最も有益であろう。内部ループを並列化すると、フォーク結合オーバーヘッドが深刻になる可能性があります(omp parallel for)。低スピードアップのために

、ここでいくつかのチェックリストは次のとおりです。

  1. あなたはすべてのコアが利用されていますか?タスクマネージャの種類をチェックしてください。暗黙的なバリア(omp parallel for)以外の同期がないので、すべてのコアを使用する必要があります。
  2. mは巨大な数字ですか?そして、計算の長さは何ですか? mが膨大で計算量が少ない場合は、omp parallel forによる並列オーバーヘッドが並列化の利点を相殺する可能性があります。内部ループを並列化すると、トリップカウント(たとえば、m)は大きくないはずです。
  3. False sharingが原因である可能性があります。コードが大量のメモリを変更すると、誤った共有が行われ、スピードアップが傷つく可能性があります。
関連する問題