MPI 集合通信函数 MPI_Scatterv(),MPI_Gatherv(),MPI_Allgatherv(),MPI_Alltoall(),MPI_Alltoallv(),MPI_Alltoallw()


▶ 函数 MPI_Scatterv() 和 MPI_Gatherv() 。注意到函数 MPI_Scatter() 和 MPI_Gather() 只能向每个进程发送或接受相同个数的元素,如果希望各进程获得或发送的元素个数不等,就需要时个用着两个函数,不同点是将发送或接受的元素个数变成一个元素个数表和一个元素偏移表,分别指定每个进程的接受或发送状况。

● 函数原型

 1 _Pre_satisfies_(sendbuf != MPI_IN_PLACE) MPI_METHOD MPI_Scatterv(
 2     _In_opt_ const void* sendbuf,                           // 指向发送数据的指针
 3     _In_opt_ const int sendcounts[],                        // 发送给各进程数据的个数表
 4     _In_opt_ const int displs[],                            // 发送给各进程数据关于 sendbuf 的偏移表,注意当 sendcounts[] 不全为 1 时 displs 是以
 5     _In_ MPI_Datatype sendtype,                             // 发送数据类型
 6     _When_(root != MPI_PROC_NULL, _Out_opt_) void* recvbuf, // 指向接收数据的指针
 7     _In_range_(>= , 0) int recvcount,                       // 接收数据个数
 8     _In_ MPI_Datatype recvtype,                             // 接收数据类型
 9     _mpi_coll_rank_(root) int root,                         // 发送数据源进程号
10     _In_ MPI_Comm comm                                      // 通信子
11 );
12 
13 _Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Gatherv(
14     _In_opt_ const void* sendbuf,                           // 指向发送数据的指针,各进程指针可以不同(自带偏移)
15     _In_range_(>= , 0) int sendcount,                       // 发送数据个数
16     _In_ MPI_Datatype sendtype,                             // 发送数据类型
17     _When_(root != MPI_PROC_NULL, _Out_opt_) void* recvbuf, // 指向接收数据的指针
18     _In_opt_ const int recvcounts[],                        // 接收数据个数表(指定存放个数)
19     _In_opt_ const int displs[],                            // 接收数据在 recvbuf 中的偏移表(指定存放地点)
20     _In_ MPI_Datatype recvtype,                             // 接收数据类型
21     _mpi_coll_rank_(root) int root,                         // 接收数据汇进程号
22     _In_ MPI_Comm comm                                      // 通信子
23 );

● 使用范例

 1 {
 2     const int localSize = 8, nProcess = 8, globalSize = 36;
 3     int globalData[globalSize], localData[localSize], count[nProcess], disp[nProcess];
 4     int comRank, comSize, i, j;
 5 
 6     MPI_Init(&argc, &argv);
 7     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
 8     MPI_Comm_size(MPI_COMM_WORLD, &comSize);
 9 
10     if (comRank == 0)
11         for (i = 0; i < globalSize; globalData[i] = i, i++);
12     for (i = 0; i < comSize; count[i] = i + 1, i++);                                    // 向 0 ~ 7 号进程分别发送 1 ~ 8 个数字   
13     for (disp[0] = 0, i = 1; i < comSize; disp[i] = disp[i - 1] + count[i - 1], i++);   // 每个进程取得的元素的起始地址
14 
15     MPI_Scatterv(globalData, count, disp, MPI_INT, localData, count[comRank], MPI_INT, 0, MPI_COMM_WORLD);  // 分发数据    
16     for (i = 0; i < count[comRank]; i++)                                                // 每个进程将收到的数字加上自身的进程编号
17         localData[i] += comRank;
18     MPI_Gatherv(localData, count[comRank], MPI_INT, globalData, count, disp, MPI_INT, 0, MPI_COMM_WORLD);   // 聚集数据
19 
20     if (comRank == 0)                                                                   // 输出结果
21     {
22         for (i = 0; i < globalSize; i++)
23             printf("%d ", globalData[i]);
24     }
25     
26     MPI_Finalize();
27     return 0;
28 }

● 输出结果:

D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n 8 -l MPIProjectTemp.exe
[0]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
// 即 0+0,1+1,2+1,3+2,4+2,5+2,6+3,7+3,8+3,9+3,……,35+7

 

