簡體   English   中英

使用OpenMP分配數組的特殊指令?

[英]Special directives for assigning array with OpenMP?

我在OpenMP進行並行化的簡單for循環是

    vector< double > xs; 
    vector< double > ys; 
    xs.resize(N);
    ys.resize(N);
    if(rank0) printf("Assigning points ...\n");
#pragma omp parallel for
    for(long i = 0; i < N; i++) {
        xs[i] = ((double)rand()/(double)RAND_MAX);
        ys[i] = ((double)rand()/(double)RAND_MAX);
    } 

但是,當我包含#pragma omp parallel for比不包含時要花費更長的時間。 當我沒有使用正確的reduction或類似的reduction時,經常會看到這種情況,所以我想知道對於#pragma我是否還需要做其他事情。

這個for循環是否需要#pragma其他功能?

請注意,這個問題與rand()的使用直接相關。

我的直接猜測是問題出在rand()使用每次調用rand()都會更新的單個種子這一事實。 這意味着即使您要寫入的數組之間沒有沖突,對rand()每次調用也可能會強制線程之間的同步。

有多種方法可以解決此問題。 一個明顯的例子是使用C ++ 11中提供的新隨機數生成類,為每個線程使用一個單獨的隨機數生成器對象,如下所示:

    std::mt19937_64 a;
    std::mt19937_64 b;

    std::uniform_real_distribution<double> da;
    std::uniform_real_distribution<double> db;

#pragma omp parallel for private(a, b)
    for (long i = 0; i < N; i++) {
        xs[i] = da(a);
        ys[i] = db(b);
    }

至少在我的系統上進行了一次快速測試,它在單線程中運行大約4秒鍾,在啟用OpenMP的情況下運行大約1秒鍾(並且這是在4核處理器上進行的,因此接近完美擴展)。

請注意,如果您使用的是32位系統(或至少使用產生32位代碼的編譯器),則使用mt19937而不是mt19937_64可能會更快。 每個生成的數字只有32位的隨機性,但是無論如何它可能與rand()產生的數字一樣多。 在64位系統/編譯器上,期望mt19937_64能夠以同樣快的速度運行,並產生更大的隨機性。

另一個小注意事項:在這里,我只為每個生成器使用了默認種子(為1 )。 您可能想要隨機生成種子,例如從std::random_device生成種子,並分別為每個線程的生成器種子,這樣就不會在線程之間重復數字。

事實證明, rand不是線程安全的。 一個簡單的替代方法是drand48_r供我嘗試使用。 如下更改我的循環將顯示我期望的確切速度:

#pragma omp parallel for private(ii, rBuf, trand) shared(xs,ys)
    for(ii = 0; ii < N; ii++) {
        drand48_r(&rBuf, &trand);
        xs[ii] = trand;
        drand48_r(&rBuf, &trand);
        ys[ii] = trand;
    } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM