可以移调阵列使用MPI_Type_create_subarray发送时? [英] Can you transpose array when sending using MPI_Type_create_subarray?

查看:203
本文介绍了可以移调阵列使用MPI_Type_create_subarray发送时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想转用MPI在C.每个进程都有一个方形子矩阵的矩阵,我想发送给正确的流程(即相反的一对电网),调换它作为部分通信。

我用 MPI_Type_create_subarray 它可以对订单的说法,无论是 MPI_ORDER_C MPI_ORDER_FORTRAN 分别行主要和列重大。我想,如果我被作为其中之一,并收到对方,那么我的矩阵将被转作为通信的一部分。然而,这似乎并没有发生 - 它只是停留非转

在code的重要组成部分,是下面,整个code文件可在这个主旨 。没有人有这是为什么不工作的任何想法?如若这种方法做转工作的?我还以为它会,看过的描述 MPI_ORDER_C MPI_ORDER_FORTRAN ,但也许不是。

  / * DO ----------- ----------- TRANSPOSE * /
/ *找到相反的坐标(因为我们知道它是一个正方形)* /
coords2 [0] = COORDS [1];
coords2 [1] = COORDS [0];/ *获取排名这一进程* /
MPI_Cart_rank(cart_comm,coords2,&安培; rank2);/ *发送到这些新坐标* /标记=(COORDS [0] + 1)*(COORDS [1] + 1);/ *创建新派生类型接收为* /
/ * MPI_Type_vector(rows_in_core,cols_in_core,cols_in_core,MPI_DOUBLE,&安培; vector_type); * /
尺寸[0] = rows_in_core;
尺寸[1] = cols_in_core;subsizes [0] = rows_in_core;
subsizes [1] = cols_in_core;开始[0] = 0;
开始[1] = 0;MPI_Type_create_subarray(2,大小,subsizes,开始,MPI_ORDER_FORTRAN,MPI_DOUBLE,&安培; send_type);
MPI_Type_commit(安培; send_type);MPI_Type_create_subarray(2,大小,subsizes,开始,MPI_ORDER_C,MPI_DOUBLE,&安培; recv_type);
MPI_Type_commit(安培; recv_type);
/ *我们发送的行主要形式,所以它只是rows_in_core * cols_in_core很多MPI_DOUBLE的* /
MPI_SEND(安培;阵列[0] [0],1,send_type,rank2,标签,cart_comm);/ *从这些新坐标接收* /
MPI_RECV(安培; new_array [0] [0],1,recv_type,rank2,吊牌,cart_comm,&安培;状态);


解决方案

我还以为这会工作,太,但显然不是。

如果您通过相关位地方实际上定义所产生的类型映射,原因变得清晰 - MPI_Type_create_subarray 映射出子阵取全阵列在该地区,而是通过以线性顺序内存游行,所以数据布局不会改变。换句话说,当尺寸等于subsizes,子阵列是记忆只是连续块;并为子阵严格小于整个数组小,你只是改变正在发送的次区域/接收的,而不是数据排序。选择只是一个分区时,您就可以看到效果:

  INT尺寸[] = {COLS,行};
INT subsizes [] = {2,4};
INT开始[] = {1,1};MPI_Type_create_subarray(2,大小,subsizes,开始,MPI_ORDER_FORTRAN,MPI_INT,&安培; FTYPE);
MPI_Type_commit(安培; FTYPE);MPI_Type_create_subarray(2,大小,subsizes,开始,MPI_ORDER_C,MPI_INT,&安培; CTYPE);
MPI_Type_commit(安培; CTYPE);MPI_Isend(及(发送[0] [0]),1,CTYPE,0,1,MPI_COMM_WORLD,&放大器; REQC);
MPI_RECV(及(recvc [0] [0]),1,CTYPE,0,1,MPI_COMM_WORLD,&放大器; statusc);MPI_Isend(及(发送[0] [0]),1,CTYPE,0,1,MPI_COMM_WORLD,&放大器; reqf);
MPI_RECV(及(recvf [0] [0]),1,FTYPE,0,1,MPI_COMM_WORLD,&放大器; statusf);/*...*/的printf(原文:\\ n);
printarr(发送,行,COLS);
的printf(\\ nReceived - Ç顺序:\\ n);
printarr(recvc,行COLS);
的printf(\\ nReceived: - 为了Fortran的:\\ n);
printarr(recvf,行COLS);

