我试图将矩阵的一部分从一个过程发送到另一个过程。这是给定的矩阵

它有10行8列。我试图发送一半的列(4到7)注->矩阵从进程0索引到进程1,借助MPI_Pack()。为此,我将使用以下代码
double snd_buf[4][r]; //r is the number of rows
double recv_buf[4][r];
double buf[4][r];
MPI_Request request[c]; //c is the number of columns
MPI_Request request1[c];
MPI_Status status[c];
//packing and sending the data
if(myrank==0)
{
//we will send the half of the matrix to process 2
for(int j=4;j<c;j++)
{
position=0; //reassigning position after each and every send
for(int i=0;i<r;i++)
{
MPI_Pack(&mat[i][j], 1 , MPI_DOUBLE,snd_buf[j-4],80,&position,MPI_COMM_WORLD);
}
}
//sending all the buffers
for(int j=4;j<c;j++)
{
MPI_Send (snd_buf[j-4], 10 , MPI_PACKED, 1 /*dest*/ , j /*tag*/ , MPI_COMM_WORLD);
}
} 为了接收,我使用了以下代码。
if(myrank==1)
{
for(j=4;j<c;j++)
{
MPI_Recv(recv_buf[j-4], 10, MPI_PACKED, 0 /*src*/ , j /*tag*/, MPI_COMM_WORLD,&status[j]);
}
for(int j=4; j<c;j++)
{
position=0;
for(int i=0;i<r;i++)
{
MPI_Unpack(recv_buf[j-4],80,&position,&buf[j-4][i], 1/*outcount*/, MPI_DOUBLE, MPI_COMM_WORLD);
}
}
}但是,当我打印recv_buf的值时,我只得到每一行的第一个元素,在某些情况下,后面跟着0,在某些情况下,还有一些垃圾值。下面给出了recv_buf的内容。
例-1:

例2:

我也检查过我的snd_buf[],但是它把所有的值都包装得很好。
我不会在recv_buf中得到这些0,有时甚至是垃圾值。请帮帮忙。
发布于 2021-04-06 19:58:54
第一
double snd_buf[4][r]; //r is the number of rows
double recv_buf[4][r];
double buf[4][r];我想你的意思是:
double snd_buf[r][4]; //r is the number of rows
double recv_buf[r][4];
double buf[r][4];从来源可以读到:
MPI_Pack -将给定数据类型的数据打包到连续内存中。
你在滥用包装/拆包功能。与其打包要发送的每个元素,您只需要用要发送的列打包行。由于行是连续地在内存中分配的,所以您可以一次打包它们,不需要分别打包每一列。此外,您正在对发送执行多个调用:
for(int j=0;j<c;j++){
MPI_Send (snd_buf[j-4], 10 , MPI_PACKED, 1 /*dest*/ , j /*tag*/ , MPI_COMM_WORLD);
}打包的目的是将所有东西打包到一个缓冲区中,并一次性发送/恢复它。如果要执行多个MPI_Send,那么打包没有什么好处,最好直接发送/接收列,而不必打包任何内容,如下所示:
if(myrank==0){
for(int i=0;i<r;i++) // Send 4 columns of each row
MPI_Send (&mat[i], 4, MPI_DOUBLE, 1, i, MPI_COMM_WORLD);
}
...
if(myrank==1){
for(int i=0;i<r;i++){ // receive 4 columns of each row
MPI_Recv(&mat[i], 4, MPI_DOUBLE, 0, i ...);
}除其他外,这些都是您需要在逻辑中修复的基本错误,以使其正常工作。
尽管如此,通过发送一半的行而不是一半的列来解决这个问题要容易得多,效率也高得多。
您可以首先分配一个连续二维阵列 (或者简单地将矩阵表示为一个数组),只需用一个调用发送/重新分配一半的行。
下面是一个演示该方法的玩具示例(它只适用于两个过程,而且还没有生产准备):
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#define ROWS 10
#define COLS 8
int main( int argc, char *argv[])
{
MPI_Status status;
MPI_Init(&argc, &argv);
int myrank, size; //size will take care of number of processes
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if(myrank == 0){
int (*arr)[COLS] = malloc(sizeof *arr * ROWS);
// Just faking some data
for(int i = 0; i < ROWS; i++)
for(int j = 0; j < COLS; j++)
arr[i][j] = i;
MPI_Send(&arr[ROWS/2], ROWS/2 * COLS, MPI_INT, 1, 0, MPI_COMM_WORLD);
}else{
int (*arr)[COLS] = malloc(sizeof *arr * ROWS/2);
MPI_Recv(arr, ROWS/2 * COLS, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
for(int i = 0; i < ROWS/2; i++){
for(int j = 0; j < COLS; j++)
printf("%d ",arr[i][j]);
printf("\n");
}
}
MPI_Finalize();
return 0;
}输入:
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 输出:
5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 要将这种方法扩展到多个进程,您应该将点对点通信例程(即MPI_Send和MPI_Recv)替换为集体通信例程斯卡特捷夫。
将缓冲区分散到通信器中的所有进程。
从组中的所有进程聚集到指定的位置。
https://stackoverflow.com/questions/66973279
复制相似问题