▶ 函数 MPI_Allgatherv() ,同时具备 MPI_Allgather() 和 MPI_Gatherv() 的特点,即各进程各自拥有同一向量中长度不相等的各分段,要将他们全部同步为整个向量

● 函数原型,仅比函数 MPI_Gatherv() 少了一个 root 参数

 1 _Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Allgatherv(
 2     _In_opt_ const void* sendbuf,       // 指向发送数据的指针
 3     _In_range_(>= , 0) int sendcount,   // 发送数据量
 4     _In_ MPI_Datatype sendtype,         // 发送数据类型
 5     _Out_opt_ void* recvbuf,            // 指向接收数据的指针
 6     _In_ const int recvcounts[],        // 从各进程接收的数据量
 7     _In_ const int displs[],            // 从各进程接收的数据在 recvbuf 中的偏移
 8     _In_ MPI_Datatype recvtype,         // 接收数据类型
 9     _In_ MPI_Comm comm                  // 通信子
10 );

● 使用范例

 1 int main(int argc, char **argv)
 2 {
 3     const int localSize = 8, nProcess = 8, globalSize = 36;
 4     int globalData[globalSize], localData[localSize], count[nProcess], disp[nProcess];
 5     int comRank, comSize, i;
 6 
 7     MPI_Init(&argc, &argv);
 8     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
 9     MPI_Comm_size(MPI_COMM_WORLD, &comSize);    
10 
11     if (comRank == 0)                        // 0 号进程初始化为所需数据,其他进程初始化为 -1
12         for (i = 0; i < globalSize; globalData[i] = i, i++);
13     else
14         for (i = 0; i < globalSize; globalData[i] = 0, i++);
15     for (i = 0; i < localSize; localData[i++] = -1);
16     for (i = 0; i < comSize; count[i] = i + 1, i++);
17     for (disp[0] = 0, i = 1; i < comSize; disp[i] = disp[i - 1] + count[i - 1], i++);
18 
19     MPI_Scatterv(globalData, count, disp, MPI_INT, localData, count[comRank], MPI_INT, 0, MPI_COMM_WORLD);  // 分发数据
20     for (i = 0; i < count[comRank]; i++)
21         localData[i] += comRank;
22     MPI_Allgatherv(localData, count[comRank], MPI_INT, globalData, count, disp, MPI_INT, MPI_COMM_WORLD);   // 聚集数据
23 
24     for (i = 0; i < globalSize; i++)
25         printf("%d ", globalData[i]);
26 
27     MPI_Finalize();
28     return 0;
29 }

● 输出结果

D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n 8 -l MPIProjectTemp.exe
[2]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[7]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[4]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[5]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[3]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[6]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[0]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42
[1]0 2 3 5 6 7 9 10 11 12 14 15 16 17 18 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42

 

▶ 函数 MPI_Alltoall(),MPI_Alltoallv(),MPI_Alltoallw() 。类似函数 MPI_Allgather() 的扩展,从每个进程的数据中挑出一部分来对所有的进程进行同步,第一个函数要求相同的大小和数据类型,第二个函数可以不同大小,第三个函数可以不同的数据类型

● 函数原型

 1 _Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Alltoall(
 2     _In_opt_ _When_(sendtype == recvtype, _In_range_(!= , recvbuf)) const void* sendbuf,// 指向发送数据的指针
 3     _In_range_(>= , 0) int sendcount,   // 发送数据个数
 4     _In_ MPI_Datatype sendtype,         // 发送数据类型
 5     _Out_opt_ void* recvbuf,            // 指向接收数据的指针
 6     _In_range_(>= , 0) int recvcount,   // 接收数据个数
 7     _In_ MPI_Datatype recvtype,         // 接收数据类型
 8     _In_ MPI_Comm comm                  // 通信子
 9 );