给你这样的:

  0 1 2 3 4 5 6
 10 11 12 13 14 15 16
 20 21 22 23 24 25 26
 30 31 32 33 34 35 36
 40 41 42 43 44 45 46
 50 51 52 53 54 55 56
 60 61 62 63 64 65 66接收 - Ç顺序:
  0 0 0 0 0 0 0
  0 11 12 13 14 0 0
  0 21 22 23 24 0 0
  0 0 0 0 0 0 0
  0 0 0 0 0 0 0
  0 0 0 0 0 0 0
  0 0 0 0 0 0 0收稿日期: - 为了Fortran语言:
  0 0 0 0 0 0 0
  0 11 12 0 0 0 0
  0 13 14 0 0 0 0
  0 21 22 0 0 0 0
  0 23 24 0 0 0 0
  0 0 0 0 0 0 0
  0 0 0 0 0 0 0

因此​​,相同的数据被得到发送和接收;一切真的发生的是,数组的大小,subsizes并启动正在逆转。

您的可以的带有MPI数据类型转 - 标准甚至给出了一个的几个例子的,其中一个我在这里音译为C - 但你必须自己创建的类型。好消息是,它真的没有长于子数组的东西:

  MPI_Type_vector(行,1,COLS,MPI_INT,&安培; COL);
MPI_Type_hvector(COLS,1,sizeof的(INT),列,和放大器;转);
MPI_Type_commit(安培;转);MPI_Isend(及(发送[0] [0]),行* COLS,MPI_INT,0,1,MPI_COMM_WORLD,&放大器; REQ);
MPI_RECV(及(recv的[0] [0]),1,转置,0,1,MPI_COMM_WORLD,&放大器;状态);MPI_Type_free(安培; COL);
MPI_Type_free(安培;转);的printf(原文:\\ n);
printarr(发送,行,COLS);
的printf(收到\\ n);
printarr(recv的,行,COLS);$的mpirun -np 1 ./transpose2
原版的:
  0 1 2 3 4 5 6
 10 11 12 13 14 15 16
 20 21 22 23 24 25 26
 30 31 32 33 34 35 36
 40 41 42 43 44 45 46
 50 51 52 53 54 55 56
 60 61 62 63 64 65 66
收到
  0 10 20 30 40 50 60
  1 11 21 31 41 51 61
  2 12 22 32 42 52 62
  3 13 23 33 43 53 63
  4 14 24 34 44 54 64
  5月15日25 35 45 55 65
  6 16 26 36 46 56 66

I'm trying to transpose a matrix using MPI in C. Each process has a square submatrix, and I want to send that to the right process (the 'opposite' one on the grid), transposing it as part of the communication.

I'm using MPI_Type_create_subarray which has an argument for the order, either MPI_ORDER_C or MPI_ORDER_FORTRAN for row-major and column-major respectively. I thought that if I sent as one of these, and received as the other, then my matrix would be transposed as part of the communication. However, this doesn't seem to happen - it just stays non-transposed.

The important part of the code is below, and the whole code file is available at this gist. Does anyone have any ideas why this isn't working? Should this approach to doing the transpose work? I'd have thought it would, having read the descriptions of MPI_ORDER_C and MPI_ORDER_FORTRAN, but maybe not.

/* ----------- DO TRANSPOSE ----------- */
/* Find the opposite co-ordinates (as we know it's a square) */
coords2[0] = coords[1];
coords2[1] = coords[0];

/* Get the rank for this process */
MPI_Cart_rank(cart_comm, coords2, &rank2);

/* Send to these new coordinates */

tag = (coords[0] + 1) * (coords[1] + 1);

/* Create new derived type to receive as */
/* MPI_Type_vector(rows_in_core, cols_in_core, cols_in_core, MPI_DOUBLE, &vector_type); */
sizes[0] = rows_in_core;
sizes[1] = cols_in_core;

subsizes[0] = rows_in_core;
subsizes[1] = cols_in_core;

starts[0] = 0;
starts[1] = 0;

MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_FORTRAN, MPI_DOUBLE, &send_type);
MPI_Type_commit(&send_type);

MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &recv_type);
MPI_Type_commit(&recv_type);


