MPI и распределение многомерных массивов в C

Я пытаюсь использовать MPI_Scatter, отправляя строки матрицы (которые распределяются динамически), но он отправляет только одну строку, в других являются ненужными. Когда я использую статическое выделение памяти — все хорошо.

MPI_Init(&argc, &argv);
int **matrix, *matrix_stor, *row,rank, P;
MPI_Comm_size(MPI_COMM_WORLD, &P);
row = new int [P];
for(int i = 0; i < P; i++)
{
row[i] = 0;
}
matrix = new int *[P];
for(int i = 0; i < P; i ++)
matrix[i] = new int [P];

//int matrix[4][4], row[4], rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0){
for(int i = 0; i < P; i++){
for(int j = 0; j < P; j++){
matrix[i][j] = rand()%20;
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
cout << endl;

MPI_Scatter(&matrix[0][0], P, MPI_INT,&row[0], P, MPI_INT,0,MPI_COMM_WORLD);
for(int i = 0; i < P; i++)
cout << row[i] << " ";
cout << endl;
free(matrix);
free(row);
MPI_Finalize();
return 0;

И результат:
Исходная матрица:
1 7 14 0
9 4 18 18
2 4 5 5
1 7 1 11
Полученные строки:
1 7 14 0
3626672 3626800 0 0
16 1 119 -33686019
-33686019 -572662307 524296 786765

1

Решение

Это не проблема MPI, это проблема C и многомерных массивов.

Проблема в том, что в C нет гарантии, что ваша выделенная матрица на самом деле P*P смежный ints. Поэтому, когда вы пытаетесь рассеять P*P целые, начиная с matrix[0][0], кто знает, что вы отправляете.

Этот код:

matrix = new int *[P];
for(int i = 0; i < P; i ++)
matrix[i] = new int [P];

Выделяет сначала массив P pointers-to-int, а затем устанавливает каждый указатель в том месте, где он был выделен P Интс. Но нет никакой гарантии, что matrix[1] начинается где matrix[0] заканчивается. Если вы хотите сделать это — и вы делаете, как для MPI, так и обычно для многомерных массивов в технических вычислительных приложениях в целом — вам нужно вручную выделить непрерывный блок памяти и иметь matrix указать на это:

matrix = new int *[P];
int *data = new int [P*P];
for(int i = 0; i < P; i ++)
matrix[i] = &(data[P*i]);

И тогда разброс должен работать.

Обратите внимание, что вы должны использовать deleteне free(), чтобы освободить память, выделенную с new,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]