みなさん、良い一日を!
私は分子動力学シミュレーションを行っていますが、最近、それを並行して実装しようと試み始めました。一見するとすべてが単純に見えます: 最も時間のかかるループの前に #pragma omp parallel for ディレクティブを記述します。しかし、たまたま、これらのループ内の関数は配列、または正確には、粒子システムに関するすべての情報とこのシステムで動作する関数を含むクラスのオブジェクトに属する配列で動作するため、 #最も時間のかかるループの 1 つの前に pragma ディレクティブを追加すると、2 コア 4 スレッド プロセッサが完全にロードされたという事実にもかかわらず、計算時間は実際には数倍増加しました。
これを整理するために、別のより単純なプログラムを作成しました。このテスト プログラムは、2 つの同一のループを実行します。1 つは並列で、もう 1 つはシリアルです。これらのループの両方を実行するのにかかる時間が測定されます。結果は私を驚かせました.最初のループが並列で計算されるときはいつでも、その計算時間はシリアルモードと比較して減少しました (それぞれ 1500 および 6000 ミリ秒) が、2 番目のループの計算時間は大幅に増加しました (シリアルの 6000 に対して 15 000)。
private() 句と firstprivate() 句を使用しようとしましたが、結果は同じでした。とにかく、並列領域の前に定義および初期化されたすべての変数を自動的に共有するべきではありませんか? 2 番目のループの計算時間は、別のベクトル vec2 で実行すると通常に戻りますが、反復ごとに新しいベクトルを作成することは明らかにオプションではありません。また、vec1 の実際の更新を #pragma omp クリティカル エリアに入れようとしましたが、それもうまくいきませんでした。どちらも Shared(vec1) 句の追加に役立ちませんでした。
私の誤りを指摘し、適切な方法を示していただければ幸いです。
その private(i) をコードに入れる必要がありますか?
このテストプログラムは次のとおりです。
#include "stdafx.h"
#include <omp.h>
#include <array>
#include <time.h>
#include <vector>
#include <iostream>
#include <Windows.h>
using namespace std;
#define N1 1000
#define N2 4000
#define dim 1000
int main(){
vector<int>res1,res2;
vector<double>vec1(dim),vec2(N1);
clock_t t, tt;
int k=0;
for( k = 0; k<dim; k++){
vec1[k]=1;
}
t = clock();
#pragma omp parallel
{
double temp;
int i,j,k;
#pragma omp for private(i)
for( i = 0; i<N1; i++){
for(j = 0; j<N2; j++){
for( k = 0; k<dim; k++){
temp+= j;
}
}
vec1[i]+=temp;
temp = 0;
}
}
tt = clock();
cout<<tt-t<<endl;
for(int k = 0; k<dim; k++){
vec1[k]=1;
}
t = clock();
for(int g = 0; g<N1; g++){
for(int h = 0; h<N2; h++){
for(int y = 0; y<dim; y++){
vec1[g]+=h;
}
}
}
tt = clock();
cout<<tt-t<<endl;
getchar();
}
お時間をいただきありがとうございます!
PS 私は Visual Studio 2012 を使用しています。プロセッサは Intel Core i3-2370M です。私のアセンブリファイルは2つの部分に分かれています: