2012-05-02 26 views
10

युक्त संरचना के लिए MPI_Datatype बनाना मेरे पास निम्न संरचना है।पॉइंटर्स

typedef struct 
{ 
int *Ai; 
double *Ax; 
int nz; 
}column; 

मैं इस संरचना MPI_Send और MPI_Receive का उपयोग कर स्थानांतरित करना चाहते हैं। मैं इस संरचना के लिए MPI_Datatype कैसे बना सकता हूं?

+0

आप कभी भी एमपीआई प्रक्रियाओं के बीच पॉइंटर्स क्यों भेजना चाहते हैं? वे वितरित स्मृति प्रणालियों में गैर पोर्टेबल हैं। – talonmies

उत्तर

8

किसी अन्य मशीन पर पॉइंटर्स भेजना व्यर्थ है (कोई इरादा नहीं है)। वर्चुअल एड्रेसिंग के कारण, पॉइंटर संभवतः प्राप्त करने वाली मशीन पर एक अमान्य मेमोरी लोकेशन को इंगित करेगा, और यदि नहीं, तो भी आपने वास्तव में वह डेटा नहीं भेजा है जो यह इंगित कर रहा था।

हालांकि, MPI_Address() और MPI_Hindexed डेटाटाइप के उचित उपयोग के साथ, आपके डेटा के मेमोरी लेआउट का वर्णन करना संभव है (मुझे लगता है कि आपके पॉइंटर्स गतिशील सरणी को इंगित करते हैं)। जैसे 3 MPI_INT रों, 5 MPI_DOUBLE है, और 1 MPI_INT, ऑफसेट MPI_Address() का उपयोग कर प्राप्त कर लिया साथ: अगर 3 int है, और 5 double रों को Ax अंक के Ai अंक, आप 3 ब्लॉक के साथ एक Hindexed प्रकार की आवश्यकता होगी।

डेटाटाइप को फिर से परिभाषित करने और अनुशंसा करने के लिए मत भूलना अगर आप वस्तुओं की संख्या को पूरी तरह से भेजने या पुन: आवंटित करने के लिए बदलते हैं। और यदि आप एकाधिक structs भेज रहे हैं, तो आपको प्रत्येक के लिए इस डेटाटाइप को परिभाषित और प्रतिबद्ध करना होगा, क्योंकि आपका एमपीआई डेटाटाइप इन structs के एक विशेष उदाहरण के लिए विशिष्ट है।

यह भी ध्यान रखें कि यदि आप मूल संरचना को फिर से बनाना चाहते हैं तो आपको प्राप्त करने वाले अंत में कुछ समान मुश्किल अनपॅकिंग करना होगा।

+0

सहायता के लिए धन्यवाद। मैंने कोशिश की लेकिन यह एक दौर के बारे में था और बहुत अधिक डेटाटाइप बना रहा था। तो मैंने इसके बजाय अपना डेटा प्रतिनिधित्व बदल दिया। हां पॉइंटर्स गतिशील सरणी थे। – ap040

9

एमपीआई संरचनाओं के सरणी के साथ काम करने के लिए डिज़ाइन किया गया है, बजाय सरणी की संरचनाओं के साथ।

MPI_Hindexed कि @suszterpatt प्रस्तावित एक भयानक हैक है। यह आपको केवल संरचना प्रकार का एक तत्व और केवल उस तत्व को भेजने की अनुमति देगा जिसका उपयोग MPI डेटा प्रकार को परिभाषित करने के लिए किया गया था। उसी संरचना प्रकार के अन्य चर के लिए यह अधिकतर गारंटी है कि गणना किए गए ऑफसेट गलत होंगे। के अलावा हिंदेक्स प्रकार सभी तत्वों के लिए एक और एक ही एमपीआई डेटा प्रकार का उपयोग करते हैं और इस प्रकार आप दोनों स्याही और युगल भेजने की अनुमति नहीं देते हैं।

करने के लिए बुद्धिमान बात संरचनाओं की सरणियों का उपयोग करने के अपने कार्यक्रम को बदलने के लिए है:

typedef struct 
{ 
    int i; 
    double z; 
} point; 

typedef struct 
{ 
    point *A; 
    int nz; 
} column; 
अब

आप कर सकते हैं एक MPI संरचित प्रकार point_type बना सकते हैं और उस प्रकार column.A के रूप में देने का nz तत्वों भेजने के लिए इसका इस्तेमाल करते हैं बफर पता:

int lens[3]; 
MPI_Aint base, disps[2]; 
MPI_Datatype oldtypes[2], point_struct, point_type; 

MPI_Get_address(&point, disps); 
MPI_Get_address(&point.z, disps+1); 
base = disps[0]; 

