Qt 並行運算高級API QtConcurrent


Qt Concurrent模塊擴展了Qt Core模塊中的基本線程支持,簡化了可以在所有可用的CPU核心上並行執行的代碼開發。

一些常用API:

  • Concurrent Map 和 Map-Reduce

QtConcurrent::map():將一個函數應用於一個容器中的每一項,就地修改 items。

QtConcurrent::mapped():和 map() 類似,只是它返回一個包含修改內容的新容器。

QtConcurrent::mappedReduced():和 mapped() 類似,只是修改后的結果減少或組合 成一個單一的結果。

  • Concurrent Filter 和 Filter-Reduce

QtConcurrent::filter():從容器中刪除所有滿足某個條件的item。

QtConcurrent::filtered():和 filter() 類似,只是它返回一個包含過濾內容的新容器。

QtConcurrent::filteredReduced():和 filtered() 類似,只是過濾后的結果減少或組合成一個單一的結果。

  • Concurrent Run

QtConcurrent::run():在另一個線程中運行一個函數。

QFuture:表示異步計算的結果

QFutureIterator:允許通過 QFuture 遍歷可用的結果

QFutureWatcher:允許使用信號槽來監控一個 QFuture

QFutureSynchronizer:是一個方便的類,用於一些 QFutures 的自動同步

Qt Concurrent 支持多種兼容 STL 的容器和迭代器類型,但是最好使用具有隨機訪問迭代器的 Qt 容器,例如:QList 或 QVector。map 和 filter 函數都接受容器和 begin/end 迭代器。

在 Qt Concurrent 迭代大量輕量級 items 的情況下,隨機訪問迭代器可以更快,因為它們允許跳過容器中的任何點。此外,使用隨機訪問迭代器允許 Qt Concurrent 通過 QFuture::progressValue() 和 QFutureWatcher::progressValueChanged() 來提供進度信息。

非就地修改的函數(例如:mapped() 和 filtered()),在調用時會創建容器的副本。如果正在使用的是 STL 容器,此復制操作可能需要一段時間,在這種情況下,建議為容器指定 begin 和 end 迭代器。

Concurrent Map 和 Map-Reduce示例:

 1 void add(int &num)  2 {  3     num +=1;  4 }  5 
 6 int mappedReducedFunction(const int& num)  7 {  8     return num + 1;  9 } 10 
11 void ReduceFunction(int& result, const int& item) 12 { 13     result = item > result ? item : result; 14 } 15 
16 { 17     QVector<int> vector; 18 
19     for(int i=0; i<3; i++) 20  vector.append(i); 21 
22     qDebug() << "start: " << vector; 23 
24     QFuture<void> vFuture = QtConcurrent::map(vector, add); 25  vFuture.waitForFinished(); 26 
27     qDebug() << "map result: " << vector; 28 
29     QFuture<int> iFuture = QtConcurrent::mappedReduced(vector, mappedReducedFunction, ReduceFunction); 30 
31     qDebug() << "mappedReduced result: " << iFuture.result(); 32 }

結果輸出:

start: QVector(0, 1, 2)
map result: QVector(1, 2, 3)
mappedReduced result: 4

QtConcurrent::mappedReduced() 類似於 QtConcurrent::mapped(),但是不是返回具有新結果的序列,而是使用 reduce 函數將結果組合成單個值。

reduce 函數必須是以下形式:

V function(T &result, const U &intermediate)

T 是最終結果的類型,U 是 map 函數的返回類型。注意: reduce 函數的返回值、返回類型沒有被使用。

對於 map 函數返回的每個結果,reduce 函數將被調用一次,並且應該將中間體合並到結果變量中。QtConcurrent::mappedReduced() 保證一次只有一個線程調用 reduce,所以沒有必要用一個 mutex 鎖定結果變量。

QtConcurrent::ReduceOptions 枚舉提供了一種方法來控制 reduction 完成的順序。如果使用 QtConcurrent::UnorderedReduce(默認),順序是不確定的;而 QtConcurrent::OrderedReduce 確保 reduction 按照原始序列的順序完成。

Concurrent Filter Filter-Reduce 與 Concurrent Map Map-Reduce 使用基本一致。

QtConcurrent::run() 函數在一個單獨的線程中運行一個函數, 函數的返回值通過 QFuture API 提供。

Concurrent Run示例:

 1 int add(int &num)  2 {  3      return ++num;  4 }  5 
 6 {  7     QFuture<int> future = QtConcurrent::run(add, 1);  8  future.waitForFinished();  9 
10     qDebug() << "result: " << future.result(); 11 }

結果輸出:

result: 2

上述兩個示例中,我們都是QFuture阻塞線程等待計算完成;QFuture 還提供了很多方法與正在進行的異步調用進行交互。例如,使用 cancel() 函數取消計算;要暫停計算,使用 setPaused() 函數或 pause(),resume()、togglePaused() 便利函數之一。

注意:並非所有異步計算都可以取消或暫停。例如,QtConcurrent::run() 返回的 future 不能被取消,但 QtConcurrent::mappedReduced() 返回的可以。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM