SlideShare ist ein Scribd-Unternehmen logo
1 von 61
Downloaden Sie, um offline zu lesen
Effective Modern C++
勉強会#3
Item 16
刈谷 満(@kariya_mitsuru)
2015/4/22
Item 16: Make const member functions thread safe.
const メンバ関数を
スレッドセーフにしよう
Item 16: Make const member functions thread safe.
例
多項式を表すクラス
⇒Polynomial
その多項式の根を計算するメンバ関数
⇒roots
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType =
std::vector<double>;
RootsType roots() const;
…
};
多項式の根を計算するメンバ関数は、多項式自体を変更しない
↓
const メンバ関数
根を保持するデータ構造
(“using” については Item 9 を参照)
Item 16: Make const member functions thread safe.
多項式の根の計算は高くつく。
⇓
必要なければ計算したくない。
でも 2 回以上は計算したくない。
⇓
最初に使われた時に計算しよう!
計算した根はキャッシュしよう!
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
bool rootsAreValid{ false };
RootsType rootVals{};
};
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
bool rootsAreValid{ false };
RootsType rootVals{};
};
キャッシュが有効じゃなかったら…
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
bool rootsAreValid{ false };
RootsType rootVals{};
};
キャッシュが有効じゃなかったら…
根を計算してそれを rootVals に保存し…
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
bool rootsAreValid{ false };
RootsType rootVals{};
};
キャッシュが有効じゃなかったら…
根を計算してそれを rootVals に保存し…
キャッシュを有効にする!
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
bool rootsAreValid{ false };
RootsType rootVals{};
};
キャッシュが有効じゃなかったら…
根を計算してそれを rootVals に保存し…
キャッシュを有効にする!
あれ?
const メンバ関数じゃなかったっけ?
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
mutable!
roots は概念的にはオブジェクトを変更しない(論理的 const 性)
詳しくはWebで!!
Effective C++ 第3版、Item 3 参照
Item 16: Make const member functions thread safe.
ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと…
Polynomial p;
…
スレッド2
auto valsGivingZero = p.roots();
スレッド1
auto rootsOfP = p.roots();
const メンバ関数だから読むだけだし、
同期しなくても大丈夫っしょ!!
Item 16: Make const member functions thread safe.
ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと…
Polynomial p;
…
スレッド2
auto valsGivingZero = p.roots();
スレッド1
auto rootsOfP = p.roots();
const メンバ関数だから読むだけだし、
同期しなくても大丈夫っしょ!!
死
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
②rootsAreValid を読む
⇓
まだ false!
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
③計算しては書き込む!
(まだ false)
②rootsAreValid を読む
⇓
まだ false!
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
③計算しては書き込む!
(まだ false)
②rootsAreValid を読む
⇓
まだ false!
④計算しては書き込む!
(まだ false)
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
③計算しては書き込む!
(まだ false)
②rootsAreValid を読む
⇓
まだ false!
④計算しては書き込む!
(まだ false)
データレース!
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
if (!rootsAreValid) {
…
rootsAreValid = true;
}
return rootVals;
}
private:
mutable bool rootsAreValid{ false };
mutable RootsType rootVals{};
};
スレッド2スレッド1
①rootsAreValid を読む
⇓
まだ false
③計算しては書き込む!
(まだ false)
②rootsAreValid を読む
⇓
まだ false!
④計算しては書き込む!
(まだ false)
データレース!ようこそUBへ!
Item 16: Make const member functions thread safe.
ここでの問題は…
roots は const メンバ関数なのに、スレッドセーフじゃない。
⇓
const メンバ関数であることは C++11 でも C++98 でも正しい。
(rootsは多項式の値を変更しない)
⇓
直すべきはスレッドセーフ性の欠如
Item 16: Make const member functions thread safe.
解決策
mutex を使え
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
std::lock_guard<std::mutex> g(m);
ここは前と一緒…
return rootVals;
}
private:
mutable std::mutex m;
ここも前と一緒…
};
lock_guard を使って
m をロック!
ブロックの終わりで
m をアンロック!
ここの mutable にも注意!
ロック、アンロックは const メンバ関数じゃない
でも、m が変わっても多項式はやっぱり変わらない!
Item 16: Make const member functions thread safe.
Caution!(Errataあり)
std::mutex はコピーもムーブもできない。
Polynomial に m を追加した結果、
コピーもムーブも出来なくなった。
Item 16: Make const member functions thread safe.
Caution!(Errataあり)
std::mutex はコピーもムーブもできない。
Polynomial に m を追加した結果、
コピーもムーブも出来なくなった。
独自のコピー、ムーブコンストラ
クタ、代入演算子を定義すれば
いいと思うんだけど…
Item 16: Make const member functions thread safe.
コメントあり
もし Polynomial が変更不可だったら、std::call_once と
std::once_flag を使う方がいんじゃね?
⇓
ちょっと書いてみました
Item 16: Make const member functions thread safe.
class Polynomial {
public:
using RootsType = std::vector<double>;
RootsType roots() const {
std::call_once(flag, [this]{ calc(); });
return rootVals;
}
void calc() const {
…
}
private:
mutable std::once_flag flag{};
mutable RootsType rootVals{};
};
call_once を使って
calc を一回だけ呼ぶ
(λ をつかってる理由は
Item 34 参照)
実際に計算、格納するメンバ関数
もちろん const メンバ関数
もちろん once_flag も mutable!
Item 16: Make const member functions thread safe.
場合によっては mutex は重過ぎ
例)メンバ関数が呼ばれた回数を数えたい
⇓
std::atomic で十分
(実際に std::atomic の方が mutex より軽いかどうかは、
動作するハードウェアと標準ライブラリの実装によるので注意!)
Item 16: Make const member functions thread safe.
class Point {
public:
…
double distanceFromOrigin() const noexcept
{
++callCount;
return std::hypot(x, y);
}
private:
mutable std::atomic<unsigned> callCount{ 0 };
double x, y;
};
アトミック(不可分)なインクリメント
(Item 40 参照)
Item 16: Make const member functions thread safe.
class Point {
public:
…
double distanceFromOrigin() const noexcept
{
++callCount;
return std::hypot(x, y);
}
private:
mutable std::atomic<unsigned> callCount{ 0 };
double x, y;
};
例によって、std::atomic<T> も
コピーはおろかムーブも
出来ないので注意!
(本書Errata)
Item 16: Make const member functions thread safe.
class Point { // 二次元の点
public:
…
double distanceFromOrigin() const noexcept // noexcept については
{
++callCount;
return std::hypot(x, y);
}
private:
mutable std::atomic<unsigned> callCount{ 0 };
double x, y;
};
あ、あと、std::hypotも
わりとデキる奴なので
忘れないであげてください!(><)
(本書Errata)
hypotenuse squared
Item 16: Make const member functions thread safe.
でも…
mutex より std::atomic の方が軽いからと言って、
使いすぎは禁物!
例)重い計算結果のキャッシュ(int)と
キャッシュの有効フラグ(bool)
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
キャッシュする値と
その有効フラグを
atomic にしました!
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
キャッシュする値と
その有効フラグを
atomic にしました!
ホントに
大丈夫…?
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
②計算して格納
(まだ無効)
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
②計算して格納
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
②計算して格納
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
④計算して格納
(まだ無効)
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
private:
mutable std::atomic<bool> cacheValid{ false };
mutable std::atomic<int> cachedValue;
};
スレッド2スレッド1
②計算して格納
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
④計算して格納
(まだ無効)残念!!!
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
じゃあじゃあ、
キャッシュの有効化と
値の代入を逆にしよう!
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
じゃあじゃあ、
キャッシュの有効化と
値の代入を逆にしよう!
ホントにホントに
大丈夫…?
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
④2つとも計算する
(まだ無効)
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効か確認する
⇓
まだ無効
①有効か確認する
⇓
まだ無効
④2つとも計算する
(まだ無効)
残念!!!
(本書Errata)
Item 16: Make const member functions thread safe.
でも…
実はもっとヤバい…
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効にする!
(まだ格納前!)
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効にする!
(まだ格納前!)
④有効か確認する
⇓
有効!?
値を返す!!!
①有効か確認する
⇓
まだ無効
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cacheValid = true;
return cachedValue = val1 + val2;
}
}
…
};
スレッド2スレッド1
②2つとも計算する
(まだ無効)
③有効にする!
(まだ格納前!)
④有効か確認する
⇓
有効!?
値を返す!!!
①有効か確認する
⇓
まだ無効
死
Item 16: Make const member functions thread safe.
教訓
単一の変数やメモリ位置の同期が必要
⇒ std::atomic
2 つ以上の変数やメモリ位置に対して不可分操作が必要
⇒ mutex(std::atomic じゃNG!)
Item 16: Make const member functions thread safe.
class Widget {
public:
…
int magicValue() const {
std::lock_guard<std::mutex> guard(m);
if (cacheValid) return cachedValue;
else {
auto val1 = expensiveComputation1();
auto val2 = expensiveComputation2();
cachedValue = val1 + val2;
cacheValid = true;
return cachedValue;
}
}
…
private:
mutable std::mutex m;
mutable int cachedValue;
mutable bool cacheValid{ false };
};
lock_guard を使って
m をロック!
ブロックの終わりで
m をアンロック!
例によって mutable!
もはや atomic の必要なし!
Item 16: Make const member functions thread safe.
ところで…
散々マルチスレッドの話をしてきたけど、
シングルスレッド前提の場合は?
⇓
これらの対応は不要
(その場合、mutex や std::atomic に
関するコストを避けられる)
Item 16: Make const member functions thread safe.
ところで…
散々マルチスレッドの話をしてきたけど、
シングルスレッド前提の場合は?
⇓
これらの対応は不要
(その場合、mutex や std::atomic に
関するコストを避けられる)
Item 16: Make const member functions thread safe.
え
ー
マ
ジ
マ
ル
チ
ス
レ
ッ
ド
未
対
応
⁉
マ
ル
チ
ス
レ
ッ
ド
未
対
応
が
許
さ
れ
る
の
は
小
学
生
ま
で
だ
よ
ね
ー
©キモイガールズ
Item 16: Make const member functions thread safe.
覚えておくこと
• 並行コンテキストで決して使用しないと確信できない限り、
const メンバ関数をスレッドセーフにしておくこと。
• std::atomic の使用は mutex よりも良いパフォーマンスを示す
かもしれないが、それは単一の変数やメモリ位置への操作のみに適
している。

