簡體   English   中英

我在 C 上遇到 OpenMP 問題

[英]I am having trouble with OpenMP on C

我想並行化 for 循環,但我似乎無法理解這個概念,每次我嘗試並行化它們時它仍然有效,但它會顯着減慢。

for(i=0; i<nbodies; ++i){
    for(j=i+1; j<nbodies; ++j) {
        d2 = 0.0;   
        
        for(k=0; k<3; ++k) {
            
            rij[k] = pos[i][k] - pos[j][k];
            
            d2 += rij[k]*rij[k];
        
        if (d2 <= cut2) {
           d = sqrt(d2);
           d3 = d*d2;
           
           for(k=0; k<3; ++k) {
                double f = -rij[k]/d3;
                forces[i][k] += f;
                forces[j][k] -= f;
           }
           
           ene += -1.0/d; 
        }
       }
    }
}

在某些情況下,我嘗試使用與屏障和關鍵的同步,但沒有任何反應,或者處理根本沒有結束。

更新,這是我現在使用的 state。 工作時沒有崩潰,但計算時間越長,我添加的線程越多。 (銳龍 5 2600 6/12)

#pragma omp parallel shared(d,d2,d3,nbodies,rij,pos,cut2,forces) private(i,j,k) num_threads(n)
    {
        clock_t begin = clock();
       #pragma omp for schedule(auto)
        for(i=0; i<nbodies; ++i){
            
            for(j=i+1; j<nbodies; ++j) {
                d2 = 0.0;
                for(k=0; k<3; ++k) {
                    rij[k] = pos[i][k] - pos[j][k];
                    d2 += rij[k]*rij[k];    
                }
                
                if (d2 <= cut2) {
                    d = sqrt(d2);
                    d3 = d*d2;
                #pragma omp parallel for shared(d3) private(k) schedule(auto) num_threads(n)
                 for(k=0; k<3; ++k) {
                    double f = -rij[k]/d3;
                    #pragma omp atomic 
                    forces[i][k] += f;
                    #pragma omp atomic
                    forces[j][k] -= f;
                    }
                    
                    ene += -1.0/d; 
                }
            }
        }
    
        clock_t end = clock();
        double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
        #pragma omp single
        printf("Calculation time %lf sec\n",time_spent);
    }

我在實際的並行代碼中加入了計時器(我認為這種方式快了幾毫秒)。 此外,我認為我得到了大部分共享和私有變量的權利。 在文件中它輸出力。

如果未同步的工作量不是很大,那么使用障礙或其他同步將減慢您的代碼。 你的情況並非如此。 您可能需要重新編寫代碼以刪除同步。

您正在做類似 N 體模擬的事情。 我在這里制定了幾個解決方案: https://pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-examples.html#N-bodyproblems

另外:您的d2循環是一個縮減,因此您可以這樣對待它,但如果該變量是i,j迭代的私有變量,則可能就足夠了。

您應該始終在最小要求的 scope 中定義您的變量,尤其是在性能存在問題的情況下。 (請注意,如果這樣做,您的編譯器可以創建更高效的代碼)。 除了性能之外,它還有助於避免數據競爭。

我認為您放錯了花括號,第一個for循環中的條件應該是i<nbodies-1 變量ene可以使用歸約來求和,並且必須使用原子操作來增加數組forces ,因此您的代碼應如下所示:

#pragma omp parallel for reduction(+:ene)
 for(int i=0; i<nbodies-1; ++i){
    for(int j=i+1; j<nbodies; ++j) {
        double d2 = 0.0;       
        double rij[3];
        for(int k=0; k<3; ++k) {
            rij[k] = pos[i][k] - pos[j][k];            
            d2 += rij[k]*rij[k];       
        }
        if (d2 <= cut2) {
           double d = sqrt(d2);
           double d3 = d*d2;
           
           for(int k=0; k<3; ++k) {
                double f = -rij[k]/d3;
                #pragma omp atomic
                forces[i][k] += f;
                #pragma omp atomic
                forces[j][k] -= f;
           }           
           ene += -1.0/d;         
       }
    }
 }
}

解決了,原來我需要的是

#pragma omp parallel for nowait

也不需要“原子”。

奇怪的解決方案,我不完全理解它是如何工作的,但它也確實 output 文件有 0 個損壞的結果。

暫無
暫無

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

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