Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Boost9 session

2,205 views

Published on

Published in: Technology
  • Be the first to comment

Boost9 session

  1. 1. 並行・並列への C++ としてのアプローチ
  2. 2. 自己紹介@Flast_ROhttp://ftp2.jp.vim.org/pub/vim とかミラーしてても金は降ってこないので転がり込む先を探 してる初めて触ったのは巫女でしたCryolite の敵
  3. 3. C(ry の敵
  4. 4. Agenda並行と並列、スレッドとかBoost.ContextC++ 標準委員会での動き
  5. 5. 並行と並列の違い並行 (concurrent) :複数の処理単位が論理的に独立して 動作すること並列 (parallel) :実際に複数の処理単位が同時に動作して いる様子ほとんどの場合混同されてるし、大方通じるので問題な いのでは… … ?
  6. 6. プロセスとスレッドどちらも少なくとも並行を実現 最近のマルチコア環境ならコアの数だけプロセスもスレッド も並列に走るように OS がしてくれるプロセスは独立したプロセス空間を持つが、スレッドは スレッド固有のリソース以外はプロセス内で共有スケジューリングは OS が担当プラットフォーム依存の API を使用しないといけない プロセス: fork, CreateProcess ... スレッド: POSIX Thread, CreateThread ...
  7. 7. はー、またプラットフォーム依存 ... sasso-sasso-
  8. 8. Boostプロセス Interprocess, Process(sandbox) ...スレッド Thread, InterThreads(sandbox) ...その他 Asio, MPI ...
  9. 9. Boostプロセス Interprocess, Process(sandbox) ...スレッド Thread, InterThreads(sandbox) ...その他 Asio, MPI ...
  10. 10. Boost.Thread v21.50.0 から v1 は提供されず v2 に完全移行(予定)C++11 compliance が中心Move semantics が Boost.Move ベースになるBoost.DateTime ベースの this_thread::sleep に加え Boost.Chrono ベースの this_thread::sleep_(for|until)
  11. 11. Boost.Thread v31.55.0 から v3 へ移行予定 1.50.0 から 1.54.0 は v3 への移行期間 #define BOOST_THREAD_VERSION 3マクロで互換性等を細かく設定できる e.g. #define BOOST_THREAD_DONT_PROVIDE_FUTURE ifdef → boost::unique_future else → boost::future
  12. 12. ところで、スレッドにも種類がある
  13. 13. カーネルスレッドとユーザースレッドスケジューリングを誰がやるかが一番のポイント カーネルスレッドは知らないうちに実行コンテキストが変 わっている ユーザースレッドはプログラマが明示的にコンテキストス イッチを仕込まなければならないユーザースレッド単体では並行しかできないが、カーネ ルスレッドは並列に動作する可能性高いユーザースレッドのコンテキストスイッチは自分でアセ ンブリを書く必要がある
  14. 14. ユーザースレッドの目的カーネルスレッドはコンテキストスイッチのコストが非 常に大きいスケジューリングする必要がある場合一連の流れを細切れにしてコールバックとかにするより 処理の流れがわかりやすい
  15. 15. Agenda並行と並列、スレッドとかBoost.ContextC++ 標準委員会での動き
  16. 16. Boost.Contextユーザーレベルでのコンテキストスイッチ機構を提供す るライブラリ作者は Oliver Kowalke http://ok73.ok.funpic.de/boost/libs/context/doc/html/現在サポートされている triple 上記ドキュメントの Tested Platforms の項を参考にする /trunk/libs/context/src/asm/ にあるファイルから推測する
  17. 17. Boost.Contextmini-review 時点ではコンテキストに関する高級な処理が あったが trunk に入ってから殆どの機能が削られた e.g. context linking / stack unwinding / high-level API1.50.0 のリリースには含まれないことになりそう 現に release branch からは削除されている
  18. 18. ctx::fcontext_t orig, fc;void f(intptr_t){ std::cout << "in context" << std::endl; ctx::jump_fcontext(&fc, &orig, 0);}int main(){ const size_t ctxsize = ctx::default_stacksize(); ctx::stack_allocator alloc; fc.fc_stack.base = alloc.allocate(ctxsize); fc.fc_stack.limit = static_cast<char *>(fc.fc_stack.base) - ctxsize; ctx::make_fcontext(&fc, f); std::cout << "pre jump" << std::endl; ctx::jump_fcontext(&orig, &fc, 0); std::cout << "post jump" << std::endl; alloc.deallocate(fc.fc_stack.base, ctxsize);}
  19. 19. ちょっとした注意TLS は使ってはいけない 多分 SEGV とかそういう話だと思うスタックのデアロケートを自動化しようとコンテキスト 内で開放してはいけない Deallocate が戻ると SEGVコンテキスト内ではスコープを意識して使わないと dtor が呼ばれないコードになってしまうエントリーポイントをそのまま出ると exit が呼ばれる
  20. 20. で、結局何が嬉しいんだろう
  21. 21. ユーザースレッドの目的カーネルスレッドはコンテキストスイッチのコストが非 常に大きいスケジューリングする必要がある場合一連の流れを細切れにしてコールバックとかにするより 処理の流れがわかりやすいIO レイテンシの隠蔽
  22. 22. ユーザースレッドの目的カーネルスレッドはコンテキストスイッチのコストが非 常に大きいスケジューリングする必要がある場合一連の流れを細切れにしてコールバックとかにするより 処理の流れがわかりやすいIO レイテンシの隠蔽 今回はこれを例にとる
  23. 23. で、結局何が嬉しいんだろう→ stateful な操作は state を持ち回る必要がなくなる
  24. 24. 簡単な例一定間隔でタイマイベントが発生する毎回少しづつ変化させたい 例えば 3 回で 1 周後々全く違う処理を同じイベントで行うかもしれないか ら callback のインターフェースは共通化して vector と かに突っ込みたい正直こんな例だとあんまり利点を見いだせないかも ...
  25. 25. 例えばコールバックベースだとfunction<void()> callback_timer; int state = 0;callback_timer = timer_handler; void timer_handler() {while ((event = peek_event()) != FINISH) switch (state){ { switch (event) case 0: { 呼ばれる毎に共有 ... process step 0 ... ... snip ... できる形でどこかに break; state case 1: case TIMER: を保持しないといけな ... process step 1 ... callback_timer(); い break; break; case 2: ... process step 2 ... ... snip ... break; } }} timer_handler を state = (state + 1) % 3; 複数登録できる } ようにするには ...
  26. 26. 例えばコールバックベースだとvector<function<void()>> timer_callbacks; void timer_handler(shared_ptr<int> ps)… snip... {timer_callbacks.push_back( switch (*ps) bind(timer_handler, { make_shared<int>(0)); case 0:… snip... ... process step 0 ...while ((event = peek_event()) != FINISH) break;{ case 1: switch (event) shared_ptr 等で固有 ... process step 1 ... { の break; 状態を持ち回る必要 ... snip ... が case 2: case TIMER: ... process step 2 ... for (auto &c : timer_callbacks) c(); break; break; } ... snip ... *ps = (*ps + 1) % 3; } }}
  27. 27. ユーザースレッドを導入するとfcontext_t fctx;// s tack とか make_f context とか void timer_handler(fcontext_t *ctx)vector<fcontext_t> timer_callbacks; {… snip... while (true)timer_callbacks.push_back(move(fctx)); { ... process step 0 …while ((event = peek_event()) != FINISH) ctx = jump_fcontext(ctx, &fo, 0);{ 固有の状態はコンテキス switch (event) ト ... process step 1 … { 自身が持ってるので ctx = jump_fcontext(ctx, &fo, 0); コンテキストの管理だけ ... snip ... 行えば良い case TIMER: ... process step 2 … for (auto &ctx : timer_callbacks) ctx = jump_fcontext(ctx, &fo, 0); jump_fcontext(&fo, &ctx, &ctx); } break; } ... snip ... シングルスレッドの処 } 理の} 流れと同じように書け る
  28. 28. しかし fcontext_t を直接扱うのはやりづらい ...
  29. 29. 高級な実装正直 Boost.Context は抽象化されてるとはいえ常用するに は低級すぎる現在 Oliver が Boost.Context をベースとした Boost.Coroutine を提案して Formal Review 待ち http://ok73.ok.funpic.de/boost/libs/coroutine/doc/html/index.html GSoC2006 で Eric Niebler が書いた Boost.Coroutine と基本インター フェースは同じ
  30. 30. ctx::fcontext_t orig, fc;void f(intptr_t){ Boost.Context std::cout << "in context (pre jump)" << std::endl; ctx::jump_fcontext(&fc, &orig, 0); std::cout << "in context (post jump)" << std::endl; ctx::jump_fcontext(&fc, &orig, 0);}int main(){ 最後に jump を忘れてはいけないし、 const size_t ctxsize = ctx::default_stacksize(); トップレベルの dtor は呼ばれない ctx::stack_allocator alloc; fc.fc_stack.base = alloc.allocate(ctxsize); fc.fc_stack.limit = static_cast<char *>(fc.fc_stack.base) - ctxsize; ctx::make_fcontext(&fc, f); std::cout << "pre jump" << std::endl; ctx::jump_fcontext(&orig, &fc, 0); std::cout << "now yield" << std::endl; ctx::jump_fcontext(&orig, &fc, 0); std::cout << "post jump" << std::endl; alloc.deallocate(fc.fc_stack.base, ctxsize);}
  31. 31. Boost.Coroutinetypedef coro::coroutine<void()> coro_t;void f(coro_t::self &self){ std::cout << "in coroutine (pre yield)" << std::endl; self.yeild(); std::cout << "in coroutine (post yield)" << std::endl;}int main(){ 最後に yield を呼ぶ必要はないし dtor も呼ばれ coro_t c(f); る std::cout << "pre jump" << std::endl; c(); std::cout << “now yield” << std::endl; c(); std::cout << "post jump" << std::endl;}
  32. 32. Agenda並行と並列、スレッドとかBoost.ContextC++ 標準委員会での動き
  33. 33. C++ 標準委員会での動きStudy Group 1 並行と並列に関する Study Groupn3328 Resumable Functions 言語仕様としてユーザースレッドを導入する提案 resumable と await の 2 つの contextual keywordsn3356 C++ Mutable Threads Mutable Threads の提案n3361 C++ Language Constructs for Parallel Programming Intel® CilkTM Plus の紹介 ( 提案は次の meeting らしい
  34. 34. C++ 標準委員会での動きn3378 A preliminary proposal for work executors Worker を投げると適当にスケジューリングして裏で実行する executer の提案 Worker の戻り値は投げた時に返ってくる future で取得しかしこれらが実際に入るのは早くとも C++2x 頃なのでは
  35. 35. まとめBoost.Context がコンテキストスイッチを抽象化している のでアセンブリとか知らなくても何か遊べそう 実際のプロダクトに使用されると面白そうC++ 標準でも並行・並列の関心は高まっている が、投入はまだ先就職先を考えねばならない
  36. 36. Question?

×