lens[0] = 1; disps[0] = MPI_Aint_diff(disps[0], base); oldtypes[0] = MPI_INT; 
lens[1] = 1; disps[1] = MPI_Aint_diff(disps[1], base); oldtypes[1] = MPI_DOUBLE; 
MPI_Type_create_struct(2, lens, disps, oldtypes, &point_struct); 
MPI_Type_create_resized(point_struct, 0, sizeof(point), &point_type); 
MPI_Type_commit(&point_type); 

MPI_Send(column.A, column.nz, point_type, ...); 

यह पहली एक MPI डेटाप्रकार point_struct कि संरचना के सदस्यों के लेआउट का वर्णन करता है बनाता है, लेकिन एन पर किसी भी गद्दी के लिए खाते में नहीं है डी और इसलिए विश्वसनीय रूप से ऐसी संरचनाओं की एक सरणी भेजने के लिए उपयोग नहीं किया जा सकता है। इसलिए, MPI_Type_create_resized का उपयोग करके सही सीमा के साथ एक दूसरा डेटाटाइप point_type बनाया गया है।

रिसीवर की ओर पर आप MPI_Probe साथ संदेश झांक सकते हैं, point_type का एक प्रकार के साथ MPI_Get_count साथ तत्वों की संख्या निकालने (कि nz क्षेत्र के लिए सीधे चला जाता है), A क्षेत्र का आवंटन और MPI_Recv में उपयोग प्राप्त करने के लिए nz तत्वों:

MPI_Status status; 
MPI_Probe(source, tag, comm, &status); 
MPI_Get_count(&status, point_type, &column.nz); 
if (nz == MPI_UNDEFINED) 
    ... non-integral message was received, do something 
column.A = (point *)malloc(column.nz*sizeof(point)); 
MPI_Recv(column.A, column.nz, point_type, source, tag, comm, MPI_STATUS_IGNORE); 

हैं कि कोड में परिवर्तन करना असंभव आप अभी भी इसे भेजने से पहले अपने संरचना बदलने के मध्यवर्ती चरण के माध्यम से जा सकते हैं, एक प्रक्रिया आम तौर पर कहा जाता है (संयुक्त राष्ट्र) प्रमुखता। रिसीवर तरफ

point *temp = (point *)malloc(nz*sizeof(point)); 
for (int i = 0; i < column.nz; i++) 
{ 
    temp[i].i = column.Ai[i]; 
    temp[i].z = column.Az[i]; 
} 
MPI_Send(temp, nz, point_type, ...); 
free(temp); 

आप विपरीत कार्य करना होगा:: आपके मामले में (मुझे लगता है कि आप nz क्षेत्र में दोनों Ai और Ax में सरणी तत्वों की संख्या की दुकान) कुछ इस तरह करते हैं पर्याप्त एक बड़े आवंटन बफर जो संरचना को पकड़ सकता है, इसमें संदेश प्राप्त कर सकता है और फिर विपरीत परिवर्तन कर सकता है।

एक बार फिर, आपको nz के वास्तविक मान को प्रेषित करने की आवश्यकता नहीं है क्योंकि इसे MPI_Get_count का उपयोग करके संदेश की लंबाई से आसानी से निकाला जा सकता है।

+0

+1 यह बहुत जानकारीपूर्ण है – pyCthon

+0

धन्यवाद, यह सहायक था। मैंने आपके द्वारा सुझाए गए मध्यवर्ती प्रतिनिधित्व का उपयोग किया और यह बहुत बेहतर था। – ap040

+0

क्या आप "disp [0]" के बारे में निश्चित हैं? यदि शून्य तत्व एक चरित्र है तो मुझे नहीं पता होगा कि यह सबसे छोटी संरेखण इकाई के बाएं या दाएं बाइट में था या नहीं। दूसरे शब्दों में: मैं इसके ऑफसेट को स्पष्ट रूप से गणना करूंगा। –

1

अक्सर कि धारणात्मक भी बेहतर है

"ऐसा करने के लिए बुद्धिमान बात संरचनाओं की सरणियों का उपयोग करने के अपने कार्यक्रम को बदलने के लिए है।"

मैं एक और तंत्र को इंगित करना चाहता हूं: MPI_Pack और MPI_Unpack का उपयोग करना। उदाहरण के लिए, मूल संरचना के साथ आप पहले पूर्णांक को पैक कर सकते हैं, फिर दो सरणी पैक करें। रिसीवर पूर्णांक को अनपैक करेगा और फिर पता होगा कि कितनी अन्य चीज़ों को अनपॅक करना है।

यह भी एक अच्छा समाधान है यदि आपकी वस्तु सीधे पहुंच योग्य नहीं है लेकिन केवल इसे पुनरावर्तक के माध्यम से एक्सेस किया जा सकता है।

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