2011-04-11 16 views
6

मैं सी में एमपीआई का उपयोग करके एक मैट्रिक्स को स्थानांतरित करने की कोशिश कर रहा हूं। प्रत्येक प्रक्रिया में एक स्क्वायर सबमिट्रिक्स होता है, और मैं इसे सही प्रक्रिया (ग्रिड पर 'विपरीत') पर भेजना चाहता हूं, इसे संचार के हिस्से के रूप में स्थानांतरित करना चाहता हूं ।क्या MPI_Type_create_subarray का उपयोग करते समय आप सरणी को ट्रांसफर कर सकते हैं?

मैं MPI_Type_create_subarray का उपयोग कर रहा हूं जिसमें क्रमशः पंक्ति-प्रमुख और स्तंभ-प्रमुख के लिए MPI_ORDER_C या MPI_ORDER_FORTRAN आदेश के लिए तर्क है। मैंने सोचा कि अगर मैंने इनमें से एक के रूप में भेजा है, और दूसरे के रूप में प्राप्त किया है, तो संचार के हिस्से के रूप में मेरे मैट्रिक्स को स्थानांतरित किया जाएगा। हालांकि, ऐसा प्रतीत नहीं होता है - यह केवल गैर-स्थानांतरित रहता है।

कोड का महत्वपूर्ण हिस्सा नीचे है, और संपूर्ण कोड फ़ाइल this gist पर उपलब्ध है। क्या किसी के पास कोई विचार है कि यह क्यों काम नहीं कर रहा है? क्या ट्रांसपोज़र काम करने के लिए यह दृष्टिकोण होना चाहिए? मैंने सोचा होगा कि यह MPI_ORDER_C और MPI_ORDER_FORTRAN के विवरण पढ़ेगा, लेकिन शायद नहीं।

/* ----------- 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); 

उत्तर

6

मैंने सोचा होगा कि यह भी काम करेगा, लेकिन स्पष्ट रूप से नहीं।

आप एमपीआई मानक जहां यह वास्तव में जिसके परिणामस्वरूप typemap को परिभाषित करता है की relevant bit माध्यम से आगे बढ़ना है, तो कारण स्पष्ट हो जाता है - MPI_Type_create_subarray बाहर नक्शे क्षेत्र है कि subarray पूर्ण सरणी में लेता है, लेकिन रैखिक क्रम में स्मृति के माध्यम से जुलूस , इसलिए डेटा लेआउट नहीं बदलता है। दूसरे शब्दों में, जब आकार subsizes के बराबर है, तो उपन्यास स्मृति की एक संगत ब्लॉक है; और पूरे सरणी से सख्ती से एक सबएरे के लिए, आप बस उस क्रम को बदल रहे हैं जिसे भेजा जा रहा है/प्राप्त किया जा रहा है, न कि डेटा ऑर्डरिंग। आप प्रभाव देख सकते हैं जब सिर्फ एक उपक्षेत्र चुनने:

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); 

आप देता है यह:

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 

तो एक ही डेटा को भेजने और प्राप्त हो रही है; जो कुछ भी वास्तव में हो रहा है वह यह है कि सरणी के आकार, subsizes और शुरू होने जा रहे हैं।

आप एमपीआई डेटाटाइप्स साथ स्थानांतरित कर सकते हैं - मानक भी एक couple of examples, जिनमें से एक मैं सी में यहां लिप्यंतरण किया है देता है - लेकिन आप प्रकार अपने आप को बनाने के लिए किया है। अच्छी खबर यह है कि यह वास्तव में उपर्युक्त सामग्री से अधिक नहीं है:

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 
+0

मैं इसे पर्याप्त रूप से ऊपर नहीं उठा सकता। मैंने अभी एक सहकर्मी के साथ एक लंबा और आगे बिताया - जिसने MPI-2 (!) - MPI_ORDER_C बनाम MPI_ORDER_FORTRAN और उसके प्रभावों के बारे में डिज़ाइन करने में मदद की। –

संबंधित मुद्दे

 संबंधित मुद्दे