2014-10-30 14 views
0

하이퍼 큐브 그룹에 속한 프로세스간에 값을 분산하려고합니다 (quicksort 프로젝트). 프로세스의 양에 따라 과도한 프로세스를 제외하고 새로운 커뮤니케이터를 생성하거나 정확하게 하이퍼 큐브 (2의 거듭 제곱)에 맞는 MPI_COMM_WORLD를 복제합니다. 두 경우MPI_Scatterv : 프로세스 0의 분할 오류 11

, 데이터를 수신 0 이외 처리하지만 : - 첫 번째 시나리오에서, 프로세스 0 세그멘테이션 오류 11 슬로우 - 번째 시나리오 아무것도 결함 온하지만 프로세스 0 값 무의미한이다 받았다.

참고 : 일반 MPI_Scatter를 시도하면 모든 것이 잘 작동합니다. 우선

//Input 
vector<int> LoadFromFile(); 

int d;      //dimension of hypercube 
int p;      //active processes 
int idle;     //idle processes 
vector<int> values;   //values loaded 
int arraySize;    //number of total values to distribute 

int main(int argc, char* argv[]) 
{  
int mpiWorldRank; 
int mpiWorldSize; 

int mpiRank; 
int mpiSize; 

MPI_Init(&argc, &argv); 

MPI_Comm_rank(MPI_COMM_WORLD, &mpiWorldRank); 
MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); 
MPI_Comm MPI_COMM_HYPERCUBE; 

d = log2(mpiWorldSize);  
p = pow(2, d);     //Number of processes belonging to the hypercube 
idle = mpiWorldSize - p;  //number of processes in excess 
int toExclude[idle];   //array of idle processes to exclude from communicator 
int sendCounts[p];    //array of values sizes to be sent to processes 

// 
int i = 0; 
while (i < idle) 
{ 
    toExclude[i] = mpiWorldSize - 1 - i; 
    ++i; 
} 

//CREATING HYPERCUBE GROUP: Group of size of power of 2 ----------------- 
MPI_Group world_group; 
MPI_Comm_group(MPI_COMM_WORLD, &world_group); 

// Remove excessive processors if any from communicator 
if (idle > 0) 
{ 
    MPI_Group newGroup;  
    MPI_Group_excl(world_group, 1, toExclude, &newGroup); 
    MPI_Comm_create(MPI_COMM_WORLD, newGroup, &MPI_COMM_HYPERCUBE); 
    //Abort any processor not part of the hypercube.  
    if (mpiWorldRank > p) 
    { 
     cout << "aborting: " << mpiWorldRank <<endl; 
     MPI_Finalize(); 
     return 0; 
    } 
} 
else 
{ 
    MPI_Comm_dup(MPI_COMM_WORLD, &MPI_COMM_HYPERCUBE); 
} 

MPI_Comm_rank(MPI_COMM_HYPERCUBE, &mpiRank); 
MPI_Comm_size(MPI_COMM_HYPERCUBE, &mpiSize); 
//END OF: CREATING HYPERCUBE GROUP -------------------------- 

if (mpiRank == 0) 
{ 
    //STEP1: Read input 
    values = LoadFromFile(); 
    arraySize = values.size(); 
} 

//Transforming input vector into an array 
int valuesArray[values.size()]; 
if(mpiRank == 0) 
{ 
    copy(values.begin(), values.end(), valuesArray); 
} 

//Broadcast input size to all processes 
MPI_Bcast(&arraySize, 1, MPI_INT, 0, MPI_COMM_HYPERCUBE); 

//MPI_Scatterv: determining size of arrays to be received and displacement 
int nmin = arraySize/p; 
int remainingData = arraySize % p; 
int displs[p]; 
int recvCount; 

int k = 0; 
for (i=0; i<p; i++) 
{ 
    sendCounts[i] = i < remainingData 
     ? nmin+1 
     : nmin; 
    displs[i] = k; 
    k += sendCounts[i]; 
} 

recvCount = sendCounts[mpiRank]; 
int recvValues[recvCount]; 

//Following MPI_Scatter works well:  
// MPI_Scatter(&valuesArray, 13, MPI_INT, recvValues , 13, MPI_INT, 0, MPI_COMM_HYPERCUBE); 

MPI_Scatterv(&valuesArray, sendCounts, displs, MPI_INT, recvValues , recvCount, MPI_INT, 0, MPI_COMM_HYPERCUBE); 

int j = 0; 
while (j < recvCount) 
{ 
    cout << "rank " << mpiRank << " received: " << recvValues[j] << endl; 
    ++j; 
} 

MPI_Finalize(); 
return 0; 
} 
+0

내가 검사 오류를 추가 : std::vector<T> 그러므로 정기적 배열에 요소를 복사하지 않고 할 수있는 간단 MPI_Scatter(v)에 대한 호출의 첫 번째 요소의 주소를 제공, 연속 된 저장소를 사용 실패 할 수있는 모든 작업과 많은 디버그 출력 (printf 또는 이와 유사한) 값이 예상되는 것이 아니거나 연산이 실패 할 경우 오버플로 될 수있는 배열이 많이 있습니다. 다중 프로세스를 사용하면 코드를 수동으로 읽음으로써 디버그를 훨씬 더 어렵게하거나 불가능하게 만들 수 있습니다. – uesp

답변

1

, 당신은 MPI_Group_excl에 잘못된 인수를 공급하고 있습니다 :

MPI_Group_excl(world_group, 1, toExclude, &newGroup); 
//      ^

두 번째 인수는 제외 목록의 항목 수를 지정하기 때문에 idle 같아야한다. 단일 순위 만 제외하고 있기 때문에 결과 그룹의 순위는 이므로 MPI_ScattervsendCounts[]displs[]에 많은 요소가 있다고 예상합니다. 그 중 단지 p 요소는 올바르게 초기화되고 나머지는 무작위이므로 MPI_Scatterv이 루트에서 충돌합니다.

또 다른 오류는 유휴 프로세스를 중단하는 코드입니다. if (mpiWorldRank >= p)이어야합니다.

나는 전체 제외 코드 대신 MPI_Comm_split에 단일 호출로 대체하는 것이 좋습니다 것입니다 :

MPI_Comm comm_hypercube; 
int colour = mpiWorldRank >= p ? MPI_UNDEFINED : 0; 

MPI_Comm_split(MPI_COMM_WORLD, colour, mpiWorldRank, &comm_hypercube); 
if (comm_hypercube == MPI_COMM_NULL) 
{ 
    MPI_Finalize(); 
    return 0; 
} 

어떤 과정 공급의 색상과 같은 MPI_UNDEFINED는 통화가 MPI_Comm_dup에 해당하지 않는 경우.

MPI_으로 시작하는 코드 이름은 MPI 구현의 기호와 충돌 할 수 있으므로 사용하지 마십시오.

추가 참고 :

MPI_Scatterv(&values[0], ...); 
+0

감사합니다. 작동하며 매우 유용했습니다! – Aymeric