0

そのため、openmpを使用してこれらのforループを並列化する最良の方法を見つけるのに少し問題があります。私がここで行うように、最大​​のスピードアップは中央のループを並列化することから来ると推測しています:

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

        }

    }

しかし、これは現在私にほとんどスピードアップを与えていません。どんなヒントも素晴らしいでしょう。私はかなり長い間立ち往生しています。

4

1 に答える 1

2

まず、ループが並列化可能であると確信していますか?値の範囲はどのくらいmですか?

3つのネストされたループすべてが並列化可能であり、m十分に大きい場合(たとえば、少なくとも16程度)、最も外側のループを並列化することが最も有益です。内側のループを並列化すると、からの分岐と結合のオーバーヘッドが大きくなる可能性がありますomp parallel for

低速化のために、ここにいくつかのチェックリストがあります:

  1. すべてのコアが使用されていますか?ある種のタスクマネージャを確認してください。の暗黙のバリアを除いて同期がないためomp parallel for、すべてのコアを利用する必要があります。
  2. m膨大な数ですか?そして、計算の長さはどれくらいですか?m計算が小さいときにが大きい場合、による並列オーバーヘッドが並列化omp parallel forの利点を相殺する可能性があります。内側のループを並列化する場合、トリップカウント(たとえばm)は大きくないはずです。
  3. 偽共有が理由である可能性があります。コードが大量のメモリを変更すると、誤った共有が発生し、スピードアップが損なわれる可能性があります。
于 2011-11-09T12:20:22.807 に答える