2011-02-03 17 views
10

मैंने एक वर्ग तैयार किया है जो बहु थ्रेडिंग की शक्ति को देखने के लिए विभिन्न प्रकार के धागे का उपयोग करके पूर्णांक के साथ एक सरणी भरता है। लेकिन मेरे नतीजे के अनुसार, कोई भी नहीं है ...मेरा बहु थ्रेडिंग क्यों सक्षम नहीं है?

विचार: विचार "1" मान के साथ 100000000 पूर्णांक की सरणी भर गया था। (पूरे सरणी एक धागे भरता) 1 धागा के साथ शुरू और 100 धागे जब तक यह incrementing (प्रत्येक धागा आकार 100000000 की एक उप सरणी भरता/nbThreads)

उदाहरण: 10 धागे के साथ, मैं 10 धागे बना सकते हैं और प्रत्येक है 10000000 पूर्णांक की सरणी भरना।

1 THREADS: 196ms 
2 THREADS: 208ms 
3 THREADS: 222ms 
4 THREADS: 213ms 
5 THREADS: 198ms 
6 THREADS: 198ms 
7 THREADS: 198ms 
8 THREADS: 198ms 
9 THREADS: 198ms 
10 THREADS: 206ms 
11 THREADS: 201ms 
12 THREADS: 197ms 
13 THREADS: 198ms 
14 THREADS: 204ms 
15 THREADS: 199ms 
16 THREADS: 203ms 
17 THREADS: 234ms 
18 THREADS: 225ms 
19 THREADS: 235ms 
20 THREADS: 235ms 
21 THREADS: 234ms 
22 THREADS: 221ms 
23 THREADS: 211ms 
24 THREADS: 203ms 
25 THREADS: 206ms 
26 THREADS: 200ms 
27 THREADS: 202ms 
28 THREADS: 204ms 
29 THREADS: 202ms 
30 THREADS: 200ms 
31 THREADS: 206ms 
32 THREADS: 200ms 
33 THREADS: 205ms 
34 THREADS: 203ms 
35 THREADS: 200ms 
36 THREADS: 206ms 
37 THREADS: 200ms 
38 THREADS: 204ms 
39 THREADS: 205ms 
40 THREADS: 201ms 
41 THREADS: 206ms 
42 THREADS: 200ms 
43 THREADS: 204ms 
44 THREADS: 204ms 
45 THREADS: 206ms 
46 THREADS: 203ms 
47 THREADS: 204ms 
48 THREADS: 204ms 
49 THREADS: 201ms 
50 THREADS: 205ms 
51 THREADS: 204ms 
52 THREADS: 207ms 
53 THREADS: 202ms 
54 THREADS: 207ms 
55 THREADS: 207ms 
56 THREADS: 203ms 
57 THREADS: 203ms 
58 THREADS: 201ms 
59 THREADS: 206ms 
60 THREADS: 206ms 
61 THREADS: 204ms 
62 THREADS: 201ms 
63 THREADS: 206ms 
64 THREADS: 202ms 
65 THREADS: 206ms 
66 THREADS: 205ms 
67 THREADS: 207ms 
68 THREADS: 210ms 
69 THREADS: 207ms 
70 THREADS: 203ms 
71 THREADS: 207ms 
72 THREADS: 205ms 
73 THREADS: 203ms 
74 THREADS: 211ms 
75 THREADS: 202ms 
76 THREADS: 207ms 
77 THREADS: 204ms 
78 THREADS: 212ms 
79 THREADS: 203ms 
80 THREADS: 210ms 
81 THREADS: 206ms 
82 THREADS: 205ms 
83 THREADS: 203ms 
84 THREADS: 203ms 
85 THREADS: 209ms 
86 THREADS: 204ms 
87 THREADS: 206ms 
88 THREADS: 208ms 
89 THREADS: 263ms 
90 THREADS: 216ms 
91 THREADS: 230ms 
92 THREADS: 216ms 
93 THREADS: 230ms 
94 THREADS: 234ms 
95 THREADS: 234ms 
96 THREADS: 217ms 
97 THREADS: 229ms 
98 THREADS: 228ms 
99 THREADS: 215ms 
100 THREADS: 232ms 

मैं क्या याद किया:

public class ThreadedArrayFilling extends Thread{ 
    private int start; 
    private int partitionSize; 
    public static int[] data; 
    public static final int SIZE = 100000000; 
    public static final int NB_THREADS_MAX = 100; 


