0

このスレッドのopenMPパフォーマンスが存在することを知っています

しかし、ここで私の例は非常に単純です

C コード:

int MaFunc(size_t szGlobalWorkSize)
{
        int iGID = 0;
        float *pfResult = (float *)calloc(szGlobalWorkSize * 100, sizeof(float));
        float fValue = 0.5f;
        struct timeval tim;
        gettimeofday(&tim, NULL);
        double tLaunch1=tim.tv_sec+(tim.tv_usec/1000000.0);

        #pragma omp parallel for
        for (iGID = 0; iGID < (int)szGlobalWorkSize * 100; iGID++)
        {
          pfResult[iGID] = fValue;
         // printf("Element %d traité par le thread %d \n",iGID,omp_get_thread_num());
        }
        gettimeofday(&tim, NULL);
        double tLaunch2=tim.tv_sec+(tim.tv_usec/1000000.0);
        printf("%.6lf Time OMP\n", tLaunch2-tLaunch1);
     }

この例のタイミングは、openMP (szGlobalworkSize = 131072) で 0.045 秒に対して、openMP なしで openMP 0.015 を使用すると増加します。

私は gcc の次の行を使用します: gcc -march=native -fopenmp -O3 MyCode.c -lm

gcc (GCC) 4.8.2 20140120 (レッドハット 4.8.2-15)

編集1:

int MyFunc2()
{
        int iGID = 0;
        int j = 0;
        //float *pfResult = (float *)calloc(szGlobalWorkSize * 100, sizeof(float));
        float *pfResult = (float *)valloc(szGlobalWorkSize * 100* sizeof(float));
        float fValue = 0.5f;
        struct timeval tim;
        gettimeofday(&tim, NULL);

        double tLaunch1=tim.tv_sec+(tim.tv_usec/1000000.0);
        double time = omp_get_wtime();
        int iChunk = getpagesize();
        int iSize = ((int)szGlobalWorkSize * 100) / iChunk;


       // #pragma omp parallel
        #pragma omp parallel for
        for (iGID = 0; iGID < iSize; iGID++)
        {
          for (j = 0; j < iChunk; j++)
          {

             pfResult[iGID * iChunk + j] = fValue;
         //pfResult[iGID] = fValue;
      }
         // printf("Element %d traité par le thread %d \n",iGID,omp_get_thread_num());
        }
        time = omp_get_wtime() - time;
        gettimeofday(&tim, NULL);
        double tLaunch2=tim.tv_sec+(tim.tv_usec/1000000.0);
        printf("%.6lf Time OMP\n", tLaunch2-tLaunch1);
        printf("Pagesize=%d\n", getpagesize());
        printf("%.6lf Time OMP2\n", time);
     }

また、memalignのチャンクと同じ時間

スレッドごとのタイミングで編集 2

#pragma omp parallel private(dLocalTime)
    {
           pdTime[omp_get_thread_num()] = omp_get_wtime();
       printf("Thread Begin %d Time %f\n", omp_get_thread_num(), pdTime[omp_get_thread_num()] );
       #pragma omp for
           for (iGID = 0; iGID < iSize; iGID++)
           {
    //   for (j = 0; j < iChunk; j++)
             {

             //  pfResult[iGID * iChunk + j] = fValue;
            pfResult[iGID] = fValue;
         }

           }
       //dLocalTime = (omp_get_wtime() - dLocalTime);
         pdTime[omp_get_thread_num()] = (omp_get_wtime() - pdTime[omp_get_thread_num()]);
             printf("Thread End %d Time %f\n", omp_get_thread_num(), pdTime[omp_get_thread_num()]);

      // printf("End Element %d traité par le thread %d \n",0,tid);
    }

各スレッドは合計 0.045 に対して 0.015 かかるため、openmp には 0.03 の修正部分があります。巨大な次元であっても、openmp とスレッドのこの修正部分が見られるのは奇妙です。ここ)

ありがとう

4

1 に答える 1

0

わかりました、あなたが主張するので.. :)

固定スレッドのウォームアップ:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <omp.h>
#include <unistd.h>

int main()
{
        int szGlobalWorkSize = 131072;
        int iGID = 0;
        int j = 0;
        omp_set_dynamic(0);
        // warmup
        #if WARMUP
        #pragma omp parallel
        {
        #pragma omp master
        {
        printf("%d threads\n", omp_get_num_threads());
        }
        }
        #endif
        printf("Pagesize=%d\n", getpagesize());
        float *pfResult = (float *)valloc(szGlobalWorkSize * 100* sizeof(float));
        float fValue = 0.5f;
        struct timeval tim;
        gettimeofday(&tim, NULL);

        double tLaunch1=tim.tv_sec+(tim.tv_usec/1000000.0);
        double time = omp_get_wtime();
        int iChunk = getpagesize();
        int iSize = ((int)szGlobalWorkSize * 100) / iChunk;

        #pragma omp parallel for
        for (iGID = 0; iGID < iSize; iGID++)
        {
          for (j = 0; j < iChunk; j++)
             pfResult[iGID * iChunk + j] = fValue;
        }
        time = omp_get_wtime() - time;
        gettimeofday(&tim, NULL);
        double tLaunch2=tim.tv_sec+(tim.tv_usec/1000000.0);
        printf("%.6lf Time1\n", tLaunch2-tLaunch1);
        printf("%.6lf Time2\n", time);
}

私のマシンには次の番号があります。

$ g++ -O2 -fopenmp testomp.cpp && OMP_NUM_THREADS=1 ./a.out
Pagesize=4096
0.036493 Time1
0.036489 Time2
$ g++ -O2 -fopenmp testomp.cpp && ./a.out
Pagesize=4096
0.034721 Time1
0.034718 Time2
$ g++ -O2 -fopenmp testomp.cpp -DWARMUP && ./a.out
24 threads
Pagesize=4096
0.026966 Time1
0.026963 Time2

ご覧のとおり、スレッドの作成時間が数値に大きく影響しています。

それでもスケーリングしないのはなぜですか?まあ、これは非常にメモリバウンドなワークロードです。実際には、ページを 2 回塗りつぶします。OS が最初のタッチでページをクリアすると、プログラムは値を介してページを塗りつぶします。システムに十分なメモリ帯域幅がないようです。parallel forデフォルトでは、スレッド間の反復をインターリーブしない静的スケジュールを使用するため、false-sharing がここで重要な役割を果たすとは思わないため、false- sharing は境界で 1 回のみ可能です。

于 2014-11-19T19:15:57.023 に答える