2012-01-17 2 views
2

각 행이 점을 나타내고 각 열이이 점과 데이터의 다른 모든 점 사이의 거리이고 거리가 매우 먼 거리 행렬을 구축하고 있습니다. 알고리즘은 순차적으로 매우 잘 작동합니다. 그러나 병렬화하려고하면 세분화 오류 오류가 발생합니다. 다음은 내 데이터가 모두 포함 된지도 인 parallel에 대한 코드입니다. 여기에 어떤 도움을 주시면 감사하겠습니다. 그것은 당신의 코드 유일한 문제이지만, 표준 컨테이너 (예 : std::map와 같은) 당신이 그들에 기록 적어도 경우 스레드가되지 않은 경우segmentation fault openmp error

map< int,string >::iterator datIt; 
map< int,string >::iterator datIt2; 
map <int, map< int, double> > dist; 
int mycont=0; 
datIt=dat.begin(); 
int size=dat.size(); 
#pragma omp parallel //construct the distance matrix 
{ 
    #pragma omp for 
    for(int i=0;i<size;i++) 
    { 
    datIt2=dat.find((*datIt).first); 
    datIt2++; 
    while(datIt2!=dat.end()) 
    { 
     double ecl=0; 
     int c=count((*datIt).second.begin(),(*datIt).second.end(),delm)+1; 
     string line1=(*datIt).second; 
     string line2=(*datIt2).second; 
     for (int i=0;i<c;i++) 
     { 
     double num1=atof(line1.substr(0,line1.find_first_of(delm)).c_str()); 
     line1=line1.substr(line1.find_first_of(delm)+1).c_str(); 
     double num2=atof(line2.substr(0,line2.find_first_of(delm)).c_str()); 
     line2=line2.substr(line2.find_first_of(delm)+1).c_str(); 
     ecl += (num1-num2)*(num1-num2); 
     } 
     ecl=sqrt(ecl); 
     dist[(*datIt).first][(*datIt2).first]=ecl; 
     dist[(*datIt2).first][(*datIt).first]=ecl; 
     datIt2++; 
    } 
    datIt++; 
    } 
} 
+2

우리가 해당 코드를 디버깅 할 것으로 예상된다면 충돌이 발생할 때 최소한 스택 추적을 제공 할 수 있습니다. – NPE

+0

최소한 코드를 게시하기 전에 들여 쓰기를하십시오. –

답변

3

는 잘 모르겠어요. 따라서 과 같이 maps과 같은 쓰기 권한이있는 경우 #pragm omp critical 또는 mutexes (omp 뮤텍스 또는 부스트 또는 C++ 11을 사용하는 경우 boost::mutex을 사용하여 동기화 구조의 일종으로지도에 대한 액세스를 래핑해야합니다. 또는 std::mutex 옵션)가 너무 없습니다 : 당신은 단지 dat 읽기 때문에

//before the parallel: 
omp_lock_t lock; 
omp_init_lock(&lock); 
... 

omp_set_lock(&lock); 
dist[(*datIt).first][(*datIt2).first]=ecl; 
dist[(*datIt2).first][(*datIt).first]=ecl; 
omp_unset_lock(&lock); 
... 

//after the parallel: 
omp_destroy_lock(&lock); 

