Mpi_Send и Mpi_Recv отправлять разделы матрицы вместо рассеяния - PullRequest
0 голосов
/ 24 января 2012

Я пытаюсь отправить разделы матрицы NxN другому процессу. Мне удалось это с помощью MPI_Scatterv, как вы можете видеть в приведенном ниже коде, но если я попытаюсь использовать вместо MPI_Send и MPI_Recv, результатом будет segfault,Зачем?Я видел разные похожие вопросы к этому, например, это Матрица MPI с динамическим распределением: Seg.Ошибка , но ничего не меняется ...

n = N/nprocs;   
n0 = n + N - n*nprocs;
int counts[nprocs], displs[nprocs];
counts[0] = n0*N;
displs[0] = 0;
for(i=1;i<nprocs;i++){
    counts[i]=n*N;
    displs[i]=(n0+(i-1)*n)*N;
}       
double * weights = (double *)calloc(N*N, (sizeof(double)));
if(myid == 0){
    n = n0;      
    for(i=0; i<N; i++){
        for(j=i; j<N; j++){
            if(i==j) *(weights+i*N+j) = 0;
            else {
               *(weights+i*N+j) = rand() / (RAND_MAX+1.0);
               *(weights+j*N+i) = *(weights+i*N+j);
            }
        }
    }
} 
double * partition = (double *)calloc(n*N, (sizeof(double)));
MPI_Scatterv(weights, counts, displs, MPI_DOUBLE, partition, n*N, MPI_DOUBLE, 0, COMM);

Вместо этого используются примитивы send и recv:

if(myid==0){
    for(i=0; i<nprocs; i++)
        MPI_Send(weights+displs[i], counts[i], MPI_DOUBLE, i, 0, COMM); 
}
MPI_Recv(partition, counts[myid], MPI_DOUBLE, 0, 0, COMM, status);

Что не так?Заранее спасибо ... ps: простите за мой английский!

1 Ответ

0 голосов
/ 24 января 2012

Это очень незначительная проблема;хотя я не вижу определения переменной, я сильно подозреваю, что строка MPI_Recv должна быть MPI_Recv(..., COMM, &status).

Однако есть еще одна проблема;задача должна избегать отправки сообщений себе, и она должна не выдавать блокирующую отправку (например, MPI_Send против MPI_Isend) для себя;для достаточно больших сообщений, отправка которых будет заблокирована, задача 0 отправляет блокирующую отправку, но пока не получает ее активно.

Примерно так будет работать:

if(myid==0){
    for(i=1; i<nprocs; i++)
        MPI_Send(weights+displs[i], counts[i], MPI_DOUBLE, i, 0, COMM);

    memcpy(weights+displs[0], partition, counts[0]*sizeof(double));
} else {
    MPI_Recv(partition, counts[myid], MPI_DOUBLE, 0, 0, COMM, &status);
}

Обратите внимание, что на практикенезависимо от того, MPI_Scatterv должен быть таким же быстрым или быстрым, как отправка по циклу.

...