7

小さいが頻繁に使用する関数オブジェクトがあります。各スレッドは独自のコピーを取得します。すべてが静的に割り当てられます。コピーは、グローバル データまたは静的データを共有しません。このオブジェクトを偽の共有から保護する必要がありますか?

ありがとうございました。編集: これは、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();
}
4

3 に答える 3

6

スレッド間の偽共有は、2 つ以上のスレッドが同じキャッシュ ラインを使用する場合です。

例:

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)。

スタック上のデータは、常に他のスレッドから「遠く」離れています。(たとえば、ウィンドウの下で、少なくとも数ページ)。

Work関数オブジェクトの定義では、 のインスタンスがヒープ上に作成され、このヒープ領域がスレッド内で使用されるため、誤った共有が発生する可能性があります。

これにより、複数のWorkインスタンスが隣接する可能性があり、キャッシュ ラインの共有が発生する可能性があります。

しかし...あなたのサンプルは意味がありません。なぜなら、データは外部で決して触れられないため、誤った共有が不必要に誘発されるからです。

このような問題を防ぐ最も簡単な方法は、「共有」データをスタックにローカルにコピーしてから、スタック コピーで作業することです。作業が終了したら、それを出力変数にコピーします。

例えば:

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;
};

これにより、共有に関するすべての問題が回避されます。

于 2010-07-26T09:55:12.887 に答える
2

私はかなりの調査を行いましたが、偽の共有に対する特効薬の解決策はないようです. これが私が思いついたものです(クリストファーに感謝します):1)未使用またはあまり使用されていないもので両側からデータを埋めます。2)データをスタックにコピーし、すべてのハードワークが完了したらコピーして戻します。3) キャッシュ整列メモリ割り当てを使用します。

于 2010-07-26T22:55:54.137 に答える
0

詳細については完全に安全だとは思いませんが、私の見解は次のとおりです。

(1)ブーストcreate_threadは参照を期待しているため、単純化された例は壊れています。一時的なものを渡します。

(2) vector<Work>スレッドごとに 1 つの項目を使用する場合、またはそれらを順番にメモリに保持する場合、誤った共有が発生します。

于 2010-07-26T09:53:15.660 に答える