4

私は現在pthreadsCで学んでおり、False Sharingの問題に遭遇しました。私はその概念を理解していると思います。少し実験してみました。

以下は、私が遊んでいる短いプログラムです。最終的には、これをプログラムに変更して、int の大きな配列を取得し、並列に合計します。

#include <stdio.h>
#include <pthread.h>

#define THREADS 4
#define NUMPAD 14

struct s
{
  int total; // 4 bytes
  int my_num; // 4 bytes
  int pad[NUMPAD]; // 4 * NUMPAD bytes
} sum_array[4];

static void *worker(void * ind) {
    const int curr_ind = *(int *) ind;
    for (int i = 0; i < 10; ++i) {
      sum_array[curr_ind].total += sum_array[curr_ind].my_num;
    }
    printf("%d\n", sum_array[curr_ind].total);
    return NULL;
}

int main(void) {
    int args[THREADS] = { 0, 1, 2, 3 };
    pthread_t thread_ids[THREADS];

    for (size_t i = 0; i < THREADS; ++i) {
        sum_array[i].total = 0;
        sum_array[i].my_num = i + 1;
        pthread_create(&thread_ids[i], NULL, worker, &args[i]);
    }

    for (size_t i = 0; i < THREADS; ++i) {
        pthread_join(thread_ids[i], NULL);
    }
}

私の質問は、パディングを使用せずに誤った共有を防ぐことは可能ですか? ここでstruct sは、各構造体が独自のキャッシュ ライン上にあるように 64 バイトのサイズを持っています (キャッシュ ラインが 64 バイトであると仮定します)。パディングなしで並列処理を実現する方法がわかりません。

また、1000 ~ 50,000 バイトのさまざまなサイズの配列を合計する場合、どうすれば偽共有を防ぐことができるでしょうか? 同様のプログラムを使用してパディングすることはできますか? 私の現在の考えは、大きな配列からの各 int を配列に入れ、struct s並列処理を使用して合計することです。ただし、これが最適なソリューションであるかどうかはわかりません。

4

1 に答える 1

2

問題を分割します。 ではworker()、ローカル変数に合計し、ローカル変数を配列に追加します。

static void *worker(void * ind) {
    const int curr_ind = *(int *) ind;
    int localsum = 0;
    for (int i = 0; i < 10; ++i) {
      localsum += sum_array[curr_ind].my_num;
    }
    sum_array[curr_ind].total += localsum;
    printf("%d\n", sum_array[curr_ind].total);
    return NULL;
}

これは、ループ後にまだ偽の共有がある可能性がありますが、それはスレッドごとに 1 回です。スレッド作成のオーバーヘッドは、単一のキャッシュ ミスよりもはるかに重要です。もちろん、現在のコードを次のように最適化できるため、実際に時間のかかる処理を実行するループが必要になる場合があります。

static void *worker(void * ind) {
    const int curr_ind = *(int *) ind;
    int localsum = 10 * sum_array[curr_ind].my_num;
    sum_array[curr_ind].total += localsum;
    printf("%d\n", sum_array[curr_ind].total);
    return NULL;
}

その実行時間は、.NET でのスレッドの作成と同期によって確実にprintf()支配されます。

于 2015-05-17T08:33:58.807 に答える