निम्नलिखित बहुत सरल कंप्यूटर प्रोग्राम पर विचार करें:
for i = 1 to n:
y[i] = x[p[i]]
यहाँ और वाई हैं n बाइट्स की तत्व सरणियों, और पी एक है n शब्दों का तत्व सरणी। यहाँ n बड़ा है, उदाहरण के लिए, n = 2 31 (ताकि डेटा का केवल एक नगण्य अंश किसी भी प्रकार की कैश मेमोरी में फिट हो)।
मान लें कि में यादृच्छिक संख्याएँ हैं , समान रूप से 1 और n के बीच वितरित की जाती हैं ।
आधुनिक हार्डवेयर के दृष्टिकोण से, इसका मतलब निम्न होना चाहिए:
- पढ़ना सस्ता है (अनुक्रमिक रीड)
- पढ़ने बहुत महंगा है (यादृच्छिक पढ़ता है; लगभग सभी पढ़ता कैश छूट जाए हैं, हम मुख्य स्मृति से प्रत्येक व्यक्ति बाइट लाने के लिए करना होगा)
- लेखन सस्ते (अनुक्रमिक लिखने) है।
और यह वास्तव में मैं क्या देख रहा हूँ। प्रोग्राम की तुलना में प्रोग्राम बहुत धीमा है जो केवल अनुक्रमिक पढ़ता है और लिखता है। महान।
अब सवाल आता है: यह कार्यक्रम आधुनिक मल्टी-कोर प्लेटफार्मों पर कितनी अच्छी तरह से समानांतर है?
मेरी परिकल्पना यह थी कि यह कार्यक्रम अच्छी तरह से समानांतर नहीं है। आखिरकार, अड़चन मुख्य स्मृति है। एक मुख्य कोर पहले से ही अपना अधिकांश समय बर्बाद कर रहा है बस मुख्य मेमोरी से कुछ डेटा की प्रतीक्षा कर रहा है।
हालाँकि, यह तब नहीं था जब मैंने कुछ एल्गोरिदम के साथ प्रयोग करना शुरू किया, जहां अड़चन इस तरह का था!
मैंने बस भोले के लिए लूप को एक ओपनएमपी समानांतर-लूप के साथ बदल दिया (संक्षेप में, यह सिर्फ रेंज को छोटे भागों में विभाजित करेगा और इन भागों को समानांतर में विभिन्न सीपीयू कोर पर चलाएगा)।
कम-अंत वाले कंप्यूटरों पर, स्पीडअप वास्तव में मामूली थे। लेकिन उच्च-अंत वाले प्लेटफार्मों पर मुझे आश्चर्य हुआ कि मुझे उत्कृष्ट निकट-रैखिक स्पीडअप मिल रहा था। कुछ ठोस उदाहरण (सटीक समयावधि थोड़ी दूर हो सकती है, बहुत अधिक यादृच्छिक भिन्नता है; ये सिर्फ त्वरित प्रयोग थे):
2 x 4-कोर Xeon (कुल 8 कोर में): एकल-थ्रेडेड संस्करण की तुलना में कारक 5-8 स्पीडअप।
2 x 6-कोर Xeon (कुल 12 कोर में): एकल-थ्रेडेड संस्करण की तुलना में कारक 8-14 स्पीडअप।
अब यह पूरी तरह से अप्रत्याशित था। प्रशन:
सटीक रूप से इस तरह का कार्यक्रम इतनी अच्छी तरह से समानांतर क्यों करता है ? हार्डवेयर में क्या होता है? (मेरा वर्तमान अनुमान इन पंक्तियों के साथ कुछ है: अलग-अलग धागे से यादृच्छिक रीड "पाइपलाइड" हैं और इन पर उत्तर प्राप्त करने की औसत दर एक एकल धागे के मामले की तुलना में बहुत अधिक है।)
क्या किसी भी स्पीडअप को प्राप्त करने के लिए कई थ्रेड्स और कई कोर का उपयोग करना आवश्यक है ? Pipelining किसी तरह का वास्तव में मुख्य स्मृति और CPU के बीच इंटरफेस में जगह लेता है, तो एक-थ्रेडेड आवेदन मुख्य स्मृति पता है नहीं कर सका है कि यह जल्द ही की आवश्यकता होगी , एक्स [ पी [ मैं + 1 ] ] , ... और कंप्यूटर मुख्य मेमोरी से संबंधित कैश लाइनों को लाना शुरू कर सकता है? यदि यह सिद्धांत रूप में संभव है, तो मैं इसे अभ्यास में कैसे प्राप्त कर सकता हूं?
सही सैद्धांतिक मॉडल क्या है जिसका उपयोग हम इस तरह के कार्यक्रमों का विश्लेषण करने के लिए कर सकते हैं (और प्रदर्शन की सही भविष्यवाणी करते हैं)?
संपादित करें: अब कुछ स्रोत कोड और बेंचमार्क परिणाम यहां उपलब्ध हैं: https://github.com/suomela/parallel-random-read
बॉलपार्क के कुछ उदाहरण ( ):
- लगभग। एक धागे के साथ प्रति नेशन (यादृच्छिक पढ़ें) 42 एन एस
- लगभग। 12 कोर के साथ पुनरावृत्ति (यादृच्छिक पढ़ें) प्रति 5 एन एस।