看板 C_and_CPP 關於我們 聯絡資訊
C++17對不少現有的function提供parallel版本,例如: std::copy, std::find, std::sort, std::unique... (但有些function沒有,例如:std::sort_heap, std::copy_backward...) 要怎麼使用這些parallel function,就得了解本文要介紹的execution policy execution policy目前分成3種class,分別是 std::sequential_execution_policy, std::parallel_execution_policy, std::parallel_vector_execution_policy 而在namespace std裡,已經有這3個class的object,分別是 std::sequential, std::par, std::par_vec (關係如同std::defer_lock_t與std::defer_lock) 因此使用上,直接使用這3個object就可以 接下來將介紹不用execution policy的for_each,以及使用execution policy的for_each (底下的std::就不打了) vector<int> vec{1,2}; const auto func{[](const auto val){ cout<<val; cout<<val; }}; 不用execution policy: for_each(cbegin(vec),cend(vec),func); 執行結果: 1122 用sequential_execution_policy: for_each(sequential,cbegin(vec),cend(vec),func); 執行結果可能是: 1122 2211 用sequential_execution_policy,表示func不一定會按照順序執行 但同一時間,絕對不會有2個func被執行(所以不用避免data race) 用parallel_execution_policy: for_each(par,cbegin(vec),cend(vec),func); 執行結果可能是: 1122(由1個或2個thread執行的結果) 1212(由2個thread執行的結果) 1221(由2個thread執行的結果) 2112(由2個thread執行的結果) 2121(由2個thread執行的結果) 2211(由1個或2個thread執行的結果) 用parallel_execution_policy時,要避免data race的問題 到這邊為止,以上兩個都很正常,然而parallel_vector_execution_policy就比較特別了 用parallel_vector_execution_policy: for_each(par_vec,cbegin(vec),cend(vec),func); 執行結果跟parallel_execution_policy一樣,但是多增加4種可能的結果 對於1212, 1221, 2112, 2121,他們有可能是由1個thread執行的結果 也就是說,當這個thread執行完func的第一個cout<<val;時 他可能會跳去執行別的func的code(!?) 這邊就要說一下code執行的順序 一般來說,在同個thread底下,給予2個evaluation,A與B 要不就是A先執行,之後換B;不然就是B先執行,之後換A 然而,使用parallel_vector_execution_policy時,就會產生另一種情況 就是A先執行,然後A還沒執行完,就跳去執行B(這情況叫做unsequenced) 也就是說,1212的執行結果由來可能是 main thread(呼叫for_each的thread)執行第一個func main thread執行cout<<val; main thread跳到第二個func main thread執行cout<<val;(第二個func的第一個cout<<val;) main thread跳回第一個func main thread執行cout<<val;(第一個func的第二個cout<<val;) main thread跳到第二個func main thread執行cout<<val;(第二個func的第二個cout<<val;) 因此在用parallel_vector_execution_policy時,要非常小心,舉例來說: mutex mut; for_each(par_vec,cbegin(vec),cend(vec),[&](const auto val){ lock_guard<mutex> lock{mut}; cout<<val; }); 當第一個func執行完lock_guard<mutex> lock{mut};後 他可能會跳到另一個func,然後又執行lock_guard<mutex> lock{mut}; 此時就會發生undefined behavior 結語: 雖然以上講了那麼多,但是目前還沒有compiler支援execution policy 所以各位可能還要等一段時間,才能使用這些特性了 : 有些補充擺到另一篇文章了(#1NEeDZ3X) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.161.18.182 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1463401846.A.EE4.html
descent: 感謝分享 05/16 22:04
IKAFIRE: par_vec的用途是什麼? 05/16 22:32
讓for_each知道你是用什麼execution policy 而par_vec其實就是parallel_vector_execution_policy這個class的instance
x000032001: func的宣告好酷喔 XD 可以問一下關鍵字嗎 05/16 23:02
這個嗎? const auto func{[](const auto val){ cout<<val; cout<<val; }}; 這是C++11的lambda加上C++14的generic lambda
loveflames: func是lambda啊 05/16 23:19
x000032001: 主要是那對 {} 的用法 搭上const auto 蠻有js的感覺 05/16 23:43
holydc: 看起來 sequential 就滿像 js interpreter 的 policy 05/17 00:19
IKAFIRE: 呃,我是問那個policy的用途是什麼,什麼情況下會用到呢 05/17 01:37
※ 編輯: Caesar08 (111.251.48.57), 05/17/2016 22:56:20