Weitere ähnliche Inhalte

Was ist angesagt?

Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Mitsuru Kariya
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールMITSUNARI Shigeo
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Preferred Networks
 
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門Fixstars Corporation
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Hiro H.
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexprGenya Murakami
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 
[DL輪読会]Deep Face Recognition: A Survey
[DL輪読会]Deep Face Recognition: A Survey[DL輪読会]Deep Face Recognition: A Survey
[DL輪読会]Deep Face Recognition: A SurveyDeep Learning JP
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみたSatoshi Sato
 

Was ist angesagt? (20)

Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
 
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
TVM の紹介
TVM の紹介TVM の紹介
TVM の紹介
 
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
[DL輪読会]Deep Face Recognition: A Survey
[DL輪読会]Deep Face Recognition: A Survey[DL輪読会]Deep Face Recognition: A Survey
[DL輪読会]Deep Face Recognition: A Survey
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみた
 

Andere mochten auch

effective modern c++ chapeter36
effective modern c++ chapeter36effective modern c++ chapeter36
effective modern c++ chapeter36Tatsuki SHIMIZU
 
Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Keisuke Fukuda
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Takatoshi Kondo
 
Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Akihiro Nishimura
 
Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Keisuke Fukuda
 
Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Takashi Hoshino
 
Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Takashi Hoshino
 
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...mooopan
 
