【フォルスシェアリング】

フォルスシェアリング とは?

最終更新:
💡 別々の席に座ったつもりが、実は同じ長椅子で押し合いへし合い

別々のコアで使う、論理的には無関係な変数が同じキャッシュラインに載り、少なくとも一方の書き込みによってキャッシュの整合性を保つ通信が増え、性能が落ちる現象。

📌 このページのポイント
別の変数が、同じラインに同居する コアA コアB ラインのコピー 変数 a を更新 ラインのコピー 変数 b を利用 a b 別の変数でも、同じキャッシュライン 整合性の管理 少なくとも一方が書き込む場合 配置を離す/共有する書き込みを減らす 効果とメモリの負担を測定する
共有メモリのライン内に別変数aとbがあり、コアAがaを書き込む例。コアBのコピーにも整合性の管理が及ぶ。具体的なプロトコルや通信順序を示す図ではない。
ひよこ ひよこ
フォルスシェアリングって何? 「偽の共有」って言われてもピンとこないよ。
ペンギン先生 ペンギン先生
別々のコアで動くスレッドAとBが、それぞれ別の変数を更新する例を考えよう。変数は別でも同じキャッシュラインに載ると、整合性を保つやり取りが増えて性能が落ちることがあるんだ。
ひよこ ひよこ
キャッシュラインって何?
ペンギン先生 ペンギン先生
キャッシュでデータを管理する塊だよ。64バイトなどの大きさがあり、具体的なサイズは機器による。変数1個だけではなく周囲のデータも同じラインに入るので、別の変数が同居することがあるんだ。
ひよこ ひよこ
どうして塊が同じだと遅くなるの?
ペンギン先生 ペンギン先生
各コアで同じラインのコピーを使うとき、一方の書き込みにより、他方のコピーの無効化や再取得などが必要になるよ。自分が使う変数自体は変わっていなくても、ライン単位の整合性の管理に巻き込まれる。そのやり取りが繰り返されると負担になるんだ。
ひよこ ひよこ
どうやって見つけて、どう直すの?
ペンギン先生 ペンギン先生
スレッドを増やしても速くならない原因はいろいろあるので、測定して確かめるよ。Linuxでは、対応する環境でperf c2cなどを使い、競合するラインを調べられる。変数を別のラインに離す配置やパディングが対策の一つだよ。C++にはalignasとstd::hardware_destructive_interference_sizeを使う例もあるんだ。
ひよこ ひよこ
全部の変数を離せばいいの?
ペンギン先生 ペンギン先生
離すほどメモリなどの負担が増えるため、問題のある箇所に使い、変更後も測定するよ。C++の定数は実装が定める推奨の間隔で、実行機器のライン幅を取得する関数ではない。各スレッドで集計して最後に合算するなど、共有する書き込みを減らす方法もあるね。
もっと詳しく知りたい人へ

両方のスレッドが書き込む場合だけ起きますか?

片方が読み取り、もう片方が同じキャッシュライン内の別の変数を書き換える場合にも起きます。両方とも読み取りだけなら、その読み取り同士では書き込みによる無効化は生じません。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「フォルスシェアリング」って出てきたら「別々の変数が同じキャッシュラインに載り、コア間のやり取りで遅くなること」と思えばだいたいOK!
📖 おまけ:英語の意味
「False Sharing」 = 偽の共有
💬 本当はデータを共有していないのに、同じキャッシュラインに載ったせいで共有しているかのように競合するから、この名前だよ

参考資料

← 用語集にもどる