2013-06-20 4 views
0

벡터에서 가장 작은 숫자를 계산하고 모든 프로세스에 브로드 캐스팅하는 자체 MPI 함수를 작성하려고합니다. 프로세스를 이진 트리로 처리하고 잎에서 루트로 이동할 때 최소값을 찾습니다. 그런 다음 나는 그 뿌리에서 자녀들을 통해 나뭇잎으로 메시지를 보낸다. 하지만 3벡터에서 최소값을 찾는 MPI 자체 코드

void Communication::ReduceMin(double &partialMin, double &totalMin) 
{ 
    MPI_Barrier(MPI_COMM_WORLD); 
    double *leftChild, *rightChild; 
    leftChild = (double *)malloc(sizeof(double)); 
    rightChild = (double *)malloc(sizeof(double)); 
    leftChild[0]=rightChild[0]=1e10; 
    cout<<"COMM REDMIN: "<<myRank<<" "<<partialMin<<" "<<nProcs<<endl; 
    MPI_Status *status; 
    //MPI_Recv from 2*i+1 amd 2*i+2 
    if(nProcs > 2*myRank+1) 
    { 
     cout<<myRank<<" waiting from "<<2*myRank+1<<" for "<<leftChild[0]<<endl; 
     MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, MPI_COMM_WORLD, status);    //SEG FAULT HERE 
     cout<<myRank<<" got from "<<2*myRank+1<<endl; 
    } 
    if(nProcs > 2*myRank+2) 
    { 
     cout<<myRank<<" waiting from "<<2*myRank+2<<endl; 
     MPI_Recv((void *)rightChild, 1, MPI_DOUBLE, 2*myRank+2, 2*myRank+2, MPI_COMM_WORLD, status); 
     cout<<myRank<<" got from "<<2*myRank+1<<endl; 
    } 
    //sum it up 
    cout<<myRank<<" finding the min"<<endl; 
    double myMin = min(min(leftChild[0], rightChild[0]), partialMin); 
    //MPI_Send to (i+1)/2-1 
    if(myRank!=0) 
    { 
     cout<<myRank<<" sending "<<myMin<<" to "<<(myRank+1)/2 -1 <<endl; 
     MPI_Send((void *)&myMin, 1, MPI_DOUBLE, (myRank+1)/2 - 1, myRank, MPI_COMM_WORLD); 
    } 

    double min; 
    //MPI_Recv from (i+1)/2-1 
    if(myRank!=0) 
    { 
     cout<<myRank<<" waiting from "<<(myRank+1)/2-1<<endl; 
     MPI_Recv((void *)&min, 1, MPI_DOUBLE, (myRank+1)/2 - 1, (myRank+1)/2 - 1, MPI_COMM_WORLD, status); 
     cout<<myRank<<" got from "<<(myRank+1)/2-1<<endl; 
    } 
    totalMin = min; 
    //MPI_send to 2*i+1 and 2*i+2 
    if(nProcs > 2*myRank+1) 
    { 
     cout<<myRank<<" sending to "<<2*myRank+1<<endl; 
     MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+1, myRank, MPI_COMM_WORLD); 
    } 
    if(nProcs > 2*myRank+2) 
    { 
     cout<<myRank<<" sending to "<<2*myRank+1<<endl; 
     MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+2, myRank, MPI_COMM_WORLD); 
    } 
} 

PS 0에서 위 단 4 프로세스와 실행의 과정 순위 1의 (공정 순위 3) 나는 왼쪽 아이의 최소값을받을려고 세그먼트 오류를 ​​얻을 : 나는 내가

MPI_Barrier(MPI_COMM_WORLD); 
MPI_Reduce((void *)&partialMin, (void *)&totalMin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); 
MPI_Bcast((void *)&totalMin, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

을 사용할 수 있습니다 알고하지만 재미를 위해 내 자신의 코드를 작성합니다.

+1

실제로 전달할 수있는 것은'M PI_Allreduce' 행. C++의 범위 지정 규칙이 정확히 어떻게 작동하는지 잘 모르겠지만 '& min'은 같은 이름을 가진 로컬 변수의 주소 대신'min' 함수의 주소를 반환 할 수 있습니다. –

+0

@HristoIliev가 언급했듯이 내장 함수를 사용하는 대신 자신의 함수를 작성하도록 설정했다면, 아마도 더 많은 디버깅 정보를 제공해야 할 것입니다. gdb/ddd/TotalView를 사용하여 segfaulting을 정확히하는 이유를 더 잘 이해하려고 시도 했습니까? –

+0

정보를 제공해 주셔서 감사합니다. 나는 gdb를 사용했고, 나는 그것이 seg라는 것을 안다. MPI Recv 문에서 오류가 발생했습니다. 나는 더 깊이 파지 않았다. 내가 프로젝트에서 늦은 이래로, 나는 MPI_Allreduce()를 사용했다. 나는 내 자신의 구현을 얼마 동안 재개 할 것이다. – Shank

답변

0

수신 호출에서 상태 인수를 사용하는 방식에 오류가 있습니다. 대신 MPI_Status 인스턴스의 주소를 전달하는, 당신은 단순히 초기화되지 않은 포인터를 전달하고 그 충돌에 이르게 : 당신이하지 않기 때문에

MPI_Status status; 
... 
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, &status); 

:

MPI_Status *status; // status declared as a pointer and never initialised 
... 
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, status); // status is an invalid pointer here 

당신은 당신의 코드를 변경해야 코드의 모든 상태를 조사하면 모든 호출에서

MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
관련 문제