10 
11 
12 _Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Alltoallv(
13     _In_opt_ const void* sendbuf,       // 指向发送数据的指针
14     _In_opt_ const int sendcounts[],    // 发送数据个数列表
15     _In_opt_ const int sdispls[],       // 发送数据的偏移列表
16     _In_ MPI_Datatype sendtype,         // 发送数据类型
17     _Out_opt_ void* recvbuf,            // 指向接收数据的指针
18     _In_ const int recvcounts[],        // 接收数据个数列表
19     _In_ const int rdispls[],           // 接收数据的偏移列表
20     _In_ MPI_Datatype recvtype,         // 接收数据类型
21     _In_ MPI_Comm comm                  // 通信子
22 );
23 
24 _Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Alltoallw(
25     _In_opt_ const void* sendbuf,               // 指向发送数据的指针
26     _In_opt_ const int sendcounts[],            // 发送数据列表
27     _In_opt_ const int sdispls[],               // 发送数据的偏移列表
28     _In_opt_ const MPI_Datatype sendtypes[],    // 发送数据的类型列表
29     _Out_opt_ void* recvbuf,                    // 指向接收数据的指针
30     _In_ const int recvcounts[],                // 接收数据个数列表
31     _In_ const int rdispls[],                   // 接收数据的偏移列表
32     _In_ const MPI_Datatype recvtypes[],        // 接收数据类型列表
33     _In_ MPI_Comm comm                          // 通信子
34 );

● 函数 MPI_Alltoall() 使用范例

 1 {
 2     const int localSize = 8, nProcess = 8, globalSize = localSize * nProcess;
 3     int comRank, comSize, i, sendData[globalSize], receiveData[globalSize];
 4 
 5     MPI_Init(&argc, &argv);
 6     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
 7     MPI_Comm_size(MPI_COMM_WORLD, &comSize);
 8 
 9     for (i = 0; i < globalSize; sendData[i] = comRank + 1, receiveData[i] = 0, i++);
10 
11     MPI_Alltoall(sendData, localSize, MPI_INT, receiveData, localSize, MPI_INT, MPI_COMM_WORLD);
12 
13     for (i = 0; i < globalSize; i++)
14         printf("%d, ", sendData[i]);    
15     fflush(stdout), MPI_Barrier(MPI_COMM_WORLD);// 使用缓冲区清空函数 fflush() 和同步函数 MPI_Barrier() 来实现分隔输出
16     for (i = 0; i < globalSize; i++)
17         printf("%d, ", receiveData[i]);
18     
19     MPI_Finalize();
20     return 0;
21 }

● 输出结果,前 8 行为原始数据,同一个进程内所有元素均相等;后 8 行为通信后的数据,所有的进程数据都相同,各分段的值来自不同的进程

D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n 8 -l MPIProjectTemp.exe
[7]8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
[5]6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
[4]5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[2]3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
[3]4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[0]1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[1]2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[6]7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
[3]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
[6]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
[4]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
[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
[7]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
[2]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
[5]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
[1]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

● 函数 MPI_Alltoallv() 使用范例

 1 {
 2     const int nProcess = 8;
 3     int sendData[nProcess * nProcess], receiveData[nProcess * nProcess];
 4     int sendCount[nProcess], receiveCount[nProcess], sendDisp[nProcess], receiveDisp[nProcess];
 5     int comRank, comSize, i;
 6 
 7     MPI_Init(&argc, &argv);
 8     MPI_Comm_size(MPI_COMM_WORLD, &comSize);
 9     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);    
10 
11     for (i = 0; i < comSize * comSize; sendData[i] = 100 * comRank + i, receiveData[i] = -1, i++);
12     for (i = 0; i < comSize; i++)
13     {
14         sendCount[i] = i;
15         receiveCount[i] = comRank;
16         receiveDisp[i] = i * comRank;
17         sendDisp[i] = (i * (i + 1)) / 2;
18     }
19     MPI_Alltoallv(sendData, sendCount, sendDisp, MPI_INT, receiveData, receiveCount, receiveDisp, MPI_INT, MPI_COMM_WORLD);
20     for (i = 0; i < comSize * comSize; i++)
21         printf("%3d ", sendData[i]);
22     fflush(stdout), MPI_Barrier(MPI_COMM_WORLD);
23     for (i = 0; i < comSize * comSize; i++)
24         printf("%3d ", receiveData[i]);
25     /*// 二维形式打印 sendData 和 receiveData
26     for (i = 0; i < comSize; i++)
27     {
28         for (int j = 0; j < comSize; j++)
29             printf("%3d ", sendData[i*comSize + j]);
30         printf("\n");
31     }
32     fflush(stdout), MPI_Barrier(MPI_COMM_WORLD);
33     for (i = 0; i < comSize; i++)
34     {
35         for (int j = 0; j < comSize; j++)
36             printf("%3d ", receiveData[i*comSize + j]);
37         printf("\n");
38     }
39     */
40     MPI_Finalize();
41     return 0;
42 }