Effective modern c++ 8
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8uchan_nos
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Keisuke Fukuda
 

Andere mochten auch (17)

Effective modern-c++#9
Effective modern-c++#9Effective modern-c++#9
Effective modern-c++#9
 
effective modern c++ chapeter36
effective modern c++ chapeter36effective modern c++ chapeter36
effective modern c++ chapeter36
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
 
Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
 
Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)
 
Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25
 
Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38
 
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
 
Effective modern c++ 8
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8
 
Emcjp item33,34
Emcjp item33,34Emcjp item33,34
Emcjp item33,34
 
emcjp Item 42
emcjp Item 42emcjp Item 42
emcjp Item 42
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
Emcpp item41
Emcpp item41Emcpp item41
Emcpp item41
 
Emcpp0506
Emcpp0506Emcpp0506
Emcpp0506
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
 

Ähnlich wie Effective Modern C++ 勉強会#3 Item16

Hello Dark-Side C# (Part. 1)
Hello Dark-Side C# (Part. 1)Hello Dark-Side C# (Part. 1)
Hello Dark-Side C# (Part. 1)Yuto Takei
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8y_taka_23
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライドkoturn 0;
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義JPCERT Coordination Center
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~CHY72
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„和弘 井之上
 
本当にあった怖い話し Db編
本当にあった怖い話し Db編本当にあった怖い話し Db編
本当にあった怖い話し Db編Oda Shinsuke
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
xv6から始めるSPIN入門
xv6から始めるSPIN入門xv6から始めるSPIN入門
xv6から始めるSPIN入門Ryousei Takano
 
