effective modern c++ chapeter36

T
Tatsuki SHIMIZUc++er en mathematical systems inc.
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 を(明
⽰示的に)指定する
1 de 22

Recomendados

Effective Modern C++ 勉強会#7 Item 27 por
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Mitsuru Kariya
2K vistas71 diapositivas
Effective modern c++ 5 por
Effective modern c++ 5Effective modern c++ 5
Effective modern c++ 5uchan_nos
11.4K vistas20 diapositivas
Emcjp item21 por
Emcjp item21Emcjp item21
Emcjp item21MITSUNARI Shigeo
2.3K vistas12 diapositivas
unique_ptrにポインタ以外のものを持たせるとき por
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときShintarou Okada
6.9K vistas28 diapositivas
Effective Modern C++ 勉強会#1 Item3,4 por
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Takashi Hoshino
2.7K vistas24 diapositivas
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」 por
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Hiro H.
8.9K vistas71 diapositivas

Más contenido relacionado

La actualidad más candente

Constexpr 中3女子テクニック por
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニックGenya Murakami
33K vistas138 diapositivas
Effective Modern C++ 勉強会#3 Item16 por
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16Mitsuru Kariya
1.1K vistas61 diapositivas
プログラムの処方箋~健康なコードと病んだコード por
プログラムの処方箋~健康なコードと病んだコードプログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコードShigenori Sagawa
8.9K vistas59 diapositivas
templateとautoの型推論 por
templateとautoの型推論templateとautoの型推論
templateとautoの型推論MITSUNARI Shigeo
15.2K vistas22 diapositivas
llvm入門 por
llvm入門llvm入門
llvm入門MITSUNARI Shigeo
16.6K vistas19 diapositivas
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ por
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロdigitalghost
7.5K vistas21 diapositivas

La actualidad más candente(20)

Constexpr 中3女子テクニック por Genya Murakami
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami33K vistas
Effective Modern C++ 勉強会#3 Item16 por Mitsuru Kariya
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
Mitsuru Kariya1.1K vistas
プログラムの処方箋~健康なコードと病んだコード por Shigenori Sagawa
プログラムの処方箋~健康なコードと病んだコードプログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコード
Shigenori Sagawa8.9K vistas
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ por digitalghost
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
digitalghost7.5K vistas
Effective Modern C++ Item 9 and 10 por uchan_nos
Effective Modern C++ Item 9 and 10Effective Modern C++ Item 9 and 10
Effective Modern C++ Item 9 and 10
uchan_nos2.4K vistas
LLVM Backend の紹介 por Akira Maruoka
LLVM Backend の紹介LLVM Backend の紹介
LLVM Backend の紹介
Akira Maruoka5.3K vistas
組み込みでこそC++を使う10の理由 por kikairoya
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya27K vistas
Effective Modern C++勉強会#4 Item 17, 18資料 por Ryo Igarashi
Effective Modern C++勉強会#4 Item 17, 18資料Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
Ryo Igarashi11.6K vistas
Effective Modern C++ 勉強会 Item26 por Akihiro Nishimura
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
Akihiro Nishimura1.2K vistas
関数型プログラミング入門 with OCaml por Haruka Oikawa
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml
Haruka Oikawa12.4K vistas
Boost.Preprocessorでプログラミングしましょう por digitalghost
Boost.PreprocessorでプログラミングしましょうBoost.Preprocessorでプログラミングしましょう
Boost.Preprocessorでプログラミングしましょう
digitalghost5.3K vistas
Deep C por Olve Maudal
Deep CDeep C
Deep C
Olve Maudal871.6K vistas
C++ マルチスレッドプログラミング por Kohsuke Yuasa
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
Kohsuke Yuasa107.7K vistas
すごい constexpr たのしくレイトレ! por Genya Murakami
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
Genya Murakami25.6K vistas
中3女子が狂える本当に気持ちのいい constexpr por Genya Murakami
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami30.5K vistas
Visual C++で使えるC++11 por nekko1119
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
nekko111936.8K vistas
不遇の標準ライブラリ - valarray por Ryosuke839
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray
Ryosuke8397.4K vistas

Destacado

topology of musical data por
topology of musical datatopology of musical data
topology of musical dataTatsuki SHIMIZU
2.7K vistas55 diapositivas
Magnitude ~ extend the Euler Characteristics via Möbius Inversion ~ por
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 ~Tatsuki SHIMIZU
1.9K vistas45 diapositivas
TDA やら Night!! por
TDA やら Night!!TDA やら Night!!
TDA やら Night!!Tatsuki SHIMIZU
569 vistas31 diapositivas
introductino to persistent homology and topological data analysis por
introductino to persistent homology and topological data analysisintroductino to persistent homology and topological data analysis
introductino to persistent homology and topological data analysisTatsuki SHIMIZU
961 vistas70 diapositivas
情報幾何学の基礎 第2章 4.5 por
情報幾何学の基礎 第2章 4.5情報幾何学の基礎 第2章 4.5
情報幾何学の基礎 第2章 4.5Tatsuki SHIMIZU
1.8K vistas20 diapositivas
Emcjp item33,34 por
Emcjp item33,34Emcjp item33,34
Emcjp item33,34MITSUNARI Shigeo
1.6K vistas9 diapositivas

Destacado(10)

