偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

GCD介紹(二):多核心的性能

移動開發(fā) iOS
本文中我們討論了如何使用GCD來提升程序性能以及發(fā)揮多核系統(tǒng)的優(yōu)勢。盡管我們需要比較謹慎地編寫并發(fā)程序,GCD還是使得我們能更簡單地發(fā)揮系統(tǒng)的可用計算資源。

[[77410]]

概念

為了在單一進程中充分發(fā)揮多核的優(yōu)勢,我們有必要使用多線程技術(我們沒必要去提多進程,這玩意兒和GCD沒關系)。在低層,GCD全局dispatch queue僅僅是工作線程池的抽象。這些隊列中的Block一旦可用,就會被dispatch到工作線程中。提交至用戶隊列的Block最終也會通過全局隊列進入相同的工作線程池(除非你的用戶隊列的目標是主線程,但是為了提高運行速度,我們絕不會這么干)。

有兩種途徑來通過GCD“榨取”多核心系統(tǒng)的性能:將單一任務或者一組相關任務并發(fā)至全局隊列中運算;將多個不相關的任務或者關聯(lián)不緊密的任務并發(fā)至用戶隊列中運算;

全局隊列

設想下面的循環(huán):

  1. for(id obj in array)  
  2.     [self doSomethingIntensiveWith:obj]; 

假定 -doSomethingIntensiveWith: 是線程安全的且可以同時執(zhí)行多個.一個array通常包含多個元素,這樣的話,我們可以很簡單地使用GCD來平行運算:

  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. for(id obj in array)  
  3.     dispatch_async(queue, ^{  
  4.         [self doSomethingIntensiveWith:obj];  
  5.     }); 

如此簡單,我們已經在多核心上運行這段代碼了。

當然這段代碼并不完美。有時候我們有一段代碼要像這樣操作一個數(shù)組,但是在操作完成后,我們還需要對操作結果進行其他操作:

  1. for(id obj in array)  
  2.     [self doSomethingIntensiveWith:obj];  
  3. [self doSomethingWith:array]; 

這時候使用GCD的 dispatch_async 就悲劇了.我們還不能簡單地使用dispatch_sync來解決這個問題, 因為這將導致每個迭代器阻塞,就完全破壞了平行計算。

解決這個問題的一種方法是使用dispatch group。一個dispatch group可以用來將多個block組成一組以監(jiān)測這些Block全部完成或者等待全部完成時發(fā)出的消息。使用函數(shù)dispatch_group_create來創(chuàng)建,然后使用函數(shù)dispatch_group_async來將block提交至一個dispatch queue,同時將它們添加至一個組。所以我們現(xiàn)在可以重新編碼:

  1. dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_group_t group = dispatch_group_create();  
  3. for(id obj in array)  
  4.     dispatch_group_async(group, queue, ^{  
  5.         [self doSomethingIntensiveWith:obj];  
  6.     });  
  7. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);  
  8. dispatch_release(group);  
  9. [self doSomethingWith:array]; 

如果這些工作可以異步執(zhí)行,那么我們可以更風騷一點,將函數(shù)-doSomethingWith:放在后臺執(zhí)行。我們使用dispatch_group_async函數(shù)建立一個block在組完成后執(zhí)行:

  1. dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_group_t group = dispatch_group_create();  
  3. for(id obj in array)  
  4.     dispatch_group_async(group, queue, ^{  
  5.         [self doSomethingIntensiveWith:obj];  
  6.     });  
  7. dispatch_group_notify(group, queue, ^{  
  8.     [self doSomethingWith:array];  
  9. });  
  10. dispatch_release(group); 

不僅所有數(shù)組元素都會被平行操作,后續(xù)的操作也會異步執(zhí)行,并且這些異步運算都會將程序的其他部分的負載考慮在內。注意如果-doSomethingWith:需要在主線程中執(zhí)行,比如操作GUI,那么我們只要將main queue而非全局隊列傳給dispatch_group_notify函數(shù)就行了。

對于同步執(zhí)行,GCD提供了一個簡化方法叫做dispatch_apply。這個函數(shù)調用單一block多次,并平行運算,然后等待所有運算結束,就像我們想要的那樣:

  1. dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2.     dispatch_apply([array count], queue, ^(size_t index){  
  3.         [self doSomethingIntensiveWith:[array objectAtIndex:index]];  
  4.     });  
  5.     [self doSomethingWith:array]; 

