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