2011-03-28 4 views
0

MPI를 배우기 위해 병렬 정렬 프로그램을 만들고 MPI_Scatter에 문제가 있습니다. 내가 실행하려고 할 때마다, 나는 다음과 같은 얻을 : 나는 문제가 있어요 왜MPI_Scatter Segfaulting

reading input 
Scattering input 
_pmii_daemon(SIGCHLD): [NID 00012] PE 0 exit signal Segmentation fault 
[NID 00012] 2011-03-28 10:12:56 Apid 23655: initiated application termination 

다른 질문에서 기본 보면 정말 대답하지 않았다 - 배열이 연속하고, 그래서 문제가 없어야합니다 불연속 메모리 액세스, 그리고 올바른 순서로 올바른 포인터를 전달 해요. 누구든지 아이디어가 있습니까?

소스 코드가 아래입니다. - 변수 입력 및 순위 크기를 아직 처리하고 싶지 않기 때문에 특정 숫자로 지정되었습니다.

#include <mpi.h> 

#include <iostream> 
using std::endl; 

using std::cout; 

#include <fstream> 
using std::ifstream; 
using std::ofstream; 
#include <algorithm> 
using std::sort; 

#define SIZEOF_INPUT 10000000 
#define NUMTHREADS 100 
#define SIZEOF_SUBARRAY SIZEOF_INPUT/NUMTHREADS 

int main(int argc, char** argv){ 
    MPI_Init(&argc, &argv); 

    int input[SIZEOF_INPUT]; 
    int tempbuf[SIZEOF_SUBARRAY]; 

    int myRank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &myRank); 

    /* 
      Read input from file 
    */ 
    if(myRank == 0){ 
      cout << "reading input" << endl; 
      ifstream in(argv[1]); 
      for(int i = 0; i < SIZEOF_INPUT; ++i) 
        in >> input[i]; 
      cout << "Scattering input" << endl; 
    } 

    // Scatter, Sort, and Gather again  
    MPI_Scatter(input,SIZEOF_INPUT,MPI_INT,tempbuf,SIZEOF_SUBARRAY,MPI_INT,0,MPI_COMM_WORLD); 
    cout << "Rank " << myRank << "Sorting" << endl; 
    sort(tempbuf,tempbuf+SIZEOF_SUBARRAY); 
    MPI_Gather(tempbuf,SIZEOF_SUBARRAY,MPI_INT,input,SIZEOF_INPUT,MPI_INT,0,MPI_COMM_WORLD); 

    if(myRank == 0){ 
      cout << "Sorting final output" << endl; 
      // I'm doing a multi-queue merge here using tricky pointer games 

      //list of iterators representing things in the queue 
      int* iterators[NUMTHREADS]; 
      //The ends of those iterators 
      int* ends[NUMTHREADS]; 

      //Set up iterators and ends 
      for(int i = 0; i < NUMTHREADS; ++i){ 
        iterators[i] = input + (i*SIZEOF_SUBARRAY); 
        ends[i] = iterators[i] + SIZEOF_SUBARRAY; 
      } 

      ofstream out(argv[2]); 
      int ULTRA_MAX = SIZEOF_INPUT + 1; 
      int* ULTRA_MAX_POINTER = &ULTRA_MAX; 
      while(true){ 
        int** curr_min = &ULTRA_MAX_POINTER; 
        for(int i = 0 ; i < NUMTHREADS; ++i) 
          if(iterators[i] < ends[i] && *iterators[i] < **curr_min) 
            curr_min = &iterators[i]; 

        if(curr_min == &ULTRA_MAX_POINTER) break; 

        out << **curr_min << endl; 
        ++(*curr_min); 
      } 
    } 

    MPI_Finalize(); 
} 

모든 도움을 주시면 감사하겠습니다. 감사 자크는

+0

분명하지만 코드에서 사용하는 것과 동일한 수의 프로세스를 생성 하시겠습니까? – suszterpatt

+0

@suszterpatt 예, 있습니다. 그래도 좋은 생각이야 –

답변

3

하아! 이걸 보러 잠시 나갔어.

트릭이 MPI_Scatter에서 프로세스로 전송할 총 금액이 아닌 총 금액입니다. 모이는 것과 동일합니다. 그것은 각각에서받는 금액입니다. 즉, 카운트가있는 것은 MPI_Scatterv과 같습니다. 카운트는 각 프로세스에 있지만,이 경우에는 동일하다고 가정합니다. 나를 위해

그래서이

MPI_Scatter(input,SIZEOF_SUBARRAY,MPI_INT,tempbuf,SIZEOF_SUBARRAY,MPI_INT,0,MPI_COMM_WORLD); 
cout << "Rank " << myRank << "Sorting" << endl; 
MPI_Gather(tempbuf,SIZEOF_SUBARRAY,MPI_INT,input,SIZEOF_SUBARRAY,MPI_INT,0,MPI_COMM_WORLD); 

작품.

또한 큰 스택을 스택에 할당하는 데주의하십시오. 나는 이것이 단지 예시 문제라는 것을 알고 있지만, 나를 위해 이것은 바로 충돌을 야기하고 있었다. 동적으로 수행 중임

int *input = new int[SIZEOF_INPUT]; 
int *tempbuf = new int[SIZEOF_SUBARRAY]; 
//.... 
delete [] input; 
delete [] tempbuf; 

이 문제를 해결했습니다.

+0

시도해 보니 완벽하게 작동했습니다. 또한 MPI_Gather를 사용했을 때의 문제점을 해결했습니다.큰 배열에 관해서는, 저는 Cray 기계에서 이것을하고 있습니다, 그래서 기억은 문제가 아니지만, 나는 미래의 일에 주목할 것입니다. 고마워요! –

1
int* iterators[NUMTHREADS]; 
//The ends of those iterators 
int* ends[NUMTHREADS]; 

//Set up iterators and ends 
for(int i = 0; i < NUMTHREADS; ++i){ 
     iterators[i] = input + (i*SIZEOF_SUBARRAY); // problem 
     ends[i] = iterators[i] + SIZEOF_SUBARRAY; // problem 
} 

iterators and ends 어디 또는 쓰레기없는 가리키는 정수 포인터의 배열입니다. 그러나 for 루프가 어떤 위치를 가리키는 것처럼 값을 유지하려고 시도하면 세그먼트 화 오류이 발생합니다. 프로그램은 먼저 메모리를 할당해야하며, 반복자가 가리킬 수있는 위치에 값을 유지해야합니다.

for(int i=0 ; i < NUMTHREADS; ++i) 
{ 
    iterators[i] = new int; 
    end[i] = new int ; 
} 
// Now do the earlier operation which caused problem 

프로그램 (즉, new에서 인수), 더 이상 필요하지 않을 때 delete[]를 사용하여 무료 저장소에 자원을 반환해야 자원을 관리하기 때문에. 아주 쉽게 리소스를 관리하는 대신 std :: vector를 사용하십시오.

+0

이 경우 segfault는 MPI_Scatter()에서 발생하지만이 줄에서는 발생하지 않습니다. 또한 반복자와 끝은 스택에 할당 된 int 포인터 배열입니다. 그들은 정크 데이터로 시작하지만, 후속 루프에서 나는 MPI_Gather()에서 나에게 주어진 결과 배열 조각에 포인터를 할당한다. 이것은 대답이 아닙니다. –

+0

@Zach H - 코드에서 볼 수 있듯이, iterator와 ends는 모두'if' 문에서 선언 된 ** 초기화되지 않은 ** 로컬 변수 ** 포인터 배열입니다. – Mahesh