/* We're sending in row-major form, so it's just rows_in_core * cols_in_core lots of MPI_DOUBLE */
MPI_Send(&array[0][0], 1, send_type, rank2, tag ,cart_comm);

/* Receive from these new coordinates */
MPI_Recv(&new_array[0][0], 1, recv_type, rank2, tag, cart_comm, &status);

解决方案

I would have thought this would work, too, but apparently not.

If you slog through the relevant bit of the MPI standard where it actually defines the resulting typemap, the reason becomes clear -- MPI_Type_create_subarray maps out the region that the subarray takes in the full array, but marches through the memory in linear order, so the data layout doesn't change. In other words, when the sizes equal the subsizes, the subarray is just a contiguous block of memory; and for a subarray strictly smaller than the whole array, you're just changing the subregion that is being sent/received to, not the data ordering. You can see the effect when choosing just a subregion:

int sizes[]={cols,rows};
int subsizes[]={2,4};
int starts[]={1,1};

MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_FORTRAN, MPI_INT, &ftype);
MPI_Type_commit(&ftype);

MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &ctype);
MPI_Type_commit(&ctype);

MPI_Isend(&(send[0][0]), 1, ctype, 0, 1, MPI_COMM_WORLD,&reqc);
MPI_Recv(&(recvc[0][0]), 1, ctype, 0, 1, MPI_COMM_WORLD, &statusc);

MPI_Isend(&(send[0][0]), 1, ctype, 0, 1, MPI_COMM_WORLD,&reqf);
MPI_Recv(&(recvf[0][0]), 1, ftype, 0, 1, MPI_COMM_WORLD, &statusf);

/*...*/

printf("Original:\n");
printarr(send,rows,cols);
printf("\nReceived -- C order:\n");
printarr(recvc,rows,cols);
printf("\nReceived: -- Fortran order:\n");
printarr(recvf,rows,cols);

gives you this:

  0   1   2   3   4   5   6 
 10  11  12  13  14  15  16 
 20  21  22  23  24  25  26 
 30  31  32  33  34  35  36 
 40  41  42  43  44  45  46 
 50  51  52  53  54  55  56 
 60  61  62  63  64  65  66 

Received -- C order:
  0   0   0   0   0   0   0 
  0  11  12  13  14   0   0 
  0  21  22  23  24   0   0 
  0   0   0   0   0   0   0 
  0   0   0   0   0   0   0 
  0   0   0   0   0   0   0 
  0   0   0   0   0   0   0 

Received: -- Fortran order:
  0   0   0   0   0   0   0 
  0  11  12   0   0   0   0 
  0  13  14   0   0   0   0 
  0  21  22   0   0   0   0 
  0  23  24   0   0   0   0 
  0   0   0   0   0   0   0 
  0   0   0   0   0   0   0 

So the same data is getting sent and received; all that's really happening is that the arrays sizes, subsizes and starts are being reversed.

You can transpose with MPI datatypes -- the standard even gives a couple of examples, one of which I've transliterated into C here -- but you have to create the types yourself. The good news is that it's really no longer than the subarray stuff:

MPI_Type_vector(rows, 1, cols, MPI_INT, &col);
MPI_Type_hvector(cols, 1, sizeof(int), col, &transpose);
MPI_Type_commit(&transpose);

MPI_Isend(&(send[0][0]), rows*cols, MPI_INT, 0, 1, MPI_COMM_WORLD,&req);
MPI_Recv(&(recv[0][0]), 1, transpose, 0, 1, MPI_COMM_WORLD, &status);

MPI_Type_free(&col);
MPI_Type_free(&transpose);

printf("Original:\n");
printarr(send,rows,cols);
printf("Received\n");
printarr(recv,rows,cols);



$ mpirun -np 1 ./transpose2 
Original:
  0   1   2   3   4   5   6 
 10  11  12  13  14  15  16 
 20  21  22  23  24  25  26 
 30  31  32  33  34  35  36 
 40  41  42  43  44  45  46 
 50  51  52  53  54  55  56 
 60  61  62  63  64  65  66 
Received
  0  10  20  30  40  50  60 
  1  11  21  31  41  51  61 
  2  12  22  32  42  52  62 
  3  13  23  33  43  53  63 
  4  14  24  34  44  54  64 
  5  15  25  35  45  55  65 
  6  16  26  36  46  56  66 

这篇关于可以移调阵列使用MPI_Type_create_subarray发送时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