my answer से this question में इस समस्या का एक लंबा विवरण है: तथ्य यह है कि बहुत से लोगों के पास ये प्रश्न प्रमाण हैं कि यह स्पष्ट नहीं है और विचारों का उपयोग कुछ करने के लिए किया जाता है।
जानना महत्वपूर्ण बात यह है कि एमपीआई डेटाटाइप का मेमोरी लेआउट क्या है। MPI_Type_vector
बुला अनुक्रम है:
int MPI_Type_vector(int count,
int blocklength,
int stride,
MPI_Datatype old_type,
MPI_Datatype *newtype_p)
यह एक नए प्रकार जो स्मृति का एक लेआउट जहां हर stride
आइटम, वहाँ है blocklength
मदों की एक ब्लॉक बाहर निकाला का वर्णन करता है, और इन ब्लॉकों के count
की कुल बनाता है। यहां आइटम old_type
की इकाइयों में हैं। तो उदाहरण के लिए, यदि आप कहा जाता है (यहां मानकों नामकरण, जो आप वास्तव में सी में ऐसा नहीं कर सकते, लेकिन :)
MPI_Type_vector(count=3, blocklength=2, stride=5, old_type=MPI_INT, &newtype);
फिर newtype
एक लेआउट स्मृति में इस तरह का वर्णन होगा:
|<----->| block length
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| X | X | | | | X | X | | | | X | X | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|<---- stride ----->|
count = 3
जहां प्रत्येक वर्ग स्मृति का एक पूर्णांक आकार का हिस्सा है, संभवतः 4 बाइट्स। ध्यान दें कि चौराहे एक ब्लॉक की शुरुआत से पूर्ण की शुरुआत में पूर्णांक की दूरी है, न कि ब्लॉक के बीच की दूरी।
ठीक है, तो आपके मामले में आप
MPI_Type_vector(N, 1, N, MPI_DOUBLE, &col);
जो count = N
ब्लॉक ले जाएगा, आकार के प्रत्येक blocklength=1
MPI_DOUBLE
रों कहा जाता है, stride=N
MPI_DOUBLE
के प्रत्येक ब्लॉक की शुरुआत के बीच एक स्थान के साथ। दूसरे शब्दों में, यह प्रत्येक एन'एथ डबल, कुल एन बार ले जाएगा; युगल के एनएक्सएन सरणी (एक साथ-संग्रहित) से एक कॉलम निकालने के लिए एकदम सही है। एक आसान जांच यह देखने के लिए है कि कितना डेटा चल रहा है (count*stride = N*N
जो मैट्रिक्स का पूरा आकार है, चेक करें) और वास्तव में कितना डेटा शामिल है (count*blocksize = N
, जो कॉलम का आकार है, जांचें।)
यदि आपको केवल व्यक्तिगत कॉलम का आदान-प्रदान करने के लिए MPI_Send और MPI_Recv को कॉल करना था, तो आप किया जाएगा; आप कॉलम के लेआउट का वर्णन करने के लिए इस प्रकार का उपयोग कर सकते हैं और आप ठीक होंगे। लेकिन एक और बात है।
आप MPI_Scatter
पर कॉल करना चाहते हैं, जो प्रोसेसर 0 के लिए पहला कॉलटाइप (कहता है), प्रोसेसर 1 के लिए अगला कलटाइप भेजता है। यदि आप इसे सरल 1 डी सरणी के साथ कर रहे हैं, तो यह पता लगाना आसान है कि कहां "अगला" डेटा प्रकार है; यदि आप प्रत्येक प्रोसेसर को 1 int स्कैटर कर रहे हैं, तो "अगली" int पहली छोर समाप्त होने के तुरंत बाद शुरू होती है।
लेकिन अपने नए coltype स्तंभ कुल extent कि बाद में N*N
MPI_DOUBLE
रों करने के लिए स्तंभ की शुरुआत से चला जाता है है - अगर MPI_Scatter यही तर्क (यह होता है) इस प्रकार है, यह बाहर "अगले" कॉलम की तलाश शुरू होगा matrices स्मृति पूरी तरह से, और इतने पर अगले और अगले के साथ। न केवल आपको वह जवाब मिलेगा जो आप चाहते थे, कार्यक्रम शायद दुर्घटनाग्रस्त हो जाएगा।
एमपीईआई को यह बताने का तरीका है कि इस डेटा का "आकार" गणना करने के प्रयोजनों के लिए कहता है कि "अगला" एक कहां है, जहां एक कॉलम शुरू होता है और अगला कॉलम शुरू होता है; वह है, बिल्कुल एक MPI_DOUBLE
। यह भेजे गए डेटा की मात्रा को प्रभावित नहीं करता है, जो अभी भी 1 कॉलम डेटा का मूल्य है; यह केवल "अगली पंक्ति में" गणना को प्रभावित करता है। किसी सरणी में कॉलम (या पंक्तियां) के साथ, आप इस आकार को स्मृति में उचित चरण आकार के रूप में भेज सकते हैं, और एमपीआई भेजने के लिए सही अगला कॉलम चुन देगा। इस आकार बदलने वाले ऑपरेटर के बिना, आपका प्रोग्राम शायद दुर्घटनाग्रस्त हो जाएगा।
जब आपके पास अधिक जटिल डेटा लेआउट होते हैं, जैसे ऊपर से जुड़े 2 डी-सरणी उदाहरण के 2 डी-ब्लॉक में, तो "अगली" वस्तुओं के बीच कोई भी एकल चरण आकार नहीं होता है; आकार को कुछ उपयोगी इकाई बनाने के लिए आपको अभी भी आकार बदलने वाली चाल करने की आवश्यकता है, लेकिन फिर आपको भेजने के लिए स्थानों को स्पष्ट रूप से निर्दिष्ट करने के लिए स्कैटर के बजाय MPI_Scatterv का उपयोग करने की आवश्यकता है।
+1 यह होमवर्क कहने के लिए +1 है। :) – solvingPuzzles
@hattenn कृपया अब [होमवर्क] टैग का उपयोग न करें। यह बहिष्कृत है। [यह पुष्टि करने के लिए टैग को स्वयं देखें] (http://stackoverflow.com/questions/tagged/homework) –