並行模式庫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
using namespace concurrency;
using namespace std;
int main(int argc, char *argv[])
{
task
{
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 其模板參數 _ReturnType 是任務返回值類型。 task:get方法則用於獲取返回值,原型如下:
class task;
_ReturnType get const;
task類的構造函數原型:
template 可以看到這是個模板函數,其參數 _Param 可以是 lambda 表達式、函數對象、仿函數、函數指針等可以以 接下來我們修改上面的程序,列印出線程 id 以便觀察並行任務的執行情況。 // final_answer_1.cpp #include using namespace concurrency; int main(int argc, char *argv[]) 繼續編譯執行,得到輸出結果: 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[]) 這次輸出結果發生了變化: Major thread id is: 173404 Thread id in task is: 185936 The final answer is: 42
__declspec(noinline) explicit task(T _Param);
_Param
形式調用的類型,或者 PPL 中的task_completion_event
// compile with: /EHsc
#include
using namespace std;
{
cout << "Major thread id is: " << this_thread::get_id << endl;
task
{
cout << "Thread id in task is:" << this_thread::get_id << endl;
return 42;
});
cout << "The final answer is: " << final_answer.get << endl;
return 0;
}
{
cout << "Major thread id is: " << this_thread::get_id << endl;
task
{
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;
}
PPL 使用了一個新的線程執行並行任務,實際上 PPL 是使用了線程池來執行被調度到的任務。
而在上一個程序中,由於沒有 sleep,也沒有其他耗時的代碼,執行到 task::get 方法時並行任務尚未被調度所以直接在當前線程執行該任務,這樣就節省了兩次線程切換的開銷。
MSDN 中對 task::wait 方法的說明:
It is possible forwait
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入手初體驗!