當前位置:
首頁 > 知識 > 並行模式庫PPL應用實戰(一):使用task類創建並行任務

並行模式庫PPL應用實戰(一):使用task類創建並行任務

自 VS2010 起,微軟就在 CRT 中集成了並發運行時(Concurrency Runtime),並行模式庫(PPL,Parallel Patterns Library)是其中的一個重要組成部分。7 年過去了,似乎大家都不怎麼Care這個事情,相關文章少少且多是蜻蜓點水。實際上這個庫的設計相當精彩,勝過 C++ 標準庫中future/promise/async系列許多,所以計劃寫一個系列探討 PPL 在實際項目中應用中的各種細節。

好了,從最簡單的代碼開始,先演示下如何使用 task類和 lambda 表達式創建一個並行任務:

// final_answer.cpp
// compile with: /EHsc

#include #include

using namespace concurrency;
using namespace std;

int main(int argc, char *argv[])
{
task final_answer([]
{
return 42;
});

cout << "The final answer is: " << final_answer.get << endl; return 0; }

使用 Visual Studio 命令行工具編譯

cl /EHsc final_answer.cpp

執行結果為:


The final answer is: 42

task類的原型如下:

template
class task;

其模板參數 _ReturnType 是任務返回值類型。 task:get方法則用於獲取返回值,原型如下:

_ReturnType get const;

task類的構造函數原型:

template
__declspec(noinline) explicit task(T _Param);

可以看到這是個模板函數,其參數 _Param 可以是 lambda 表達式、函數對象、仿函數、函數指針等可以以 _Param 形式調用的類型,或者 PPL 中的task_completion_event類型。因此可以使用各種靈活的方式構造task對象,其中 lambda 表達式無疑是最方便常用的一種。

接下來我們修改上面的程序,列印出線程 id 以便觀察並行任務的執行情況。

// final_answer_1.cpp
// compile with: /EHsc

#include #include
#include

using namespace concurrency;
using namespace std;

int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id << endl; task final_answer(
{
cout << "Thread id in task is:" << this_thread::get_id << endl; return 42; }); cout << "The final answer is: " << final_answer.get << endl; return 0; }

繼續編譯執行,得到輸出結果:


Major thread id is: 164824

Thread id in task is: 164824

The final answer is: 42

注意兩個線程 id 是相同的,很有些意外,任務是在主線程執行的而非預計的其他後台工作線程。實際上這是 PPL 的優化策略造成的。

再修改下程序,在 task對象構造完成後加一個 sleep 調用掛起當前線程一小段時間:

int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id << endl; task final_answer(
{
cout << "Thread id in task is:" << this_thread::get_id << endl; return 42; }); this_thread::sleep_for(chrono::milliseconds(1)); cout << "The final answer is: " << final_answer.get << endl; return 0; }

這次輸出結果發生了變化:

Major thread id is: 173404

Thread id in task is: 185936

The final answer is: 42

PPL 使用了一個新的線程執行並行任務,實際上 PPL 是使用了線程池來執行被調度到的任務。

而在上一個程序中,由於沒有 sleep,也沒有其他耗時的代碼,執行到 task::get 方法時並行任務尚未被調度所以直接在當前線程執行該任務,這樣就節省了兩次線程切換的開銷

MSDN 中對 task::wait 方法的說明:


It is possible for

wait

to execute the task inline, if all of the tasks dependencies are satisfied, and it has not already been picked up for execution by a background worker.

task::get 方法的內部實現會先調用 task::wait 方法所以有同樣的效果。

本章小結:

1. task 類對象構造完成後即可被調度執行;

2. 並行有可能被優化在當前線程執行;

留一個問題,如果 task 對象構造後馬上析構,該並行任務是否會被調度執行呢?

本章代碼使用 visual studio community 2013 編譯調試通過。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

EF Core學習Code First
多線程和非同步編程示例和實踐-踩過的坑
Java類的載入的一個小問題
ElasticSearch裡面一些小坑筆記

TAG:達人科技 |

您可能感興趣

如何讓語言模型充分利用GPU:針對大規模並行設備的N-gram
使用 Dask 在 Python 中進行並行計算
Python數據預處理:使用Dask和Numba並行化加速
基於改進MapReduce模型的BP神經網路並行化研究
任務調度並行演算法的Python簡單實現
initial語句中的並行執行和串列執行
技術創新與產品質量並行 OPPO Find X無懼跌落和灰塵
ClusterShell:一個在集群節點上並行運行命令的好工具
一行 Python 代碼實現並行,騷技能!
Dover Street Market:時尚大廈與藝術空間並行的零售先驅
friedman benda舉行並行展覽 探索建築師傢具設計
Loom Network-並行側鏈
基於密度峰值優化的Canopy-Kmeans並行演算法
Python中的並行處理:實例編程指南
Gyrfalcon Technology入局AI晶元戰場,研發存儲計算融合一體的本地並行AI運算架構
Uber 開源 Plato:擴展性極強的開發測試會話 AI 平台,可實現多智能體並行訓練
Uber 開源 Plato:擴展性極強的開發測試會話 AI 平台,可實現多智能體並行訓練!
VasSonic源碼之並行載入
降噪與助聽並行,Nuheara IQbuds Max無線耳機發布
科技與時尚並行 手機望遠鏡OPPO Reno入手初體驗!