2012-05-28 3 views
10

का उपयोग कर एक मैट्रिक्स के कॉलम भेजना मैं एमपीआई का उपयोग कर एक मैट्रिक्स-वेक्टर गुणात्मक प्रोग्राम लिखने की कोशिश कर रहा हूं। मैं प्रक्रियाओं को अलग करने और स्थानीय रूप से परिणाम की गणना करने के लिए मैट्रिक्स के कॉलम भेजने की कोशिश कर रहा हूं। अंत में मैं MPI_SUM ऑपरेशन का उपयोग कर MPI_Reduce करता हूं।एमपीआई_Scatter

मैट्रिक्स की पंक्तियां भेजना आसान है क्योंकि सी स्टोर्स सरणी पंक्ति-प्रमुख क्रम में है, लेकिन कॉलम नहीं है (यदि आप उन्हें एक-एक करके नहीं भेजते हैं)।

MPI_Scatter - sending columns of 2D array

जोनाथन दर्सी नई एमपीआई डेटाटाइप्स का उपयोग कर सुझाव दिया और यहाँ क्या मैं अपने ही आवश्यकताओं के अपने कोड अनुकूल किया है है:: मैं सवाल यहाँ पढ़

double matrix[10][10]; 
    double mytype[10][10]; 
    int part_size; // stores how many cols a process needs to work on 
    MPI_Datatype col, coltype; 
    // ... 
    MPI_Type_vector(N, 1, N, MPI_DOUBLE, &col); 
    MPI_Type_commit(&col); 
    MPI_Type_create_resized(col, 0, 1*sizeof(double), &coltype); 
    MPI_Type_commit(&coltype); 
    // ... 
    MPI_Scatter(matrix, part_size, coltype, 
       mypart, part_size, coltype, 
       0, MPI_COMM_WORLD); 

    // calculations... 
    MPI_Reduce(local_result, global_result, 
      N, MPI_DOUBLE, 
      MPI_SUM, 
      0, MPI_COMM_WORLD); 

यह पूरी तरह से काम करता है, लेकिन मैं नहीं कह सकता कि मैं वास्तव में समझता हूं कि यह कैसे काम करता है।

  1. MPI_Type_vector मेमोरी में संग्रहीत कैसे है?
  2. MPI_Type_create_resized() कैसे काम करता है और यह वास्तव में क्या करता है?

कृपया ध्यान रखें कि मैं एमपीआई में कुल शुरुआत कर रहा हूं। अग्रिम में धन्यवाद।

+2

+1 यह होमवर्क कहने के लिए +1 है। :) – solvingPuzzles

+0

