सबसे पहले, सटीक उत्तर इस पर निर्भर करता है: (1) उपयोग, अर्थात फ़ंक्शन इनपुट तर्क, (2) MPI कार्यान्वयन गुणवत्ता और विवरण, और (3) आपके द्वारा उपयोग किए जा रहे हार्डवेयर। अक्सर, (2) और (3) संबंधित होते हैं, जैसे कि जब हार्डवेयर विक्रेता अपने नेटवर्क के लिए MPI का अनुकूलन करता है।
सामान्य तौर पर, छोटे संदेशों के लिए फ़्यूज़िंग एमपीआई कलेक्टिव बेहतर होता है, क्योंकि स्टार्ट-अप की लागतें नैटिव हो सकती हैं और कॉल्स को ब्लॉक करने के लिए कंप्यूर टाइम में भिन्नता होने पर कलेक्टिव्स को ब्लॉक करके सिंक्रोनाइजेशन को कम से कम किया जाना चाहिए। बड़े संदेशों के लिए, लक्ष्य यह होना चाहिए कि भेजे जाने वाले डेटा की मात्रा कम से कम हो।
उदाहरण के लिए, सिद्धांत रूप में, उसके बाद की MPI_Reduce_scatter_block
तुलना में बेहतर होना चाहिए , हालांकि पूर्व को अक्सर बाद के संदर्भ में लागू किया जाता है, जैसे कि कोई वास्तविक लाभ नहीं है। MPI के अधिकांश कार्यान्वयन में कार्यान्वयन गुणवत्ता और उपयोग की आवृत्ति के बीच संबंध है, और विक्रेता स्पष्ट रूप से उन कार्यों को अनुकूलित करते हैं जिनके लिए मशीन अनुबंध द्वारा इसकी आवश्यकता होती है।MPI_Reduce
MPI_Scatter
दूसरी तरफ, यदि कोई ब्लू जीन पर है, तो ऐसा MPI_Reduce_scatter_block
करना MPI_Allreduce
, जो कि अधिक संचार करता है MPI_Reduce
और MPI_Scatter
संयुक्त है, वास्तव में काफी तेज है। यह कुछ ऐसा है जिसे मैंने हाल ही में खोजा है और एमपीआई में प्रदर्शन आत्म-स्थिरता के सिद्धांत का एक दिलचस्प उल्लंघन है (यह सिद्धांत "स्व-सुसंगत एमपीआई प्रदर्शन दिशानिर्देश" में अधिक विस्तार से वर्णित है )।
तितर बितर + इकट्ठा करने के विशिष्ट मामले में, विचार करें कि पूर्व में, सभी डेटा को एक प्रक्रिया से और उसके पास जाना चाहिए, जो इसे अड़चन बनाता है, जबकि allgather में, डेटा सभी रैंकों में और बाहर प्रवाह कर सकते हैं , क्योंकि सभी रैंकों के पास सभी अन्य रैंकों को भेजने के लिए कुछ डेटा है। हालांकि, सभी नोड्स से एक बार में डेटा भेजना जरूरी नहीं है कि कुछ नेटवर्क पर एक अच्छा विचार है।
अंत में, इस प्रश्न का उत्तर देने का सबसे अच्छा तरीका यह है कि अपने कोड में निम्नलिखित करें और प्रयोग द्वारा प्रश्न का उत्तर दें।
#ifdef TWO_MPI_CALLS_ARE_BETTER_THAN_ONE
MPI_Scatter(..)
MPI_Gather(..)
#else
MPI_Allgather(..)
#endif
एक बेहतर विकल्प यह है कि अपने कोड को पहले दो पुनरावृत्तियों के दौरान प्रयोगात्मक रूप से मापें, फिर शेष पुनरावृत्तियों के लिए जो भी तेज़ हो उसका उपयोग करें:
const int use_allgather = 1;
const int use_scatter_then_gather = 2;
int algorithm = 0;
double t0 = 0.0, t1 = 0.0, dt1 = 0.0, dt2 = 0.0;
while (..)
{
if ( (iteration==0 && algorithm==0) || algorithm==use_scatter_then_gather )
{
t0 = MPI_Wtime();
MPI_Scatter(..);
MPI_Gather(..);
t1 = MPI_Wtime();
dt1 = t1-t0;
}
else if ( (iteration==1 && algorithm==0) || algorithm==use_allgather)
{
t0 = MPI_Wtime();
MPI_Allgather(..);
t1 = MPI_Wtime();
dt2 = t1-t0;
}
if (iteration==1)
{
dt2<dt1 ? algorithm=use_allgather : algorithm=use_scatter_then_gather;
}
}
MPI_Scatter
बाद एकMPI_Gather
ही संचार अर्थ प्रदान नहीं करता हैMPI_Allgather
। जब आप ऑपरेशन को किसी भी तरह से व्यक्त करते हैं तो शायद अतिरेक शामिल होता है?