2015-12-09 24 views
5

enter image description hereMPI_Cart_Shift.Corner vicinato

ho bisogno di creare un comunicatore con topologia cubo e quindi selezionare faccia del cubo, utilizzando il MPI_Cart_Shift implementato messaggi tra processi che sono sull'orlo. Per esempio sto elaborando con il grado 0 (R0) i miei quartieri sono R2, R4, R6 (faccia inferiore del cubo). Posso trovare R2 e R4, ma non riesco a capire come trovare R6. Il mio codice:

#include<mpi.h> 
#include<stdio.h> 

int main(int argc, char *argv[]) 
{ 
int rank, k; 
int size; 
int ndims = 3; 
int source, dest; 
int up,down,right,left,up3, down3; 

int edges[6][4] = {{0,1,5,4}, 
       {4,5,7,6}, 
       {2,3,1,0}, 
       {6,7,3,2}, 
       {1,3,7,5}, 
       {0,2,6,7}}; 

int t, incep=0; 
char processor_name[MPI_MAX_PROCESSOR_NAME]; 

MPI_Comm comm, comm3d; 
int dims[3]={0,0,0}, coords[3]={0,0,0}, 
    periods[3]={1,1,1}, reorder = 0; 


MPI_Status status; 


int user_edge; 

MPI_Init(&argc, &argv); 

MPI_Comm_size(MPI_COMM_WORLD, &size); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

MPI_Dims_create(size, ndims, dims); 


    MPI_Cart_create(MPI_COMM_WORLD, ndims, dims, periods, reorder, &comm); 


    MPI_Cart_coords(comm, rank, 3, coords); 

fflush(stdout); 
    printf("Rank %d coordinates are %d %d %d\n", rank, coords[0], coords[1], coords[2]); 
MPI_Barrier(comm); 

    int leftrank, rightrank; 
    int downrank, uprank; 

MPI_Comm_rank(comm, &rank); 
    MPI_Cart_coords(comm, rank, 2, coords); 
MPI_Cart_shift(comm, 0, -1, &downrank, &uprank); 
MPI_Sendrecv(buffer, 10, MPI_INT, downrank, 123, buffer2, 10, MPI_INT, uprank, 123, comm, &status); 
MPI_Cart_shift(comm, 1, -1, &rightrank, &leftrank); 
    MPI_Sendrecv(buffer, 10, MPI_INT, leftrank, 123, buffer2, 10, MPI_INT, rightrank, 123, comm, &status); 


printf("P:%d My neighbors are rightRank: %d downRank:%d leftRank:%d upRank:%d diagonal:%d diagonalX:%d\n", rank,rightrank,downrank,leftrank,uprank,diagonal,diagonalX); 



MPI_Finalize(); 

return 0; 

} 

cercherò aggiungere qualcosa di simile MPI_Cart_shift (comm, 2, 1, & diagonale, & diagonalX); Ma per R0 mi mostra R1 e capisco ... Come posso ottenere quartieri d'angolo?

risposta

2

È possibile utilizzare MPI_Cart_rank per trovare le informazioni necessarie.

int MPI_Cart_rank(MPI_Comm comm, const int coords[], int *rank) 

Qui Comm è un comunicatore con topologia cartesiana. coords è un array intero (la dimensione di questo array è il numero di dimensioni della topologia cartesiana) contenente la coordinata di un processo (nel tuo caso, 1,1,0 per R6). Quindi l'output rank restituirebbe il rango globale di quel processo che è possibile utilizzare nelle comunicazioni successive.

BTW, MPI_Cart_coords esegue la direzione opposta, vale a dire da posizione a coordinata.

0

Hai dimenticato di etichettare R5. Non c'è un approccio diretto a cui io possa pensare. Ma ecco un modo indiretto:

