SlideShare una empresa de Scribd logo
1 de 22
Descargar para leer sin conexión
Effective Modern C++Effective Modern C++勉強会勉強会 #8#8
2015/08/19
@simizut22
⾮非同期性が必須なら⾮非同期性が必須なら std::launch::asyncstd::launch::async を指定すを指定す
るる
item36item36
asyncasync のの 22 種類の種類の overloadoverload
default
task のpolicy 指
定
async(F&&, Args&&...);
async(std::launch, F&&, Args&&...);
std::launchstd::launch
enum class lauch : unspecified {
async = unspecified
, deferred = unspecified
implementation-defined
};
scoped enum を⽤用いて規定されている bitmask type
拡張 policy 及びそのbitmask の実装は,実装系に許可
されている
std::launchstd::launch とと std::asyncstd::async
lauch::async
lauch::deferred
異なるスレッドで⾮非同期実⾏行を指定する
呼び出しスレッドと同期実⾏行を指定する
launch::deferred 指定時
get /wait が呼ばれたときに task が実⾏行される
実⾏行されないかもしれない(thread と違って問題ない)
注釈について注釈について
auto f = std::async( std::launch::deferred,
[]{ std::cout << "wait..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0; });
std::shared_future< int > sf = f.share();
auto sf2 = sf;
sf.wait();
std::cout << sf2.get() << std::endl;
sf2 に対して wait/get 呼ぶ前から
sf2 の参照する shared_state は結果を持っている
(shared_state に関しては item38 参照)
defaultdefault とと policypolicy 指定指定
std::async( f );
std::async( std::launch::async | std::launch::deferred,
f);
default の実⾏行は bit を async/deferred 両⽅方⽴立てるの
と同じ意味
つまり,次の2つは全く同じ挙動をする
このときの挙動は実装依存
とある
“ Note: If this policy is specified together with other policies, such as
when using a policy value of launch::async |launch::deferred,
implementations should defer invocation or the selection of the policy
when no more concurrency can be effectively exploited.
実装依存!!
とはいえ [futures.async] の note に
> 実⾏行ポリシーを launch::async |launch::deferred と指定したときに
は, 並列性を効果的に利⽤用できない場合,どちらのポリシーに従うか
を決めるのを遅延するか,task の実⾏行を遅延する(deferred を選択す
る)べき
というところ
並列性が⼗十分に取れるときの動きは書かれていない(未規定??)
http://melpon.org/wandbox/permlink/PiUr8pUjjDmA7C5V
std::cout << "hardware_concurrency = " << std::thread::hardware_concurrency()<<std::endl;
using namespace std::literals;
std::vector< std::future< void > > fvec(100);
std::generate( std::begin(fvec), std::end(fvec),
[]{ return
std::async([]{ std::this_thread::sleep_for(1s);
std::cout << std::this_thread::get_id() <<std::endl;});});
std::for_each( std::begin(fvec),
std::end(fvec),
[](auto&& x){ x.wait();} );
なお,gcc は 6 系で default の挙動が変わる模様??
6 より前と後で,次の code の結果がかなり違う
にあるように,
同期/⾮非同期的に動くかを library の実装が決めてくれる
Bartos Mileski ⽒氏のblog
default policydefault policy の良さの良さ
terminate called after throwing an instance of 'std::system_error'
what(): Resource temporarily unavailable
中⽌止
さらに,resource のこういう error ⾒見なくてよくな
る
defaultdefault ,困ります,困ります(>_<)(>_<)
auto fut = srd::async( f ); // use default policy
s, t, u という名前に次のようにスレッドを束縛する
s f が実⾏行されるスレッド
t async が呼ばれるスレッド
u get/wait を呼ぶスレッド
例えば次みたいな code を考えると...
void f() {
std::cout << "s: " << std::this_thread::get_id() << std::endl; // s
}
std::future< void > g() {
std::cout << "t: " << std::this_thread::get_id() << std::endl; // t
auto fut = std::async( f );
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return fut;
}
int main() {
std::cout << "u:" << std::this_thread::get_id() << std::endl; // u
std::async( g ).get().get();
return 0;
}
http://melpon.org/wandbox/permlink/a7oHldjWHTEGA1Yq
VisualStudio2015 で build した結果
あれ,あれ,ss とと tt が⼀一致しているが⼀一致している!!(!!(環境でまちまち環境でまちまち))
defaultdefault ,困ります,困ります(>_<)(>_<)
s != t かわからない (∵ deferred になるかもしれない
s != u かわからない
そもそもget/wait されないかもしれない
s f が実⾏行されるスレッド
t async が呼ばれるスレッド
u get/wait を呼ぶスレッド
*再掲
defaultdefault ,困ります,困ります(>_<)(>_<)
thread-local storage(TLS) を使ってると問題出る
thread_local int i = 0;
void fun(int left, int right ) {
if (left < right-1) {
auto f1 = std::async( fun, left, (left + right) / 2);
auto f2 = std::async( fun, (left + right)/2, right);
f1.wait();
f2.wait();
}
else {
++i;
}
}
int main() {
fun(0, 10);
std::cout << i << std::endl;
}
どのスレッドで fun が呼ばれるかで結果が変わる
http://melpon.org/wandbox/permlink/lcd7FOlnXfsUBH7T
defaultdefault ,困ります,困ります(>_<)(>_<)
次の code を考える
void f () { std::this_thread::sleep( 1s ); // std::chrono::seconds(1)
auto fut = std::async(f);
while (fut.wait_for(100ms) // std::chrono::milliseconds(1)
!=
std::future_status::ready) {
/* something */
}
wait_for/untilwait_for/until とと future_statusfuture_status
deferred 関数をもつ future_status::deferred
準備完了(値が返せる) future_status::ready
準備中 future_status::timeout
wait_for/until の返値は shared_stateにより以下で決まる
while (fut.wait_for(100ms)
!=
std::future_status::ready) {
}
deferred と schedule されたら,
いくら待っても ready にならない!!!! bug だっ
bug fixbug fix
future が deferred かどうか直接聞く⽅方法はない
wait の返値で future_status::deferred と⾔言うのはある
wait は deferred のとき何もしない
template< typename R >
inline
bool is_defered( std::future< R > const& f) {
return f.wait_for(0s) == std::future_status::deferred;
}
// shared_future も まったく同じなので割愛
auto fut = std::async(f);
if (is_defered(fut)) {
/* hogehoge */
}
else {
while (fut.wait_for(100ms)) {
/* fugafuga */
}
}
ということなので, check を作る
asyncasync でデフォルトが使える条件でデフォルトが使える条件
1. call/wait を呼ぶ thread と並列であってもなくてもよい
2. どの thread の TLS を読み書きするか問わない(またはTLS は使わな
い)
3. get/wait をどの path でも呼んでいる.
または実⾏行されなくても問題ない保証がある
4. wait_for/until を使っているならば deferred も考慮している
であれば async をdefault で実⾏行してもよ
い.
どれか⼀一つでも⽋欠けるなら default ,やめよう
async policyasync policy を使うを使う APIAPI ⽤用意する⽤用意する......
template< typename F, typename ...Args >
inline
std::future< typename std::result_of< F(Args...) >::type >
reallyAsync( F&& f, Args&&... args) {
return std::async(std::launch::async,
std::forward< F >(f),
std::forward< Args >(args)...);
}
c++11 version1
(c++11では)間違ってないけど...
C++14 だと若干型の宣⾔言が修正されている
template< typename F, typename ...Args >
inline
std::future< std::result_of_t< std::decay_t< F >(std::decay_t< Args >...) > >
// ^^^^^^^^^^^^ ^^^^^^^^^^^^ // decay がついてる!
reallyAsync( F&& f, Args&&... args) {
return std::async(std::launch::async,
std::forward< F >(f),
std::forward< Args >(args)...);
}
愚直に書き換え愚直に書き換え
c++14 version1
返値の型書くの,ツライ(-_-;)
修正版修正版(C++14 version)(C++14 version)
template< typename F, typename ...Args >
inline
auto
reallyAsync( F&& f, Args&&... args) {
return std::async(std::launch::async,
std::forward< F >(f),
std::forward< Args >(args)...);
}
すっきり (^^)/
* C++11 で trailing return type 使っても,やっぱりだるい...
things to rememberthings to remember
async の default policy は task の同期/⾮非同期実⾏行のど
ちらにもなり得る
その柔軟性のために
- TLS 使⽤用時に不確かさを起こし得る(毎回違う結果と
か
- task が実⾏行されないかもしれない
- time-out の wait に対して program の変更が必要
などの影響をもたらす
確実に⾮非同期実⾏行にしたければ std::launch::async を(明
⽰示的に)指定する

Más contenido relacionado

La actualidad más candente

条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
Akihiko Matuura
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
Shintaro Fukushima
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
kiki utagawa
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用まで
yoshihikoozaki5
 

La actualidad más candente (20)

Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
 
templateとautoの型推論
templateとautoの型推論templateとautoの型推論
templateとautoの型推論
 
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
 
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
 
Map
MapMap
Map
 
Python 学習教材 (300~309ページ)
Python 学習教材 (300~309ページ)Python 学習教材 (300~309ページ)
Python 学習教材 (300~309ページ)
 
C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
 
Pythonによる非同期プログラミング入門
Pythonによる非同期プログラミング入門Pythonによる非同期プログラミング入門
Pythonによる非同期プログラミング入門
 
ElixirでFPGAを設計する
ElixirでFPGAを設計するElixirでFPGAを設計する
ElixirでFPGAを設計する
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用まで
 

Destacado (9)

topology of musical data
topology of musical datatopology of musical data
topology of musical data
 
Magnitude ~ extend the Euler Characteristics via Möbius Inversion ~
Magnitude ~ extend the Euler Characteristics via  Möbius Inversion ~Magnitude ~ extend the Euler Characteristics via  Möbius Inversion ~
Magnitude ~ extend the Euler Characteristics via Möbius Inversion ~
 
TDA やら Night!!
TDA やら Night!!TDA やら Night!!
TDA やら Night!!
 
introductino to persistent homology and topological data analysis
introductino to persistent homology and topological data analysisintroductino to persistent homology and topological data analysis
introductino to persistent homology and topological data analysis
 
情報幾何学の基礎 第2章 4.5
情報幾何学の基礎 第2章 4.5情報幾何学の基礎 第2章 4.5
情報幾何学の基礎 第2章 4.5
 
Emcjp item33,34
Emcjp item33,34Emcjp item33,34
Emcjp item33,34
 
Effective modern c++ 5
Effective modern c++ 5Effective modern c++ 5
Effective modern c++ 5
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
 
Emcpp item41
Emcpp item41Emcpp item41
Emcpp item41
 

Similar a effective modern c++ chapeter36

Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
 
initとプロセス再起動
initとプロセス再起動initとプロセス再起動
initとプロセス再起動
Takashi Takizawa
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
Kiwamu Okabe
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
digitalghost
 
ZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみるZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみる
Koichi Suzuki
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
Takuya Tsuchida
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 session
freedom404
 
SystemC Tutorial
SystemC TutorialSystemC Tutorial
SystemC Tutorial
kocha2012
 

Similar a effective modern c++ chapeter36 (20)

Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
Kanazawa.js.Next
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
 
initとプロセス再起動
initとプロセス再起動initとプロセス再起動
initとプロセス再起動
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
Swift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswiftSwift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswift
 
Flow.js
Flow.jsFlow.js
Flow.js
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
 
ZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみるZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみる
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
 
Improvement future api
Improvement future apiImprovement future api
Improvement future api
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 session
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
 
Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68
 
Boost tour 1_44_0
Boost tour 1_44_0Boost tour 1_44_0
Boost tour 1_44_0
 
SystemC Tutorial
SystemC TutorialSystemC Tutorial
SystemC Tutorial
 
URLで遊ぼう
URLで遊ぼうURLで遊ぼう
URLで遊ぼう
 

Más de Tatsuki SHIMIZU

Más de Tatsuki SHIMIZU (13)

ロマ数16 simizut
ロマ数16 simizutロマ数16 simizut
ロマ数16 simizut
 
Introduction to Persistence Theory
Introduction to Persistence TheoryIntroduction to Persistence Theory
Introduction to Persistence Theory
 
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
 
Practical topology
Practical topologyPractical topology
Practical topology
 
Euler 標数は測度ですか??
Euler 標数は測度ですか??Euler 標数は測度ですか??
Euler 標数は測度ですか??
 
Operad and Recognition Principle
Operad and Recognition PrincipleOperad and Recognition Principle
Operad and Recognition Principle
 
しかくのお勉強
しかくのお勉強しかくのお勉強
しかくのお勉強
 
Packing
PackingPacking
Packing
 
Introduction to Topological Data Analysis
Introduction to Topological Data AnalysisIntroduction to Topological Data Analysis
Introduction to Topological Data Analysis
 
Jules henri poincaré
Jules henri poincaréJules henri poincaré
Jules henri poincaré
 
情報幾何の基礎輪読会 #1
情報幾何の基礎輪読会 #1情報幾何の基礎輪読会 #1
情報幾何の基礎輪読会 #1
 
代数トポロジー入門
代数トポロジー入門代数トポロジー入門
代数トポロジー入門
 
Effective modern-c++#9
Effective modern-c++#9Effective modern-c++#9
Effective modern-c++#9
 

effective modern c++ chapeter36

  • 1. Effective Modern C++Effective Modern C++勉強会勉強会 #8#8 2015/08/19 @simizut22
  • 3. asyncasync のの 22 種類の種類の overloadoverload default task のpolicy 指 定 async(F&&, Args&&...); async(std::launch, F&&, Args&&...);
  • 4. std::launchstd::launch enum class lauch : unspecified { async = unspecified , deferred = unspecified implementation-defined }; scoped enum を⽤用いて規定されている bitmask type 拡張 policy 及びそのbitmask の実装は,実装系に許可 されている
  • 5. std::launchstd::launch とと std::asyncstd::async lauch::async lauch::deferred 異なるスレッドで⾮非同期実⾏行を指定する 呼び出しスレッドと同期実⾏行を指定する launch::deferred 指定時 get /wait が呼ばれたときに task が実⾏行される 実⾏行されないかもしれない(thread と違って問題ない)
  • 6. 注釈について注釈について auto f = std::async( std::launch::deferred, []{ std::cout << "wait..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); return 0; }); std::shared_future< int > sf = f.share(); auto sf2 = sf; sf.wait(); std::cout << sf2.get() << std::endl; sf2 に対して wait/get 呼ぶ前から sf2 の参照する shared_state は結果を持っている (shared_state に関しては item38 参照)
  • 7. defaultdefault とと policypolicy 指定指定 std::async( f ); std::async( std::launch::async | std::launch::deferred, f); default の実⾏行は bit を async/deferred 両⽅方⽴立てるの と同じ意味 つまり,次の2つは全く同じ挙動をする このときの挙動は実装依存
  • 8. とある “ Note: If this policy is specified together with other policies, such as when using a policy value of launch::async |launch::deferred, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited. 実装依存!! とはいえ [futures.async] の note に > 実⾏行ポリシーを launch::async |launch::deferred と指定したときに は, 並列性を効果的に利⽤用できない場合,どちらのポリシーに従うか を決めるのを遅延するか,task の実⾏行を遅延する(deferred を選択す る)べき というところ 並列性が⼗十分に取れるときの動きは書かれていない(未規定??)
  • 9. http://melpon.org/wandbox/permlink/PiUr8pUjjDmA7C5V std::cout << "hardware_concurrency = " << std::thread::hardware_concurrency()<<std::endl; using namespace std::literals; std::vector< std::future< void > > fvec(100); std::generate( std::begin(fvec), std::end(fvec), []{ return std::async([]{ std::this_thread::sleep_for(1s); std::cout << std::this_thread::get_id() <<std::endl;});}); std::for_each( std::begin(fvec), std::end(fvec), [](auto&& x){ x.wait();} ); なお,gcc は 6 系で default の挙動が変わる模様?? 6 より前と後で,次の code の結果がかなり違う
  • 10. にあるように, 同期/⾮非同期的に動くかを library の実装が決めてくれる Bartos Mileski ⽒氏のblog default policydefault policy の良さの良さ terminate called after throwing an instance of 'std::system_error' what(): Resource temporarily unavailable 中⽌止 さらに,resource のこういう error ⾒見なくてよくな る
  • 11. defaultdefault ,困ります,困ります(>_<)(>_<) auto fut = srd::async( f ); // use default policy s, t, u という名前に次のようにスレッドを束縛する s f が実⾏行されるスレッド t async が呼ばれるスレッド u get/wait を呼ぶスレッド 例えば次みたいな code を考えると...
  • 12. void f() { std::cout << "s: " << std::this_thread::get_id() << std::endl; // s } std::future< void > g() { std::cout << "t: " << std::this_thread::get_id() << std::endl; // t auto fut = std::async( f ); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return fut; } int main() { std::cout << "u:" << std::this_thread::get_id() << std::endl; // u std::async( g ).get().get(); return 0; } http://melpon.org/wandbox/permlink/a7oHldjWHTEGA1Yq VisualStudio2015 で build した結果 あれ,あれ,ss とと tt が⼀一致しているが⼀一致している!!(!!(環境でまちまち環境でまちまち))
  • 13. defaultdefault ,困ります,困ります(>_<)(>_<) s != t かわからない (∵ deferred になるかもしれない s != u かわからない そもそもget/wait されないかもしれない s f が実⾏行されるスレッド t async が呼ばれるスレッド u get/wait を呼ぶスレッド *再掲
  • 14. defaultdefault ,困ります,困ります(>_<)(>_<) thread-local storage(TLS) を使ってると問題出る thread_local int i = 0; void fun(int left, int right ) { if (left < right-1) { auto f1 = std::async( fun, left, (left + right) / 2); auto f2 = std::async( fun, (left + right)/2, right); f1.wait(); f2.wait(); } else { ++i; } } int main() { fun(0, 10); std::cout << i << std::endl; } どのスレッドで fun が呼ばれるかで結果が変わる http://melpon.org/wandbox/permlink/lcd7FOlnXfsUBH7T
  • 15. defaultdefault ,困ります,困ります(>_<)(>_<) 次の code を考える void f () { std::this_thread::sleep( 1s ); // std::chrono::seconds(1) auto fut = std::async(f); while (fut.wait_for(100ms) // std::chrono::milliseconds(1) != std::future_status::ready) { /* something */ }
  • 16. wait_for/untilwait_for/until とと future_statusfuture_status deferred 関数をもつ future_status::deferred 準備完了(値が返せる) future_status::ready 準備中 future_status::timeout wait_for/until の返値は shared_stateにより以下で決まる while (fut.wait_for(100ms) != std::future_status::ready) { } deferred と schedule されたら, いくら待っても ready にならない!!!! bug だっ
  • 17. bug fixbug fix future が deferred かどうか直接聞く⽅方法はない wait の返値で future_status::deferred と⾔言うのはある wait は deferred のとき何もしない template< typename R > inline bool is_defered( std::future< R > const& f) { return f.wait_for(0s) == std::future_status::deferred; } // shared_future も まったく同じなので割愛 auto fut = std::async(f); if (is_defered(fut)) { /* hogehoge */ } else { while (fut.wait_for(100ms)) { /* fugafuga */ } } ということなので, check を作る
  • 18. asyncasync でデフォルトが使える条件でデフォルトが使える条件 1. call/wait を呼ぶ thread と並列であってもなくてもよい 2. どの thread の TLS を読み書きするか問わない(またはTLS は使わな い) 3. get/wait をどの path でも呼んでいる. または実⾏行されなくても問題ない保証がある 4. wait_for/until を使っているならば deferred も考慮している であれば async をdefault で実⾏行してもよ い. どれか⼀一つでも⽋欠けるなら default ,やめよう
  • 19. async policyasync policy を使うを使う APIAPI ⽤用意する⽤用意する...... template< typename F, typename ...Args > inline std::future< typename std::result_of< F(Args...) >::type > reallyAsync( F&& f, Args&&... args) { return std::async(std::launch::async, std::forward< F >(f), std::forward< Args >(args)...); } c++11 version1 (c++11では)間違ってないけど... C++14 だと若干型の宣⾔言が修正されている
  • 20. template< typename F, typename ...Args > inline std::future< std::result_of_t< std::decay_t< F >(std::decay_t< Args >...) > > // ^^^^^^^^^^^^ ^^^^^^^^^^^^ // decay がついてる! reallyAsync( F&& f, Args&&... args) { return std::async(std::launch::async, std::forward< F >(f), std::forward< Args >(args)...); } 愚直に書き換え愚直に書き換え c++14 version1 返値の型書くの,ツライ(-_-;)
  • 21. 修正版修正版(C++14 version)(C++14 version) template< typename F, typename ...Args > inline auto reallyAsync( F&& f, Args&&... args) { return std::async(std::launch::async, std::forward< F >(f), std::forward< Args >(args)...); } すっきり (^^)/ * C++11 で trailing return type 使っても,やっぱりだるい...
  • 22. things to rememberthings to remember async の default policy は task の同期/⾮非同期実⾏行のど ちらにもなり得る その柔軟性のために - TLS 使⽤用時に不確かさを起こし得る(毎回違う結果と か - task が実⾏行されないかもしれない - time-out の wait に対して program の変更が必要 などの影響をもたらす 確実に⾮非同期実⾏行にしたければ std::launch::async を(明 ⽰示的に)指定する