● 输出结果

D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n 8 -l MPIProjectTemp.exe
[2]200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
[5]500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
[0]  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  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63
[4]400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
[1]100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
[3]300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
[7]700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
[6]600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
[4] 10  11  12  13 110 111 112 113 210 211 212 213 310 311 312 313 410 411 412 413 510 511 512 513 610 611 612 613 710 711 712 713  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[5] 15  16  17  18  19 115 116 117 118 119 215 216 217 218 219 315 316 317 318 319 415 416 417 418 419 515 516 517 518 519 615 616 617 618 619 715 716 717 718 719  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[0] -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[6] 21  22  23  24  25  26 121 122 123 124 125 126 221 222 223 224 225 226 321 322 323 324 325 326 421 422 423 424 425 426 521 522 523 524 525 526 621 622 623 624 625 626 721 722 723 724 725 726  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[3]  6   7   8 106 107 108 206 207 208 306 307 308 406 407 408 506 507 508 606 607 608 706 707 708  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[7] 28  29  30  31  32  33  34 128 129 130 131 132 133 134 228 229 230 231 232 233 234 328 329 330 331 332 333 334 428 429 430 431 432 433 434 528 529 530 531 532 533 534 628 629 630 631 632 633 634 728 729 730 731 732 733 734  -1  -1  -1  -1  -1  -1  -1  -1
[1]  1 101 201 301 401 501 601 701  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
[2]  3   4 103 104 203 204 303 304 403 404 503 504 603 604 703 704  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1

 ● 函数 MPI_Alltoallw() 使用范例(从函数 MPI_Alltoallv() 范例改过来的)

 1 {
 2     const int nProcess = 8;
 3     int sendData[nProcess * nProcess], receiveData[nProcess * nProcess];
 4     int sendCount[nProcess], receiveCount[nProcess], sendDisp[nProcess], receiveDisp[nProcess];
 5     MPI_Datatype dataType[nProcess];
 6     int comRank, comSize, i;
 7 
 8     MPI_Init(&argc, &argv);
 9     MPI_Comm_size(MPI_COMM_WORLD, &comSize);
10     MPI_Comm_rank(MPI_COMM_WORLD, &comRank);    
11 
12     for (i = 0; i < comSize * comSize; sendData[i] = 100 * comRank + i, receiveData[i] = -1, i++);
13     for (i = 0; i < comSize; i++)
14     {
15         sendCount[i] = i;
16         receiveCount[i] = comRank;
17         receiveDisp[i] = i * comRank * sizeof(int);   // 因为数据类型放宽,偏移地址改用字节为单位
18         sendDisp[i] = (i * (i + 1)) / 2 * sizeof(int);
19         dataType[i] = MPI_INT;                        // 数据类型从单变成为列表
20     }
21     MPI_Alltoallw(sendData, sendCount, sendDisp, dataType, receiveData, receiveCount, receiveDisp, dataType, MPI_COMM_WORLD);// 把两个数据类型的参数换成列表
22     for (i = 0; i < comSize * comSize; i++)
23         printf("%3d ", sendData[i]);
24     fflush(stdout), MPI_Barrier(MPI_COMM_WORLD);
25     for (i = 0; i < comSize * comSize; i++)
26         printf("%3d ", receiveData[i]);
27     /*// 二维形式打印 sendData 和 receiveData
28     for (i = 0; i < comSize; i++)
29     {
30         for (int j = 0; j < comSize; j++)
31             printf("%3d ", sendData[i*comSize + j]);
32         printf("\n");
33     }
34     fflush(stdout), MPI_Barrier(MPI_COMM_WORLD);
35     for (i = 0; i < comSize; i++)
36     {
37         for (int j = 0; j < comSize; j++)
38             printf("%3d ", receiveData[i*comSize + j]);
39         printf("\n");
40     }
41     */
42     MPI_Finalize();
43     return 0;
44 }

● 输出结果同函数 MPI_Alltoallv() 的范例


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM