質問
私は小さいがよく使われる関数オブジェクトを持っています。各スレッドは独自のコピーを取得します。すべてが静的に割り当てられています。コピーは、グローバルデータまたは静的データを共有しません。このオブジェクトを誤った共有から保護する必要がありますか?
ありがとうございます。 編集:ここでboost.threadsを使用するおもちゃプログラムです。フィールドデータ?
のために誤った共有が発生する可能性があります。#include <boost/thread/thread.hpp>
struct Work {
void operator()() {
++data;
}
int data;
};
int main() {
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(Work());
threads.join_all();
}
. 解決
スレッド間の誤った共有は、2つ以上のスレッドが同じキャッシュラインを使用する場合です。
e.g。 :
struct Work {
Work( int& d) : data( d ) {}
void operator()() {
++data;
}
int& data;
};
int main() {
int false_sharing[10] = { 0 };
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(Work(false_sharing[i]));
threads.join_all();
int no_false_sharing[10 * CACHELINE_SIZE_INTS] = { 0 };
for (int i = 0; i < 10; ++i)
threads.create_thread(Work(no_false_sharing[i * CACHELINE_SIZE_INTS]));
threads.join_all();
}
.
最初のブロックのスレッドは誤った共有に苦しんでいます。 2番目のブロックのスレッドは(CACHELINE_SIZE
のおかげで)
スタック上のデータは常に他のスレッドから離れています。 (例えば、Windowsの下、少なくとも数ページ)。
関数オブジェクトの定義を使用して、HEAP上にWork
のインスタンスが作成され、このヒープスペースがスレッド内で使用されているため、falseの共有が表示されることがあります。
これは、隣接するいくつかのWork
インスタンスにつながる可能性があり、キャッシュラインの共有を招く可能性があります。
しかし...あなたのサンプルは意味がないので、データは外で触れられないため、虚偽の共有が不必要に誘発されるためです。
最も簡単な方法で、このような問題を防ぐために、スタックをローカルにコピーしてから、スタックコピーを作業することです。作業が完了したら、出力varに戻ります。
e.g:
struct Work {
Work( int& d) : data( d ) {}
void operator()()
{
int tmp = data;
for( int i = 0; i < lengthy_op; ++i )
++tmp;
data = tmp;
}
int& data;
};
.
これは共有に関するすべての問題を防ぎます。
他のヒント
私は公正な研究をしました、そしてそれは誤った共有に対する銀の弾丸の解決策がないようです。これが私が思い付いたものです(クリストファーのおかげで): 1)両側から未使用以下の頻度で使用されるものでデータを埋めます。 2)データをスタックにコピーして、すべてのハードワークが完了した後にそれをコピーします。 3)キャッシュ整列メモリ割り当てを使用してください。
私は詳細を完全に安全ではないが、ここに私の服用:
(1)簡易例は壊れており、Boost create_thread
は参照を予定しているので、一時的に渡します。
(2)各スレッドFROを1つの項目で使用する場合、またはメモリに順次メモリ内にある場合は、誤った共有が発生します。