2011-04-13 11 views
18

मैं NSThread और ग्रांड सेंट्रल डिस्पैच (GCD) के लिए कुछ परीक्षण कोड बनाया:ग्रांड सेंट्रल डिस्पैच बनाम NSThread

- (void)doIt:(NSNumber *)i 
{ 
sleep(1); 
NSLog(@"Thread#%i", [i intValue]); 
} 

- (IBAction)doWork:(id)sender 
{ 

for (int i = 0; 10 > i; i++) { 
    NSNumber *t = [NSNumber numberWithInt:i]; 
    [NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t]; 
} 

sleep(1); 

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_apply(10, queue, ^(size_t i) { 
    sleep(1); 
    NSLog(@"GCD#%u",(int)i); 
}); 
} 

और परिणाम:

2011-04-13 19:41:07.806 GDC[1494:5e03] Thread#0 
2011-04-13 19:41:07.813 GDC[1494:6903] Thread#3 
2011-04-13 19:41:07.812 GDC[1494:6403] Thread#2 
2011-04-13 19:41:07.812 GDC[1494:5f03] Thread#1 
2011-04-13 19:41:07.813 GDC[1494:6e03] Thread#4 
2011-04-13 19:41:07.814 GDC[1494:7303] Thread#5 
2011-04-13 19:41:07.814 GDC[1494:7803] Thread#6 
2011-04-13 19:41:07.815 GDC[1494:7d03] Thread#7 
2011-04-13 19:41:07.815 GDC[1494:8203] Thread#8 
2011-04-13 19:41:07.816 GDC[1494:8703] Thread#9 
2011-04-13 19:41:08.812 GDC[1494:707] GCD#0 
2011-04-13 19:41:09.816 GDC[1494:707] GCD#1 
2011-04-13 19:41:10.819 GDC[1494:707] GCD#2 
2011-04-13 19:41:11.825 GDC[1494:707] GCD#3 
2011-04-13 19:41:12.828 GDC[1494:707] GCD#4 
2011-04-13 19:41:13.833 GDC[1494:707] GCD#5 
2011-04-13 19:41:14.838 GDC[1494:707] GCD#6 
2011-04-13 19:41:15.848 GDC[1494:707] GCD#7 
2011-04-13 19:41:16.853 GDC[1494:707] GCD#8 
2011-04-13 19:41:17.857 GDC[1494:707] GCD#9 

NSThreads काम के रूप में मैं उम्मीद: कार्य एक साथ चलते हैं और प्रत्येक धागा 1 सेकंड के लिए सोता है।

प्रेषण_प्लीली काम नहीं करता है जैसा कि मैंने अपेक्षित किया था: क्रम अनुक्रमिक क्यों है? पिछले लूप खत्म होने तक प्रत्येक लूप प्रतीक्षा क्यों करता है?

सहायता के लिए धन्यवाद।

उत्तर

33

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

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

संपादित करें: मैंने अपने मैक पर एक साधारण कमांड लाइन प्रोग्राम में आपके कोड के साथ थोड़ा सा खेला। जैसा कि मैंने नीचे दी गई मेरी टिप्पणी में सुझाव दिया है, और @के बजाय dispatch_async() का उपयोग करके @ रेन-डी के उत्तर में भी उल्लेख किया है, यह एक बड़ा अंतर बनाता है। यहाँ कोड मैं प्रयोग किया जाता है:

- (void)doIt:(NSNumber *)i 
{ 
    for (int j = 0; j < MAX_COUNT; j++) 
     ; 
    NSLog(@"Thread#%i", [i intValue]); 
} 

- (void)doWork:(id)sender 
{ 
    for (int i = 0; i<10; i++) { 
     NSNumber *t = [NSNumber numberWithInt:i]; 
     [NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t]; 
    } 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    for (size_t i = 0; i<10; i++) { 
     dispatch_async(queue, ^(void) { 
      for (int j = 0; j < MAX_COUNT; j++) 
       ; 
      NSLog(@"GCD#%u",(int)i); 
     }); 
    } 
    NSLog(@"Done."); 
    sleep(15); 
} 

आप देख सकते हैं, मैं for छोरों कि कुछ समय गिनती खर्च के साथ अपने sleep() कॉल बदल दिया। (मैंने मैकबुक प्रो पर कोड चलाया - यदि आप किसी आईफोन पर चल रहे हैं तो आप नीचे MAX_COUNT के मान को समायोजित करना चाहेंगे।) यदि आप थ्रेड और ब्लॉक दोनों में sleep() का उपयोग करते हैं, तो dispatch_async() ब्लॉक केवल व्यवहार करते हैं धागे की तरह - सभी ब्लॉक एक साथ चलते हैं और एक ही समय में पूरा होते हैं। व्यवहार को बदलने की गणना करने के लिए स्विचिंग - कई धागे सभी एक साथ चलते हैं, लेकिन समूहों में ब्लॉक निष्पादित होते हैं (मेरी मशीन में दो प्रोसेसर कोर होते हैं, इसलिए यह दो समूहों में ब्लॉक चलाता है)। यह वही है जैसा आप उम्मीद करेंगे; जीसीडी का काम कार्यों को कतार करना और जितना संभव हो सके उन्हें उपलब्ध संसाधनों का सबसे अच्छा उपयोग करना है, जितना संभव हो सके उतने कार्यों को चलाने के लिए नहीं।