Magnitude ~ extend the Euler Characteristics via Möbius Inversion ~ por Tatsuki SHIMIZU
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 ~
Tatsuki SHIMIZU1.9K vistas
introductino to persistent homology and topological data analysis por Tatsuki SHIMIZU
introductino to persistent homology and topological data analysisintroductino to persistent homology and topological data analysis
introductino to persistent homology and topological data analysis
Tatsuki SHIMIZU961 vistas
情報幾何学の基礎 第2章 4.5 por Tatsuki SHIMIZU
情報幾何学の基礎 第2章 4.5情報幾何学の基礎 第2章 4.5
情報幾何学の基礎 第2章 4.5
Tatsuki SHIMIZU1.8K vistas
Effective modern c++ 8 por uchan_nos
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8
uchan_nos1.3K vistas
Effective Modern C++ 読書会 Item 35 por Keisuke Fukuda
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda11.1K vistas

Similar a effective modern c++ chapeter36

Continuation with Boost.Context por
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
2.1K vistas24 diapositivas
Pfi Seminar 2010 1 7 por
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Preferred Networks
3.4K vistas60 diapositivas
今日からできる!簡単 .NET 高速化 Tips por
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
35.1K vistas53 diapositivas
Kanazawa.js.Next por
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Nextdynamis
1.6K vistas84 diapositivas
initとプロセス再起動 por
initとプロセス再起動initとプロセス再起動
initとプロセス再起動Takashi Takizawa
49.2K vistas29 diapositivas
emc++ chapter32 por
emc++ chapter32emc++ chapter32
emc++ chapter32Tatsuki SHIMIZU
1.1K vistas16 diapositivas

Similar a effective modern c++ chapeter36(20)

Continuation with Boost.Context por Akira Takahashi
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi2.1K vistas
今日からできる!簡単 .NET 高速化 Tips por Takaaki Suzuki
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
Takaaki Suzuki35.1K vistas
Kanazawa.js.Next por dynamis
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
dynamis 1.6K vistas
Dive into RTS - another side por Kiwamu Okabe
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
Kiwamu Okabe1.4K vistas
C++コンパイラ GCCとClangからのメッセージをお読みください por digitalghost
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
digitalghost4.7K vistas
Swift 2.0 で変わったところ「前編」 #cswift por Tomohiro Kumagai
Swift 2.0 で変わったところ「前編」 #cswiftSwift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswift
Tomohiro Kumagai28.6K vistas
Flow.js por uupaa
Flow.jsFlow.js
Flow.js
uupaa7.8K vistas
Pub/Sub model, msm, and asio por Takatoshi Kondo
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
Takatoshi Kondo1.6K vistas
ZFSのソースコードをチラ見してみる por Koichi Suzuki
ZFSのソースコードをチラ見してみるZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみる
Koichi Suzuki1.2K vistas
あんなテスト、こんなテスト(this and that about testing) por Takuya Tsuchida
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
Takuya Tsuchida2.4K vistas
Boost9 session por freedom404
Boost9 sessionBoost9 session
Boost9 session
freedom4041.8K vistas
Flutterを体験してみませんか por cch-robo
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
cch-robo255 vistas
SystemC Tutorial por kocha2012
SystemC TutorialSystemC Tutorial
SystemC Tutorial
kocha20129.1K vistas

Más de Tatsuki SHIMIZU

ロマ数16 simizut por
ロマ数16 simizutロマ数16 simizut
ロマ数16 simizutTatsuki SHIMIZU
195 vistas25 diapositivas
Introduction to Persistence Theory por
Introduction to Persistence TheoryIntroduction to Persistence Theory
Introduction to Persistence TheoryTatsuki SHIMIZU
767 vistas28 diapositivas
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~ por
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~Tatsuki SHIMIZU
1.7K vistas55 diapositivas
Practical topology por
Practical topologyPractical topology
Practical topologyTatsuki SHIMIZU
1.4K vistas27 diapositivas
Euler 標数は測度ですか?? por
Euler 標数は測度ですか??Euler 標数は測度ですか??
Euler 標数は測度ですか??Tatsuki SHIMIZU
2.5K vistas30 diapositivas
Operad and Recognition Principle por
Operad and Recognition PrincipleOperad and Recognition Principle
Operad and Recognition PrincipleTatsuki SHIMIZU
1.3K vistas18 diapositivas

Más de Tatsuki SHIMIZU(13)

Introduction to Persistence Theory por Tatsuki SHIMIZU
Introduction to Persistence TheoryIntroduction to Persistence Theory
Introduction to Persistence Theory
Tatsuki SHIMIZU767 vistas
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~ por Tatsuki SHIMIZU
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
エキゾチック球面ナイト(浮気編)~28 日周期の彼女たち~
Tatsuki SHIMIZU1.7K vistas
Euler 標数は測度ですか?? por Tatsuki SHIMIZU
Euler 標数は測度ですか??Euler 標数は測度ですか??
Euler 標数は測度ですか??
Tatsuki SHIMIZU2.5K vistas
Operad and Recognition Principle por Tatsuki SHIMIZU
Operad and Recognition PrincipleOperad and Recognition Principle
Operad and Recognition Principle
Tatsuki SHIMIZU1.3K vistas
Introduction to Topological Data Analysis por Tatsuki SHIMIZU
Introduction to Topological Data AnalysisIntroduction to Topological Data Analysis
Introduction to Topological Data Analysis
Tatsuki SHIMIZU2.8K vistas

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 を(明 ⽰示的に)指定する