32

非常に単純な for ループを並列化しようとしていますが、これは久しぶりに openMP を使用する試みです。実行時間に困惑しています。これが私のコードです:

#include <vector>
#include <algorithm>

using namespace std;

int main () 
{
    int n=400000,  m=1000;  
    double x=0,y=0;
    double s=0;
    vector< double > shifts(n,0);


    #pragma omp parallel for 
    for (int j=0; j<n; j++) {

        double r=0.0;
        for (int i=0; i < m; i++){

            double rand_g1 = cos(i/double(m));
            double rand_g2 = sin(i/double(m));     

            x += rand_g1;
            y += rand_g2;
            r += sqrt(rand_g1*rand_g1 + rand_g2*rand_g2);
        }
        shifts[j] = r / m;
    }

    cout << *std::max_element( shifts.begin(), shifts.end() ) << endl;
}

私はそれをコンパイルします

g++ -O3 testMP.cc -o testMP  -I /opt/boost_1_48_0/include

つまり、「-fopenmp」はありません。これらのタイミングが得られます。

real    0m18.417s
user    0m18.357s
sys     0m0.004s

「-fopenmp」を使用すると、

g++ -O3 -fopenmp testMP.cc -o testMP  -I /opt/boost_1_48_0/include

私は時間のためにこれらの数字を取得します:

real    0m6.853s
user    0m52.007s
sys     0m0.008s

私には意味がありません。8 コアを使用してもパフォーマンスが 3 倍しか向上しないのはなぜですか? ループを正しくコーディングしていますか?

4

4 に答える 4

38

andには OpenMPreduction句を使用する必要がxありyます。

#pragma omp parallel for reduction(+:x,y)
for (int j=0; j<n; j++) {

    double r=0.0;
    for (int i=0; i < m; i++){

        double rand_g1 = cos(i/double(m));
        double rand_g2 = sin(i/double(m));     

        x += rand_g1;
        y += rand_g2;
        r += sqrt(rand_g1*rand_g1 + rand_g2*rand_g2);
    }
    shifts[j] = r / m;
}

reduction各スレッドでは、最終的な値を取得するために、最終的にすべての部分的な値が合計されますxy

Serial version:
25.05s user 0.01s system 99% cpu 25.059 total
OpenMP version w/ OMP_NUM_THREADS=16:
24.76s user 0.02s system 1590% cpu 1.559 total

参照 - 超線形スピードアップ:)

于 2012-08-02T08:30:25.807 に答える
-3

せいぜい (!) 達成できるのは、線形の高速化です。Linuxの時間とどちらがどちらであるかは覚えていませんが、time.hまたは(C ++ 11の場合)「クロノ」を使用して、プログラムから直接ランタイムを測定することをお勧めします。コード全体をループにパックし、10 回実行して平均すると、プログラムによっておよそのランタイムが得られます。

さらに、並列プログラミングにおけるデータ局所性のパラダイムに準拠していない x、y に問題があります。

于 2012-08-02T07:51:40.400 に答える