這很棒,但是異步咋辦?dispatch_apply函數(shù)可是沒有異步版本的。但是我們使用的可是一個為異步而生的API??!所以我們只要用dispatch_async函數(shù)將所有代碼推到后臺就行了:

  1. dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_async(queue, ^{  
  3.     dispatch_apply([array count], queue, ^(size_t index){  
  4.         [self doSomethingIntensiveWith:[array objectAtIndex:index]];  
  5.     });  
  6.     [self doSomethingWith:array];  
  7. }); 

簡單的要死!

這種方法的關鍵在于確定我們的代碼是在一次對不同的數(shù)據(jù)片段進行相似的操作。如果你確定你的任務是線程安全的(不在本篇討論范圍內)那么你可以使用GCD來重寫你的循環(huán)了,更平行更風騷。

要看到性能提升,你還得進行一大堆工作。比之線程,GCD是輕量和低負載的,但是將block提交至queue還是很消耗資源的——block需要被拷貝和入隊,同時適當?shù)墓ぷ骶€程需要被通知。不要將一張圖片的每個像素作為一個block提交至隊列,GCD的優(yōu)點就半途夭折了。如果你不確定,那么請進行試驗。將程序平行計算化是一種優(yōu)化措施,在修改代碼之前你必須再三思索,確定修改是有益的(還有確保你修改了正確的地方)。

Subsystem并發(fā)運算

前面的章節(jié)我們討論了在程序的單個subsystem中發(fā)揮多核心的優(yōu)勢。下來我們要跨越多個子系統(tǒng)。

例如,設想一個程序要打開一個包含meta信息的文檔。文檔數(shù)據(jù)本身需要解析并轉換至模型對象來顯示,meta信息也需要解析和轉換。但是,文檔數(shù)據(jù)和meta信息不需要交互。我們可以為文檔和meta各創(chuàng)建一個dispatch queue,然后并發(fā)執(zhí)行。文檔和meta的解析代碼都會各自串行執(zhí)行,從而不用考慮線程安全(只要沒有文檔和meta之間共享的數(shù)據(jù)),但是它們還是并發(fā)執(zhí)行的。

一旦文檔打開了,程序需要響應用戶操作。例如,可能需要進行拼寫檢查、代碼高亮、字數(shù)統(tǒng)計、自動保存或者其他什么。如果每個任務都被實現(xiàn)為在不同的dispatch queue中執(zhí)行,那么這些任務會并發(fā)執(zhí)行,并各自將其他任務的運算考慮在內(respect to each other),從而省去了多線程編程的麻煩。

使用dispatch source(下次我會講到),我們可以讓GCD將事件直接傳遞給用戶隊列。例如,程序中監(jiān)視socket連接的代碼可以被置于它自己的dispatch queue中,這樣它會異步執(zhí)行,并且執(zhí)行時會將程序其他部分的運算考慮在內。另外,如果使用用戶隊列的話,這個模塊會串行執(zhí)行,簡化程序。

結論

我們討論了如何使用GCD來提升程序性能以及發(fā)揮多核系統(tǒng)的優(yōu)勢。盡管我們需要比較謹慎地編寫并發(fā)程序,GCD還是使得我們能更簡單地發(fā)揮系統(tǒng)的可用計算資源。

下一篇中,我們將討論dispatch source,也就是GCD的監(jiān)視內部、外部事件的機制。

責任編輯:閆佳明 來源: dreamingwish
相關推薦

2013-07-15 16:28:15

iOS多線程GCD介紹Dispatch Qu

2011-07-21 14:15:08

java

2013-07-15 16:18:08

2013-07-15 16:55:54

iOS多線程GCD實戰(zhàn)資源競爭

2009-06-18 09:47:14

Spring的核心

2009-10-23 09:58:54

2009-03-22 19:19:15

多核多核服務器多核歷史

2010-03-04 09:22:14

Firefox新版下載

2016-09-07 09:27:39

多核心芯片CPU手機芯片

2013-07-15 15:51:32

iOS多線程GCD基本概念Dispatch Qu

2009-10-19 10:26:39

2009-10-23 08:12:31

Windows 7系統(tǒng)能耗

2013-12-25 10:31:13

多核英特爾18核心

2014-08-08 15:27:45

性能Apdex

2010-06-29 10:20:11

LEACH協(xié)議

2011-04-13 13:45:04

數(shù)據(jù)庫虛擬化

2009-12-17 14:28:20

桌面Linux版本

2011-07-21 13:51:38

java

2010-05-26 17:39:38

Linux性能監(jiān)控

2010-05-26 18:52:28

Linux 查看性能
點贊
收藏

51CTO技術棧公眾號