Saya memiliki masalah dengan MPI_Isend
dan MPI_Irecv
. Saya sedang mengerjakan matriks ketetanggaan dari sebuah grafik, yang didistribusikan berdasarkan baris. Kita dapat berasumsi bahwa setiap prosesor berisi satu baris. Untuk setiap pasangan indeks (i,j)
saya perlu mengirim dan menerima 2 bilangan bulat. Pada dasarnya, saya perlu menerima beberapa informasi lain dari baris lain untuk melakukan perhitungan. Saya baru di MPI, dan ini masuk ke loop tak terbatas, saya bahkan tidak yakin apakah ini cara yang tepat untuk menggunakan MPI_Isend
atau MPI_Irecv
dalam loop for, juga sebagai tempat untuk menunggu.
Sebagai contoh, Asumsikan kita mempunyai graf dengan 6 simpul, sehingga matriks ketetanggaan (adjMatrix
) adalah matriks 6*6, kita juga mempunyai matriks 6*2 untuk beberapa informasi lainnya, dan terakhir, kita mendistribusikan graf tersebut data di antara 6 prosesor. Karena itu:
|0 20 16 0 6 0 | |0 1|
|20 0 0 19 0 6 | |1 1|
addMatrix=|16 0 0 0 12 0 | M=|2 1|
|0 19 0 0 0 12| |3 1|
|6 0 12 0 0 9 | |0 0|
|0 6 0 12 9 0 | |1 0|
Kami mendistribusikan matriks sebagai berikut:
P0: |0 20 16 0 6 0 | |0 1|
P1: |20 0 0 19 0 6 | |1 1|
P2: |16 0 0 0 12 0 | |2 1|
P3: |0 19 0 0 0 12| |3 1|
P4: |6 0 12 0 0 9 | |0 0|
P5: |0 6 0 12 9 0 | |1 0|
Sekarang, setiap prosesor perlu memperbarui porsinya sebesar adjMatrix
. Untuk melakukannya, mereka memerlukan informasi dari beberapa bagian matriks M
, yang ada di prosesor lain. Misalnya, untuk P0
memperbarui indeks (0,1)
yaitu 20
, ia perlu memiliki akses ke baris 1
dari matriks M
yaitu {1,1}
. Karena itu:
P1
harus mengirimMLocal[0][0]=1
danMLocal[0][1]=1
keP0
di manaP0
menerimanya masing-masing sebagaiM_j0
danM_j1
.Dan
P0
harus mengirimMLocal[0][0]=0
danMLocal[0][1]=1
keP1
di manaP1
menerimanya masing-masing sebagaiM_j0
danM_j1
.
for(int i=0;i<rows;i++){
for (int j=0; j<n; j++)
{
int M_j0,M_j1;
MPI_Isend(&MLocal[i][0], 1, MPI_INT, j, my_rank+i*n+j+0, MPI_COMM_WORLD, &send_request0);
MPI_Isend(&MLocal[i][1], 1, MPI_INT, j, my_rank+i*n+j+1, MPI_COMM_WORLD, &send_request1);
MPI_Irecv(&M_j0, 1, MPI_INT, j, my_rank+i*n+j+0, MPI_COMM_WORLD, &recv_request0);
MPI_Irecv(&M_j1, 1, MPI_INT, j, my_rank+i*n+j+1, MPI_COMM_WORLD, &recv_request1);
//MPI_Wait(&send_request0, &status);
//MPI_Wait(&send_request1, &status);
MPI_Wait(&recv_request0, &status);
MPI_Wait(&recv_request1, &status);
// Do something ...
}
}
Kemudian dengan saran GillesGouaillardet, saya mengubah 4 MPI_Isend
dan MPI_Irecv
menjadi:
MPI_Sendrecv(&MoatsLocal[i][0], 1, MPI_INT, j, my_rank+i*n+j+0, &M_j0,1, MPI_INT, my_rank, my_rank+i*n+j+0, MPI_COMM_WORLD, &status);
MPI_Sendrecv(&MoatsLocal[i][1], 1, MPI_INT, j, my_rank+i*n+j+1, &M_j1,1, MPI_INT, my_rank, my_rank+i*n+j+1, MPI_COMM_WORLD, &status);
Tapi tetap saja, ini masuk ke dalam lingkaran tak terbatas.
MEMPERBARUI:
Saya memperbarui kodenya, sebagian masalahnya adalah karena peringkat prosesor dan pencocokan tag. Saya memperbaiki bagian itu tetapi tetap saja rawan kebuntuan, yang menurut saya saya tahu di mana masalahnya. Dan mungkin tidak bisa menyelesaikannya. Jika saya memiliki jumlah prosesor yang cukup, untuk mendistribusikan setiap baris ke prosesor, yaitu n=p, itu tidak akan menjadi masalah. Namun permasalahannya dimana jumlah processor kurang dari n
, maka alirannya tidak lancar melalui diagonal utama Saya jelaskan melalui contoh, misalkan kita mempunyai 4 processor dan n=6
. Asumsikan inilah distribusinya:
P0: |0 20 16 0 6 0 | |0 1|
P1: |20 0 0 19 0 6 | |1 1|
|16 0 0 0 12 0 | |2 1|
P2: |0 19 0 0 0 12| |3 1|
P3: |6 0 12 0 0 9 | |0 0|
|0 6 0 12 9 0 | |1 0|
Inilah yang terjadi melalui loop.
Iterasi pertama:
P0 mengirim dan menerima ke/dari informasi P1 untuk (0,1):"20" dan tunggu(selesai)
P1 mengirim dan menerima ke/dari informasi P0 untuk (1,0):"20" dan tunggu(selesai)
P2 mengirim dan menerima ke/dari informasi P1 untuk (3,1):"19" dan tunggu
P3 mengirim dan menerima ke/dari informasi P0 untuk (4,1):"6" dan tunggu
Iterasi kedua:
P0 mengirim dan menerima ke/dari informasi P1 untuk (0,2):"16" dan tunggu
P1 mengirim dan menerima ke/dari informasi P2 untuk (1,3):"19" dan tunggu(selesai)
P2 menunggu P1 (3,1):"19" lalu terima saja dan selesai!
P3 menunggu P0 untuk (4,1):"6" dan tunggu
Iterasi ketiga:
P0 menunggu P1 untuk (0,2):"16"
P1 mengirim dan menerima ke/dari informasi P3 untuk (1,5):"19" dan tunggu
P2 mengirim dan menerima ke/dari informasi P3 untuk (3,5):"12" dan tunggu
P3 menunggu P0 untuk (4,1):"6"
Iterasi keempat:
P0 menunggu P1 untuk (0,2):"16"
P1 menunggu P3 untuk (1,5):"19"
P2 menunggu P3 untuk (3,5):"12"
P3 menunggu P0 untuk (4,1):"6"
Sekarang, semua menunggu satu sama lain, saya rasa tidak ada cara untuk menyelesaikannya. Solusi yang disarankan ptb mungkin berhasil, saya akan mencobanya.
Namun, ide lain apa pun dihargai!
MPI_Waitall(4, ...);
- person Gilles Gouaillardet   schedule 04.04.2018MPI_Sendrecv()
- person Gilles Gouaillardet   schedule 04.04.2018MPI_Waitall(4, ...)
? hal ini seharusnya mengurangi kemungkinan terjadinya kebuntuan. - person Gilles Gouaillardet   schedule 05.04.2018