Build Node.js-WASM/WASI Tiny compiler with Node.js
Build Node.js-WASM/WASI Tiny compiler with Node.jsBuild Node.js-WASM/WASI Tiny compiler with Node.js
Build Node.js-WASM/WASI Tiny compiler with Node.jsmganeko
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61TATSUYA HAYAMIZU
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 

Ähnlich wie Effective Modern C++ 勉強会#3 Item16 (20)

Hello Dark-Side C# (Part. 1)
Hello Dark-Side C# (Part. 1)Hello Dark-Side C# (Part. 1)
Hello Dark-Side C# (Part. 1)
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライド
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
 
Stream2の基本
Stream2の基本Stream2の基本
Stream2の基本
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
 
本当にあった怖い話し Db編
本当にあった怖い話し Db編本当にあった怖い話し Db編
本当にあった怖い話し Db編
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
xv6から始めるSPIN入門
xv6から始めるSPIN入門xv6から始めるSPIN入門
xv6から始めるSPIN入門
 
Move semantics
Move semanticsMove semantics
Move semantics
 
Build Node.js-WASM/WASI Tiny compiler with Node.js
Build Node.js-WASM/WASI Tiny compiler with Node.jsBuild Node.js-WASM/WASI Tiny compiler with Node.js
Build Node.js-WASM/WASI Tiny compiler with Node.js
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
Altanative macro
Altanative macroAltanative macro
Altanative macro
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 

Kürzlich hochgeladen

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsWSO2
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...Toru Tamaki
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video UnderstandingToru Tamaki
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Gamesatsushi061452
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptxsn679259
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 

Kürzlich hochgeladen (10)

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