    public static void main(String[] args){ 
     data = new int[SIZE]; 
     long startTime, endTime; 
     int partition, startIndex, j; 
     ThreadedArrayLookup[] threads; 

     for(int i = 1; i <= NB_THREADS_MAX; i++){  
      startTime = System.currentTimeMillis(); 
      partition = SIZE/i; 
      startIndex = 0; 
       threads = new ThreadedArrayLookup[i]; 
      for(j = 0; j < i; j++){   
       threads[j] = new ThreadedArrayLookup(startIndex, partition); 
       startIndex += partition; 
      } 
      for(j = 0; j < i; j++){ 
       try { 
        threads[j].join(); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      endTime = System.currentTimeMillis();  
      System.out.println(i + " THREADS: " + (endTime - startTime) + "ms"); 
     } 
    } 

    public ThreadedArrayFilling(int start, int size){ 
     this.start = start; 
     this.partitionSize = size; 
     this.start(); 
    } 

    public void run(){ 
     for(int i = 0; i < this.partitionSize; i++){ 
      data[this.start + i] = 1; 
     } 
    } 

    public static String display(int[] d){ 
     String s = "["; 

     for(int i = 0; i < d.length; i++){ 
      s += d[i] + ", "; 
     } 

     s += "]"; 
     return s; 
    } 

} 

और यहाँ मेरी परिणाम हैं:

यहाँ मेरी कोड है?

संपादित करें: अतिरिक्त जानकारी:

मेरे मशीन एक डुअल कोर चल रहा है।

उम्मीदें:

  • मैं 1 और 2 धागे (डुअल कोर का उपयोग करना) के बीच प्रदर्शन में भारी वृद्धि देखने के लिए उम्मीद कर रहा था
  • मैं भी बाद एक मंदी देखने के लिए उम्मीद कर रहा था कि बड़ी संख्या में धागे के लिए।

लेकिन यह मेरी अपेक्षाओं में से कोई भी सत्यापित नहीं करता है। क्या मेरी उम्मीदें झूठी हैं, या क्या यह मेरे अहंकार के साथ एक समस्या है?

+1

@nbarraille, आपके मशीन पर आपके पास कितने कोर हैं? – dsolimano

+0

"उदाहरण: 10 धागे के साथ, मैं 10 धागे बना देता हूं और प्रत्येक 10000000 पूर्णांक की सरणी भर रहा है।" - मुझे लगता है कि आपका मतलब है कि प्रत्येक धागा सरणी के 1/10 को भर रहा है? – Grammin

+0

dsolimano: इस मशीन पर 2cores – nbarraille

उत्तर

18

दो कोर के साथ, संभवत: आप संभवतः सबसे अच्छा प्रदर्शन कर सकते हैं 2 थ्रेड एक थ्रेड के रूप में आधे समय लेते हैं।कोई भी अतिरिक्त थ्रेड केवल उसके बाद बेकार ओवरहेड बना रहा है - यह मानते हुए कि आप पूरी तरह से सीपीयू-बाध्य हैं, लेकिन आप वास्तव में नहीं हैं।

सवाल यह है कि 1 से 2 धागे से जाने पर आपको कोई सुधार क्यों नहीं दिख रहा है। और कारण यह है कि आपका प्रोग्राम सीपीयू-बाध्य नहीं है, लेकिन स्मृति-बाध्य है। आपकी बाधा मुख्य स्मृति पहुंच है, और 2 धागे सिर्फ मुख्य स्मृति में लिखने के लिए बदल रहे हैं। वास्तविक सीपीयू कोर अधिकतर समय कुछ नहीं कर रहे हैं। स्मृति के बड़े क्षेत्र पर थोड़ा वास्तविक काम करने की बजाय आप अपेक्षाकृत अंतर देखेंगे, आप स्मृति की एक छोटी राशि पर बहुत सी CPU-गहन काम करते हैं। क्योंकि तब प्रत्येक सीपीयू कोर अपने कैश के अंदर completel काम कर सकते हैं।

+0

धन्यवाद। मुझे मुद्दा मिला कि मुझे 1 और 2 धागे के बीच कोई प्रदर्शन वृद्धि क्यों नहीं दिखाई दे रही है। लेकिन आप कैसे समझा सकते हैं कि प्रदर्शन 100 धागे के लिए अपमानजनक नहीं है? – nbarraille

+0

अतिरिक्त प्रश्न: मुझे यह समझने के लिए दिया गया है कि कुछ अनुप्रयोगों में, आपके CPU की संख्या की तुलना में बहुत अधिक थ्रेड का उपयोग करने के लिए और अधिक कुशल हो सकता है, जब सीमित कारक CPU या स्मृति (डिस्क या नेटवर्क पहुंच की तरह नहीं) होता है। क्या आप इस बात से सहमत हैं? – nbarraille

+1

@nbarraille: हाँ, यह कुछ हद तक सच है। विचार यह है कि कुछ थ्रेड सीपीयू का उपयोग कर सकते हैं जबकि अन्य आईओ की प्रतीक्षा करते हैं। हालांकि, इन कार्यों के लिए अलग धागे (या धागे के पूल) का उपयोग करना बेहतर है। आप आम तौर पर डिस्क तक पहुंचने वाले एक से अधिक धागे नहीं चाहते हैं, और यह एक धागा गणना को गणना गणना धागे के पूल में सौंप सकता है। कई धागे के साथ गिरावट देखने के लिए, मुझे यकीन नहीं है। शायद प्रत्येक थ्रेड मूल रूप से अनुक्रम में अपना हिस्सा लेता है, इसलिए कोई विवाद ओवरहेड नहीं होता है, और थ्रेड सृजन ओवरहेड दो कोर होते हैं जो वैकल्पिक होते हैं, या केवल छोटे होते हैं। –

9

आपका सॉफ़्टवेयर सीपीयू-बाउंड होने पर मल्टीथ्रेडिंग बहुत ही कुशल है: ऐसे कई अनुप्रयोग हैं जो मोनो-थ्रेडेड हैं और आप उन्हें केवल एक कोर के उपयोग को अधिकतम करके आधुनिक CPUs को दर्दनाक रूप से देख सकते हैं (यह सीपीयू मॉनीटर में बहुत स्पष्ट रूप से दिखाई देता है)।

हालांकि (वर्चुअल) CPU की संख्या की तुलना में कई और धागे लॉन्च करने में कोई बात नहीं है।

सही बहु-थ्रेडेड अनुप्रयोग जो उदाहरण के लिए, संख्या क्रंचिंग करते हैं, जेवीएम के लिए उपलब्ध वर्चुअल) CPUs की संख्या से संबंधित कई कार्यकर्ता धागे बनाते हैं।

+0

हां, यही वह है जो मैं उम्मीद कर रहा था: जैसा कि मेरे कंप्यूटर में 2 सीपीयू हैं, मैं 1 और 2 कोर के बीच प्रदर्शन की वास्तविक वृद्धि देखने की उम्मीद कर रहा था, और फिर बड़ी संख्या में धागे के लिए मंदी। लेकिन मेरी धारणा में से कोई भी सत्यापित नहीं किया गया था ... – nbarraille

+4

@nbarraille - आपका कोड शायद सीपीयू बाध्य नहीं है, लेकिन स्मृति पहुंच गति से अधिक सीमित है। – Justin

+0

जस्टिन: क्या मैं इसे JVM में आवंटित स्मृति की मात्रा को बदलकर बदल सकता हूं? यदि हां, तो ग्रहण पर मैं ऐसा कैसे कर सकता हूं? – nbarraille

4

जो काम आप थ्रेड के अंदर करते हैं वह इतना छोटा होता है, उसके लिए उपयोग किया जाने वाला समय आपके सेटअप के ऊपरी हिस्से से अधिक होता है।

कुछ भारी गणना करें (उदाहरण के लिए सरणी में डालने के लिए पीआई का अनुमान लगाएं) आपको कई धागे का लाभ दिखाई देगा, लेकिन केवल आपके मशीन के कोर की संख्या लगभग ही होगी।

या ऐसा कुछ करें जो कुछ बाहरी (डेटाबेस से पढ़ना, किसी वेबसाइट से डेटा खरोंच) के लिए इंतजार कर रहा हो, तब तक यह अधिक प्रदर्शनकारी हो सकता है जब तक अन्य धागे कुछ उपयोगी न हों, जबकि अन्य प्रतीक्षा कर रहे हों।

0

दो धागे के लिए यह संभव है - प्रत्येक अपने स्वयं के सीपीयू या कोर के साथ - एकजुट होकर काम कर रहा है, ताकि एक काम धीमा हो सके, केवल एक धागा सभी काम करता है। दोनों कोर अपने एल 1 + एल 2 कैश को स्मृति में डेटा लिखने के लिए चाहते हैं जो ठीक है। हालांकि वे जल्द ही इस तरह से सामान्य एल 3 कैश को संतृप्त करते हैं कि यह अतिरिक्त लिखना बंद कर देता है जब तक कि यह रैम में एक अपडेटेड कैश लाइन लिखने में कामयाब न हो, जिससे नए लिखने को स्वीकार किया जा सके।

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

आपके धागे इतने छोटे हैं कि सभी संभावनाओं में वे एल 1 कैश में रहेंगे और इसलिए सिस्टम रैम से प्राप्त करने की आवश्यकता नहीं है जो रैम लिखने की आपकी क्षमता में बाधा डालती है। रैम को लिखने की आपकी क्षमता वही है चाहे आपके पास 1 या 100 धागे ऐसा करने की कोशिश कर रहे हों। आपके पास जितने अधिक धागे हैं, उतना अधिक थ्रेड प्रशासन ओवरहेड होगा। यह कुछ धागे के लिए नगण्य है लेकिन हर अतिरिक्त धागे के लिए बढ़ता है और अंततः ध्यान देने योग्य हो जाएगा।

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