(1) Per qualsiasi grado le cui coordinate sono (A,y,z) prendere in considerazione le coordinate: (A,y+1,z+1), (A,y-1,z-1), (A,y+1,z-1) e (A,y-1,z+1) - questi possono essere i 4 vicini diagonali. Chiaramente, quando si considera un segno negativo per es. z-1, è chiaro che z-1 >= 0 e quando si considera un vantaggio per es. y+1 <= (dimension_in_y - 1). Ad esempio, considera R5 (che hai dimenticato di etichettare). R5 secondo MPI ha coordinate R5(0,1,0). Può avere 4 vicini diagonali: (0,1+1,0+1), (0,1-1,0-1),(0,1+1,0-1),(0,1-1,0+1) - di cui esiste solo il quarto (che è chiaro come nessun vicino può avere coordinate negative e ogni coordinata deve essere 1 meno della dimensione in quella direzione). Successivamente, è sufficiente eseguire una query su MPI_coordinate_to_rank().

(2) Un altro metodo è quello di interrogare i right e left vicini sui loro front e back vicini (questo sarà cattiva performance-saggio).

(3) Per generalizzare a 8 vicini - è necessario variare anche la coordinata X - ma la domanda è limitata alla faccia di un cubo.

+0

Ho modificato il mio post. – Vdovin

+0

Controllare le coordinate del processo. NON sono conformi alle coordinate cartesiane MPI. –

1

MPI_Cart_shift può trovare solo i vicini in una delle direzioni principali, ma non in diagonale - è necessario implementarlo da solo, il che non è così difficile da fare. Lo spostamento cartesiano sé non è altro che una funzione convenienza che avvolge chiamate MPI_Cart_coords e MPI_Cart_rank:

// 
// The following is equivalent to 
// MPI_Cart_shift(cart_comm, i, disp, &rank_source, &rank_dest); 
// 

// Obtain the rank of the calling process and translate it into coordinates 
int rank, coords[ndims]; 
MPI_Comm_rank(cart_comm, &rank); 
MPI_Cart_coords(cart_comm, rank, ndims, coords); 

int mycoord_i = coords[i]; 

// Compute the coordinates of the destination in direction i and convert them into rank 
coords[i] = mycoord_i + disp; 
// Take care of non-periodic dimensions 
if (!periods[i] && (coords[i] >= dims[i] || coords[i] < 0)) 
    rank_dest = MPI_PROC_NULL; 
else 
    MPI_Cart_rank(cart_comm, coords, &rank_dest); 

// Compute the coordinates of the source in direction i and convert them into rank 
coords[i] = mycoord_i - disp; 
// Take care of non-periodic dimensions 
if (!periods[i] && (coords[i] >= dims[i] || coords[i] < 0)) 
    rank_source = MPI_PROC_NULL; 
else 
    MPI_Cart_rank(cart_comm, coords, &rank_source); 

noti come uscire-di-bound dovrebbero essere esplicitamente manipolati per dimensioni non periodiche.Per quelli periodici, lo stesso MPI_Cart_rank esegue la piegatura delle coordinate. La topologia cartesiana è periodica, pertanto i controlli potrebbero essere saltati (non consigliato).

È possibile adattare facilmente il codice sopra per produrre uno spostamento in due o più dimensioni, quindi utilizzarlo per elencare tutte le possibili combinazioni di spostamenti e direzioni per trovare i ranghi che si trovano su un determinato viso. Per esempio:

int rank, coords[ndims]; 
MPI_Comm_rank(cart_comm, &rank); 
MPI_Cart_coords(cart_comm, rank, ndims, coords); 
int my_coord1 = coords[1]; 
int my_coord2 = coords[2]; 
coords[1] = my_coord1 + 1; 
coords[2] = my_coord2 + 1; 
MPI_Cart_rank(cart_comm, coords, &rank_dest); 
coords[1] = my_coord1 - 1; 
coords[2] = my_coord2 - 1; 
MPI_Cart_rank(cart_comm, coords, &rank_source); 

vi darà il grado di R6 in rank_dest quando eseguito da R0. Se si estrae il codice in una routine separata e chiami MyMPI_Cart_shift2:

MyMPI_Cart_shift2(cart_comm, 1, 1, 2, 1, &rank_source, &rank_dest); 

Un'altra opzione sarebbe quella di utilizzare MPI_Cart_sub per dividere la topologia cartesiana in lastre, paralleli al lato. È quindi possibile eseguire direttamente la comunicazione che coinvolge solo ranghi in una data lastra.