Effective Modern C++ 勉強会#3 Item16

  • 1. Effective Modern C++ 勉強会#3 Item 16 刈谷 満(@kariya_mitsuru) 2015/4/22
  • 2. Item 16: Make const member functions thread safe. const メンバ関数を スレッドセーフにしよう
  • 3. Item 16: Make const member functions thread safe. 例 多項式を表すクラス ⇒Polynomial その多項式の根を計算するメンバ関数 ⇒roots
  • 4. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const; … }; 多項式の根を計算するメンバ関数は、多項式自体を変更しない ↓ const メンバ関数 根を保持するデータ構造 (“using” については Item 9 を参照)
  • 5. Item 16: Make const member functions thread safe. 多項式の根の計算は高くつく。 ⇓ 必要なければ計算したくない。 でも 2 回以上は計算したくない。 ⇓ 最初に使われた時に計算しよう! 計算した根はキャッシュしよう!
  • 6. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; };
  • 7. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら…
  • 8. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し…
  • 9. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し… キャッシュを有効にする!
  • 10. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し… キャッシュを有効にする! あれ? const メンバ関数じゃなかったっけ?
  • 11. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; mutable! roots は概念的にはオブジェクトを変更しない(論理的 const 性) 詳しくはWebで!! Effective C++ 第3版、Item 3 参照
  • 12. Item 16: Make const member functions thread safe. ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと… Polynomial p; … スレッド2 auto valsGivingZero = p.roots(); スレッド1 auto rootsOfP = p.roots(); const メンバ関数だから読むだけだし、 同期しなくても大丈夫っしょ!!
  • 13. Item 16: Make const member functions thread safe. ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと… Polynomial p; … スレッド2 auto valsGivingZero = p.roots(); スレッド1 auto rootsOfP = p.roots(); const メンバ関数だから読むだけだし、 同期しなくても大丈夫っしょ!! 死
  • 14. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1
  • 15. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false
  • 16. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ②rootsAreValid を読む ⇓ まだ false!
  • 17. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false!
  • 18. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false)
  • 19. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false) データレース!
  • 20. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false) データレース!ようこそUBへ!
  • 21. Item 16: Make const member functions thread safe. ここでの問題は… roots は const メンバ関数なのに、スレッドセーフじゃない。 ⇓ const メンバ関数であることは C++11 でも C++98 でも正しい。 (rootsは多項式の値を変更しない) ⇓ 直すべきはスレッドセーフ性の欠如
  • 22. Item 16: Make const member functions thread safe. 解決策 mutex を使え
  • 23. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { std::lock_guard<std::mutex> g(m); ここは前と一緒… return rootVals; } private: mutable std::mutex m; ここも前と一緒… }; lock_guard を使って m をロック! ブロックの終わりで m をアンロック! ここの mutable にも注意! ロック、アンロックは const メンバ関数じゃない でも、m が変わっても多項式はやっぱり変わらない!
  • 24. Item 16: Make const member functions thread safe. Caution!(Errataあり) std::mutex はコピーもムーブもできない。 Polynomial に m を追加した結果、 コピーもムーブも出来なくなった。
  • 25. Item 16: Make const member functions thread safe. Caution!(Errataあり) std::mutex はコピーもムーブもできない。 Polynomial に m を追加した結果、 コピーもムーブも出来なくなった。 独自のコピー、ムーブコンストラ クタ、代入演算子を定義すれば いいと思うんだけど…
  • 26. Item 16: Make const member functions thread safe. コメントあり もし Polynomial が変更不可だったら、std::call_once と std::once_flag を使う方がいんじゃね? ⇓ ちょっと書いてみました
  • 27. Item 16: Make const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { std::call_once(flag, [this]{ calc(); }); return rootVals; } void calc() const { … } private: mutable std::once_flag flag{}; mutable RootsType rootVals{}; }; call_once を使って calc を一回だけ呼ぶ (λ をつかってる理由は Item 34 参照) 実際に計算、格納するメンバ関数 もちろん const メンバ関数 もちろん once_flag も mutable!
  • 28. Item 16: Make const member functions thread safe. 場合によっては mutex は重過ぎ 例)メンバ関数が呼ばれた回数を数えたい ⇓ std::atomic で十分 (実際に std::atomic の方が mutex より軽いかどうかは、 動作するハードウェアと標準ライブラリの実装によるので注意!)
  • 29. Item 16: Make const member functions thread safe. class Point { public: … double distanceFromOrigin() const noexcept { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; アトミック(不可分)なインクリメント (Item 40 参照)
  • 30. Item 16: Make const member functions thread safe. class Point { public: … double distanceFromOrigin() const noexcept { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; 例によって、std::atomic<T> も コピーはおろかムーブも 出来ないので注意! (本書Errata)
  • 31. Item 16: Make const member functions thread safe. class Point { // 二次元の点 public: … double distanceFromOrigin() const noexcept // noexcept については { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; あ、あと、std::hypotも わりとデキる奴なので 忘れないであげてください!(><) (本書Errata) hypotenuse squared
  • 32. Item 16: Make const member functions thread safe. でも… mutex より std::atomic の方が軽いからと言って、 使いすぎは禁物! 例)重い計算結果のキャッシュ(int)と キャッシュの有効フラグ(bool)
  • 33. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; キャッシュする値と その有効フラグを atomic にしました!
  • 34. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; キャッシュする値と その有効フラグを atomic にしました! ホントに 大丈夫…?
  • 35. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1
  • 36. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
  • 37. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ①有効か確認する ⇓ まだ無効
  • 38. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効
  • 39. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④計算して格納 (まだ無効)
  • 40. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④計算して格納 (まだ無効)残念!!!
  • 41. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; じゃあじゃあ、 キャッシュの有効化と 値の代入を逆にしよう!
  • 42. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; じゃあじゃあ、 キャッシュの有効化と 値の代入を逆にしよう! ホントにホントに 大丈夫…?
  • 43. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1
  • 44. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
  • 45. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ①有効か確認する ⇓ まだ無効
  • 46. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効
  • 47. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④2つとも計算する (まだ無効)
  • 48. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④2つとも計算する (まだ無効) 残念!!! (本書Errata)
  • 49. Item 16: Make const member functions thread safe. でも… 実はもっとヤバい…
  • 50. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1
  • 51. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
  • 52. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ①有効か確認する ⇓ まだ無効
  • 53. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ①有効か確認する ⇓ まだ無効
  • 54. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ④有効か確認する ⇓ 有効!? 値を返す!!! ①有効か確認する ⇓ まだ無効
  • 55. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ④有効か確認する ⇓ 有効!? 値を返す!!! ①有効か確認する ⇓ まだ無効 死
  • 56. Item 16: Make const member functions thread safe. 教訓 単一の変数やメモリ位置の同期が必要 ⇒ std::atomic 2 つ以上の変数やメモリ位置に対して不可分操作が必要 ⇒ mutex(std::atomic じゃNG!)
  • 57. Item 16: Make const member functions thread safe. class Widget { public: … int magicValue() const { std::lock_guard<std::mutex> guard(m); if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } … private: mutable std::mutex m; mutable int cachedValue; mutable bool cacheValid{ false }; }; lock_guard を使って m をロック! ブロックの終わりで m をアンロック! 例によって mutable! もはや atomic の必要なし!
  • 58. Item 16: Make const member functions thread safe. ところで… 散々マルチスレッドの話をしてきたけど、 シングルスレッド前提の場合は? ⇓ これらの対応は不要 (その場合、mutex や std::atomic に 関するコストを避けられる)
  • 59. Item 16: Make const member functions thread safe. ところで… 散々マルチスレッドの話をしてきたけど、 シングルスレッド前提の場合は? ⇓ これらの対応は不要 (その場合、mutex や std::atomic に 関するコストを避けられる)
  • 60. Item 16: Make const member functions thread safe. え ー マ ジ マ ル チ ス レ ッ ド 未 対 応 ⁉ マ ル チ ス レ ッ ド 未 対 応 が 許 さ れ る の は 小 学 生 ま で だ よ ね ー ©キモイガールズ
  • 61. Item 16: Make const member functions thread safe. 覚えておくこと • 並行コンテキストで決して使用しないと確信できない限り、 const メンバ関数をスレッドセーフにしておくこと。 • std::atomic の使用は mutex よりも良いパフォーマンスを示す かもしれないが、それは単一の変数やメモリ位置への操作のみに適 している。