2011-04-14 02:48:46.840 BlockTest[14969:903] Hello, World! 
2011-04-14 02:48:47.104 BlockTest[14969:903] Done. 
2011-04-14 02:48:52.834 BlockTest[14969:1503] Thread#0 
2011-04-14 02:48:52.941 BlockTest[14969:4f03] GCD#0 
2011-04-14 02:48:52.952 BlockTest[14969:5003] GCD#1 
2011-04-14 02:48:52.956 BlockTest[14969:4703] Thread#8 
2011-04-14 02:48:53.030 BlockTest[14969:3703] Thread#4 
2011-04-14 02:48:53.074 BlockTest[14969:2b03] Thread#1 
2011-04-14 02:48:53.056 BlockTest[14969:4b03] Thread#9 
2011-04-14 02:48:53.065 BlockTest[14969:3b03] Thread#5 
2011-04-14 02:48:53.114 BlockTest[14969:3303] Thread#3 
2011-04-14 02:48:53.138 BlockTest[14969:4303] Thread#7 
2011-04-14 02:48:53.147 BlockTest[14969:3f03] Thread#6 
2011-04-14 02:48:53.156 BlockTest[14969:2f03] Thread#2 
2011-04-14 02:48:53.909 BlockTest[14969:4f03] GCD#2 
2011-04-14 02:48:53.915 BlockTest[14969:5003] GCD#3 
2011-04-14 02:48:54.700 BlockTest[14969:4f03] GCD#4 
2011-04-14 02:48:54.721 BlockTest[14969:5003] GCD#5 
2011-04-14 02:48:55.508 BlockTest[14969:4f03] GCD#6 
2011-04-14 02:48:55.550 BlockTest[14969:5003] GCD#7 
2011-04-14 02:48:56.321 BlockTest[14969:4f03] GCD#8 
2011-04-14 02:48:56.345 BlockTest[14969:5003] GCD#9 

ध्यान दें कि ब्लॉक के दो वास्तव में सभी धागे में से एक है लेकिन इससे पहले समाप्त हो गया:

यहाँ ऊपर कोड से उत्पादन है। इसके अलावा: कोड के अंत में sleep(15) प्रोग्राम को समाप्त होने से पहले धागे और ब्लॉक को उनके संदेशों को लॉग करने दें। इस कोड के आधार पर कि आप किस प्रकार के प्रोग्राम को कोड पेस्ट करते हैं, आपको इसकी आवश्यकता नहीं हो सकती है।

+0

तो बेकार है? और मुझे एनएसटीएचड का उपयोग करना चाहिए? – CarlJ

+5

बिलकुल नहीं। इसके बजाय dispatch_async() आज़माएं। – Caleb

+1

दूसरा उत्तर सही है। dispatch_apply तुल्यकालिक है। आपके उत्तर के लिए – XJones

7

कोशिश इस वेबसाइट को देखने के लिए: http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

आईओएस वातावरण में, कहा जाता है कि dispatch_apply कतार में पारित कर दिया पर निर्भर करेगा, अगर लक्ष्य कतार एक समवर्ती कतार dispatch_get_global_queue द्वारा दिया (जो आपके मामला है) है , ब्लॉक समवर्ती रूप से लागू किया जा सकता है।

तो, मुझे लगता है कि यह काम कर रहा है, बस ऐसा होता है कि ऐसा लगता है कि यह असीमित रूप से चलता है। साथ ही, कोड पर कौन सा डिवाइस चलाया जा सकता है परिणाम पर एक भूमिका निभा सकता है (जैसे @ कैलेब द्वारा उल्लिखित)। लेकिन मेरा सुझाव है, शायद इसके बजाय dispatch_async आज़माएं?

+1

वह पृष्ठ मैक संदर्भ के लिए है, जो दुख की बात है (टैग की गईं) [आईओएस संदर्भ] (http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference से अलग है। एचटीएमएल) ... "यदि लक्ष्य कतार dispatch_get_global_queue द्वारा लौटाई गई समवर्ती कतार है, तो ब्लॉक को समवर्ती रूप से बुलाया जा सकता है, और इसलिए इसे पुनर्वित्त-सुरक्षित होना चाहिए। समवर्ती कतार के साथ इस फ़ंक्शन का उपयोग लूप के लिए एक समान समानांतर के रूप में उपयोगी हो सकता है । " –

+1

मेरा बुरा, मूल टैग, जहां मैंने इस प्रश्न का उत्तर दिया था 'कोको' और 'ios' था। मैंने यह मानकर गलती की कि यह इसके बजाय 'कोको' पर था। – Rpranata

2

किसी को भी परीक्षण करना चाहते हैं, जो विधि spedify probleme के लिए सबसे अच्छा है, यहाँ कोड IST है:

#define MAX_COUNT 99999999 
#define HOW_MUCH 10 
- (void)doIt:(NSNumber *)i 
{ 
    for (int j = 0; j < MAX_COUNT; j++) 
     ; 
    NSLog(@"Thread#%i", [i intValue]); 
} 


- (IBAction)doWork:(id)sender 
{ 
    NSLog(@"START"); 

    for (int i = 0; i < HOW_MUCH; i++) { 
     NSNumber *t = [NSNumber numberWithInt:i]; 
     [NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t]; 
    } 

    sleep(3); 


    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_apply(HOW_MUCH, queue, ^(size_t i) { 
     for (int j = 0; j < MAX_COUNT; j++) 
      ; 
     NSLog(@"GCD APPLY %u",(int)i); 
    }); 


    sleep(3); 

    for (size_t k = 0; k < HOW_MUCH; k++) { 
     dispatch_async(queue, ^(void) { 
      for (int j = 0; j < MAX_COUNT; j++) 
       ; 
      NSLog(@"GCD ASYNC#%u",(int)k); 
     }); 
    } 

    sleep(10); 
    NSLog(@"DONE"); 
} 
एक iOS डिवाइस GCD पर

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

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