Я пытаюсь разбить матрицу (массив) на несколько процессов.
Мой код основан на:
Использование ScatterV для разделения массива на несколько процессов
Мне нужно сделать это динамически. Когда я присваиваю значения sendcounts и displs статически работает нормально, но если я это сделаю, использование цикла завершится неудачно. Показывать только первые 5 элементов. Я не думаю, что это связано с MPI, но я не смогу заставить его работать.
Это код:
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROOT 0
#define N 5
/**
*
* With this row
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
*
* Assign portions to each process.
*
* Execution with 3 process
*
* From 0 to 4 assigned to process 0
* From 5 to 9 assigned to process 1
* From 10 to 24 assigned to process 2
*/
int *createMatrix(int nRows, int nCols) {
int *matrix;
int h, i, j;
if ((matrix = malloc(nRows * nCols * sizeof(int))) == NULL) {
printf("Malloc error:");
exit(1);
}
//Test values
for (h = 0; h < nRows * nCols; h++) {
matrix[h] = h;
}
return matrix;
}
void printArray(int *row, int nElements) {
int i;
for (int i = 0; i < nElements; i++) {
printf("%d ", row[i]);
}
printf("\n");
}
int main(int argc, char **argv) {
// for storing this process' rank, and the number of processes
int rank, np;
int i, j;
int begin, end;
int *matrix;
int *sendcounts, *displs, *recvbuf;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&np);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
//Initialize matrix
if (rank == ROOT) {
matrix = createMatrix(N, N);
printf("Initial matrix: \n");
printArray(matrix, N*N);
}
int lastRow;
int quotient = N / np;
int multiplicacion = quotient * np;
if (multiplicacion < N) {
lastRow = quotient + (N - (quotient * np));
} else {
lastRow = quotient;
}
printf("PROCESS: %d\n", rank);
printf("quotient: %d\n", quotient);
begin = rank * quotient;
if (rank == np -1) {
end = N - 1;
}else if (rank == ROOT) {
end = begin + quotient - 1 ;
}else {
end = (quotient * rank + quotient) - 1;
}
printf("begin: %d\n", begin);
printf("end: %d\n", end);
printf("total elements: %d\n", end - begin + 1);
//scatterv SECTION
//array with number of elements per process
sendcounts = malloc(np * sizeof(int));
//array with the initial address in the main vector (matrix)
displs = malloc(np * sizeof(int));
printf("Process %d, begin: %d\n", begin, rank);
//Using this option WORKS correct
sendcounts[0] = 5;
sendcounts[1] = 5;
sendcounts[2] = 15;
displs[0] = 0;
displs[1] = 5;
displs[2] = 10;
//Using this loop FAILS, assign the first 5 elements
//for (i = 0; i < np; i++){
// sendcounts[i] = (end - begin + 1) * 5;
// displs[i] = begin * N;
//}
printf("sendcounts[%d]: %d\n", rank, sendcounts[rank]);
printf("displs[%d]: %d\n", rank, displs[rank]);
recvbuf = malloc(sendcounts[rank] * sizeof(int));
for (i = 0; i < sendcounts[rank]; i++) {
recvbuf[i] = 0;
}
MPI_Scatterv(matrix, sendcounts, displs, MPI_INT, recvbuf, sendcounts[rank], MPI_INT, ROOT, MPI_COMM_WORLD);
printArray(recvbuf, sendcounts[rank]);
printf("\n");
free(recvbuf);
recvbuf=NULL;
MPI_Finalize();
return 0;
}
Любая идея, почему, если я использую этот код, он терпит неудачу:
for (i = 0; i < np; i++){
sendcounts[i] = (end - begin + 1) * 5;
displs[i] = begin * N;
}
спасибо
Desired output:
Initial matrix:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
PROCESS: 0
sendcounts[0]: 5
displs[0]: 0
0 1 2 3 4
PROCESS: 1
sendcounts[1]: 5
displs[1]: 5
5 6 7 8 9
PROCESS: 2
sendcounts[2]: 15
displs[2]: 10
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
ОБНОВЛЕНИЕ 1:
Я изменил код, чтобы включить инициализацию sendcounts и displs в ROOT, но проблема в том, что я теряю значения размеров recvbuf и размера recvbuf для каждого процесса.
int main(int argc, char **argv) {
// for storing this process' rank, and the number of processes
int rank, np;
int i, j;
int begin, end;
int *matrix;
int *sendcounts, *displs, *recvbuf;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&np);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
sendcounts = malloc(np * sizeof(int));
//array with the initial address in the main vector (matrix)
displs = malloc(np * sizeof(int));
//Initialize matrix
if (rank == ROOT) {
matrix = createMatrix(N, N);
printf("Initial matrix: \n");
printArray(matrix, N*N);
int lastRow;
int quotient = N / np;
int multiplicacion = quotient * np;
if (multiplicacion < N) {
lastRow = quotient + (N - (quotient * np));
} else {
lastRow = quotient;
}
for (i = 0; i < np; i++) {
begin = i * quotient;
if (i == np -1) {
end = N - 1;
}else if (i == ROOT) {
end = begin + quotient - 1 ;
}else {
end = (quotient * i + quotient) - 1;
}
sendcounts[i] = (end - begin + 1) * N;
displs[i] = begin * N;
printf("assigning sendcounts[%d]: %d\n", i, sendcounts[i]);
printf("assigning displs[%d]: %d\n", i, displs[i]);
recvbuf = malloc(sendcounts[rank] * sizeof(int));
}
}
printf("sendcounts[%d]: %d\n", rank, sendcounts[rank]);
printf("displs[%d]: %d\n", rank, displs[rank]);
// recvbuf = malloc(sendcounts[rank] * sizeof(int));
//sendcounts outside ROOT doesn't exit
MPI_Scatterv(matrix, sendcounts, displs, MPI_INT, recvbuf, sendcounts[rank], MPI_INT, ROOT, MPI_COMM_WORLD);
printArray(recvbuf, sendcounts[rank]);
printf("\n");
free(recvbuf);
recvbuf=NULL;
MPI_Finalize();
return 0;
}