@hattenn कृपया अब [होमवर्क] टैग का उपयोग न करें। यह बहिष्कृत है। [यह पुष्टि करने के लिए टैग को स्वयं देखें] (http://stackoverflow.com/questions/tagged/homework) –

उत्तर

28

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=1MPI_DOUBLE रों कहा जाता है, stride=NMPI_DOUBLE के प्रत्येक ब्लॉक की शुरुआत के बीच एक स्थान के साथ। दूसरे शब्दों में, यह प्रत्येक एन'एथ डबल, कुल एन बार ले जाएगा; युगल के एनएक्सएन सरणी (एक साथ-संग्रहित) से एक कॉलम निकालने के लिए एकदम सही है। एक आसान जांच यह देखने के लिए है कि कितना डेटा चल रहा है (count*stride = N*N जो मैट्रिक्स का पूरा आकार है, चेक करें) और वास्तव में कितना डेटा शामिल है (count*blocksize = N, जो कॉलम का आकार है, जांचें।)

यदि आपको केवल व्यक्तिगत कॉलम का आदान-प्रदान करने के लिए MPI_Send और MPI_Recv को कॉल करना था, तो आप किया जाएगा; आप कॉलम के लेआउट का वर्णन करने के लिए इस प्रकार का उपयोग कर सकते हैं और आप ठीक होंगे। लेकिन एक और बात है।

आप MPI_Scatter पर कॉल करना चाहते हैं, जो प्रोसेसर 0 के लिए पहला कॉलटाइप (कहता है), प्रोसेसर 1 के लिए अगला कलटाइप भेजता है। यदि आप इसे सरल 1 डी सरणी के साथ कर रहे हैं, तो यह पता लगाना आसान है कि कहां "अगला" डेटा प्रकार है; यदि आप प्रत्येक प्रोसेसर को 1 int स्कैटर कर रहे हैं, तो "अगली" int पहली छोर समाप्त होने के तुरंत बाद शुरू होती है।

लेकिन अपने नए coltype स्तंभ कुल extent कि बाद में N*NMPI_DOUBLE रों करने के लिए स्तंभ की शुरुआत से चला जाता है है - अगर MPI_Scatter यही तर्क (यह होता है) इस प्रकार है, यह बाहर "अगले" कॉलम की तलाश शुरू होगा matrices स्मृति पूरी तरह से, और इतने पर अगले और अगले के साथ। न केवल आपको वह जवाब मिलेगा जो आप चाहते थे, कार्यक्रम शायद दुर्घटनाग्रस्त हो जाएगा।

एमपीईआई को यह बताने का तरीका है कि इस डेटा का "आकार" गणना करने के प्रयोजनों के लिए कहता है कि "अगला" एक कहां है, जहां एक कॉलम शुरू होता है और अगला कॉलम शुरू होता है; वह है, बिल्कुल एक MPI_DOUBLE। यह भेजे गए डेटा की मात्रा को प्रभावित नहीं करता है, जो अभी भी 1 कॉलम डेटा का मूल्य है; यह केवल "अगली पंक्ति में" गणना को प्रभावित करता है। किसी सरणी में कॉलम (या पंक्तियां) के साथ, आप इस आकार को स्मृति में उचित चरण आकार के रूप में भेज सकते हैं, और एमपीआई भेजने के लिए सही अगला कॉलम चुन देगा। इस आकार बदलने वाले ऑपरेटर के बिना, आपका प्रोग्राम शायद दुर्घटनाग्रस्त हो जाएगा।

जब आपके पास अधिक जटिल डेटा लेआउट होते हैं, जैसे ऊपर से जुड़े 2 डी-सरणी उदाहरण के 2 डी-ब्लॉक में, तो "अगली" वस्तुओं के बीच कोई भी एकल चरण आकार नहीं होता है; आकार को कुछ उपयोगी इकाई बनाने के लिए आपको अभी भी आकार बदलने वाली चाल करने की आवश्यकता है, लेकिन फिर आपको भेजने के लिए स्थानों को स्पष्ट रूप से निर्दिष्ट करने के लिए स्कैटर के बजाय MPI_Scatterv का उपयोग करने की आवश्यकता है।

+1

यह स्टैक ओवरफ्लो पर कभी भी मिले सबसे स्पष्ट उत्तरों में से एक है, बहुत बहुत धन्यवाद। अब यह सब स्पष्ट है। अगर मैं कर सकता था तो मैं 100 गुना ऊपर उठाना चाहता था :) – hattenn

+0

एडिनबर्ग समांतर कंप्यूटिंग सेंटर ने हमें एक मैट्रिक्स के 2 डी स्कैटर का उदाहरण प्रदान किया जो 'एमपीआई_यूबी' छद्म प्रकार के साथ बहिष्कृत 'एमपीआई_Type_create_struct' का उपयोग करता है ताकि ऊपरी बाउंड को बराबर बाउंड सेट किया जा सके। एक मैट्रिक्स तत्व का आकार (और उन्होंने कहा कि यह एक भयानक हैक था)। मुझे आश्चर्य है कि उन्होंने 'MPI_Type_create_resized()' का उपयोग क्यों नहीं किया - इसे 2003 के आसपास सूर्य एमपीआई में लागू किया जाना चाहिए था। –

+0

मुझे लगता है कि कभी-कभी जो लोग वार्ता देते हैं, वे डेवलपर्स के कोड को अपडेट करने से बहुत कम अक्सर अपनी स्लाइड अपडेट करते हैं; मुझे पता है कि कभी-कभी मैं कुछ हद तक पुराने उदाहरणों का उपयोग करने के लिए दोषी हूं, जो कि उनकी सबसे अच्छी तिथि से पहले है। –

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

  • कोई संबंधित समस्या नहीं^_^