그것이 동기화 해하지 않고 잘해야한다 (이 더있다 C++ (11)는 적어도, C++ 03 무엇이든지 threadsafety에 대한 보장이 없습니다에 (때문에 스레드의 개념). 동기화 없이는 사용하는 것이 일반적으로 좋지만 기술적으로는 구현에 따라 달라집니다.

또한 공유 데이터를 지정하지 않았기 때문에 parallel 영역 외부에서 선언 된 모든 변수는 기본적으로 공유됩니다. 따라서 datItdatIt2에 대한 쓰기 권한도 경쟁 조건을 나타냅니다. 당신이 반복 할 보이기 때문에, datIt이 해결

map< int,string >::iterator datIt2=dat.find((*datIt).first); 

좀 더 문제가된다 datIt2를 들어이 처음 사용 시점을 선언하는 더 나은조차 비공개로를 지정, 또는 중 하나를 방지 할 수 있습니다 지도의 전체 길이

#pragma omp parallel //construct the distance matrix 
{ 
    map< int,string >::iterator datItLocal=datIt; 
    int lastIdx = 0; 
    for(int i=0;i<size;i++) 
    { 
     std::advance(datItLocal, i - lastIdx); 
     lastIdx = i; 
     //use datItLocal instead of datIt everytime you reference datIt in the parallel 
    //remove ++datIt 
    } 
} 

: (O(n) 사전에 각각의 반복을 사용하여 지나치게 비용이 많이 드는되지 않습니다) 가장 쉬운 방법은 (그냥 빨리 개요 100 %의 정확성을 보장하지 않음) 따라 진행되는 datIt의 개인 사본에서 작동하도록 보인다 이 방법은지도가 반복됩니다 omp_get_num_threads() 번,하지만 작동합니다. 이것이 허용 할 수없는 오버 헤드라면, this answer of mine에서 openmp의 bidirectional iterator에서 루핑을위한 대체 솔루션을 찾아보십시오.

사이드로 : 어쩌면 내가 놓친 것 같지만 datItdat에있는 반복기라고 생각하면 dat.find(datIt->first)은 조금 반복됩니다. 맵에 지정된 키가있는 요소가 하나만 있어야하고 datIt 포인트이므로 datIt2=datIt (비싸면 저를 고치십시오)와 같이 비싸게 보입니다.

2

Girzzly의 답변 외에도 비공개 또는 공유를 지정하지 않았습니다. 이것은 보통 당신이 당신의 기억의 접근을 통제하지 않는다는 것을 의미합니다. 병렬 영역을 입력 할 때 datIt firstprivate와 datIt2을 private로 정의해야합니다. 그렇지 않으면 everythread가 공유 값을 덮어 씀으로써 segfault가됩니다.

잠금을 사용하는 대신 중요한 섹션 인 openmpish를 사용합니다.

+0

일반적으로 코드의 다른 지점에서 공유 데이터 구조에 대한 액세스를 추가하려고 할 수 있으므로 잠금을 사용하여 중요한 섹션에 대한 잠금을 선호합니다. 잠금을 사용하여 쉽게 작업 할 수는 있지만 중요한 섹션에서는 쉽지 않습니다 서로 다른 중요한 섹션이 서로 동기화됩니다 (제 지식에 따라). 그러나 나는 alsways RAII 클래스에서 잠금 코드를 래핑 할 것이고, 나는 간략하게하기 위해 샘플에서하지 않았다. 내 대답에 'datIt'에 대한 요점을 추가하면 괜찮 으면 좋겠다. – Grizzly

+0

괜찮아. OOC 코드에서 openmp를 광범위하게 사용하지 않았습니다. 그 이후로 코드가 한 번에 한 스레드 씩 실행되므로 서로 동기화하여 무엇을 의미하는지 확신 할 수 없습니다. 또한 임계 구역 전후에 암시 적 플러시가 호출되므로 모든 사람이 최신 상태로 유지됩니다. – Bort

+0

100 % 확신 할 수는 없지만 소스 코드의 다른 부분에서 액세스하면 공유 섹션에 대한 액세스를 보호 할 수 없습니다. 단 하나의 스레드 만 같은 시간에 주어진 중요한 섹션을 동시에, 다른 중요한 섹션 beeing에 대한 금지가 없습니다 (나는 그것이 정말로 낭비 것 같다면). 따라서 중요한 섹션은 특정 데이터 구조 대신 코드의 특정 위치를 보호합니다. 그것은 나에게 좋은 생각처럼 보이지 않습니다. – Grizzly

관련 문제