많은 반복을 실행하는 코드가 있으며 조건이 충족되는 경우에만 반복 결과가 저장됩니다. 이것은 자연스럽게 while 루프로 표현됩니다. 각 실현은 독립적이기 때문에 코드를 병렬로 실행하려고합니다. 그래서이있다 :OpenMP while 루프
while(nit<avit){
#pragma omp parallel shared(nit,avit)
{
//do some stuff
if(condition){
#pragma omp critical
{
nit++;
\\save results
}
}
}//implicit barrier here
}
를이 잘 작동하지만 의미 각각 실현 후 장벽이 있다는 것을 내가 병렬 블록 내에서 일을하고있는 물건이 더 이상 다른 사람보다 하나의 반복에 걸리는 경우, 모든 스레드는 다음 반복을 계속하는 대신 완료되기를 기다리고 있습니다.
스레드가 계속 작동하도록이 장벽을 피할 방법이 있습니까? 나는 수천 번의 반복을 평균하고있다. 따라서 더 많은 상처를 입지 않는다. (nit
변수가 이미 실행중인 스레드에서 증가하지 않은 경우) ...
나는 이것을 병렬로 바꾸려고 노력했다. for 루프가 자동으로 증가하면 nit
변수가 변경됩니다. 이것은 나의 시도 :
#pragma omp parallel shared(nit,avit)
{
#pragma omp for
for(nit=0;nit<avit;nit++){
//do some stuff
if(condition){
\\save results
} else {
#pragma omp critical
{
nit--;
}
}
}
}
그리고 예상대로 작동 및 루프의 주위에가는 유지하지만 하나가 다른 스레드에 의해 그것의 증가와 감소를 기대할 수 있기 때문에 내 nit
변수는 ... 예측할 수없는 값을 사용합니다 다른 시간에.
...
incr=0;
for(nit=0;nit<avit;nit+=incr)
...
하지만 같은, 컴파일, 또는 루프의에는 증가가없는 내 코드를 속이려하지 않습니다 내 코드가 충돌합니다 ...
아이디어가 있으십니까?
감사
편집 : 여기에 while 루프의 코드의 작업 최소한의 예제는 :
#include <random>
#include <vector>
#include <iostream>
#include <time.h>
#include <omp.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main(){
int nit,dit,avit=100,t,j,tmax=100,jmax=10;
vector<double> Res(10),avRes(10);
nit=0; dit=0;
while(nit<avit){
#pragma omp parallel shared(tmax,nit,jmax,avRes,avit,dit) private(t,j) firstprivate(Res)
{
srand(int(time(NULL))^omp_get_thread_num());
t=0; j=0;
while(t<tmax&&j<jmax){
Res[j]=rand() % 10;
t+=Res[j];
if(omp_get_thread_num()==5){
usleep(100000);
}
j++;
}
if(t<tmax){
#pragma omp critical
{
nit++;
for(j=0;j<jmax;j++){
avRes[j]+=Res[j];
}
for(j=0;j<jmax;j++){
cout<<avRes[j]/nit<<"\t";
}
cout<<" \t nit="<<nit<<"\t thread: "<<omp_get_thread_num();
cout<<endl;
}
} else{
#pragma omp critical
{
dit++;
cout<<"Discarded: "<<dit<<"\r"<<flush;
}
}
}
}
return 0;
}
나는 다른 사람보다 오래 걸리는 하나 개의 스레드를 시뮬레이션 할
usleep
부분을 추가했다. 프로그램을 실행하면 모든 스레드가 스레드 5가 완료 될 때까지 기다린 후 다음 실행을 시작합니다. 내가 뭘하려고하는지 정확하게 기다리는 것을 피하는 것입니다. 즉, 다른 스레드가 5를 끝내기를 기다리지 않고 다음 반복을 선택하고 싶습니다. 또한 중요한 지역으로 작동
int nit = 0;
#pragma omp parallel
while(1) {
int local_nit;
#pragma omp atomic read
local_nit = nit;
if (local_nit >= avit) {
break;
}
[...]
if (...) {
#pragma omp critical
{
#pragma omp atomic capture
local_nit = ++nit;
for(j=0;j<jmax;j++){
avRes[j] += Res[j];
}
for(j=0;j<jmax;j++){
// technically you could also use `nit` directly since
// now `nit` is only modified within this critical section
cout<<avRes[j]/local_nit<<"\t";
}
}
} else {
#pragma omp atomic update
dit++;
}
}
을하지만, 아토 더 효율적입니다 :
* 일부 항목 *에 대해 더 구체적으로 이해하지 않으면 질문에 올바르게 답변 할 수 없습니다. 특히 우리는 * 물건에 * 접근 할 수 있는지, 그리고 여러 스레드가 동시에 조건을 가지고있을 때 일어날 것인가, 아니면 하나의 스레드가 몇 가지 작업을하는 동안 여러 번 업데이트되는 것을 생각할 필요가 없습니다 * ... 어렵습니다. 그러나 훌륭하고 구체적인 답변을 위해서는 [mcve]를 만들어야합니다. – Zulan
@Zulan 주석 주셔서 감사합니다. 끝에 최소한의 예제를 추가하기 위해 질문을 편집했습니다. 희망이 물건을 명확히합니다. –