2

私はこの方法を持っています:

void A::overlapOut(int pos)
{
    for(unsigned int j = 0; j < size; ++j)
    {
        out[pos+j] += local_arr[j] / scalingFactor;
    }
}

std::transform主にコードの一貫性のために、のようなSTLアルゴリズムを使用してリファクタリングしたいと思います。テーマのバリエーションである他の約5つのメソッドがあり、std::transformorを使用してリファクタリングできましたstd::copy。次のように:

void A::nonOverlapOut(int pos)
{
    auto normalize = [&] (double x) { return x / otherScalingFactor; };
    std::transform(local_arr, local_arr + size, out + pos, normalize);
}

ただし、ここでの主な違いは+=. 私の他のすべての関数は重複せず、以前の値を使用しないため、data[i]並列呼び出しを行うことができますが、これはdata[i] += stuffの代わりにを実行する必要がありdata[i] = stuffdata[i]も実行する他のスレッドによってアクセスされる可能性があります+=

それで、これを行うための最良のC++ 11-icの方法は何でしょうか? std::atomic<double>配列の代わりに使用することを考えdoubleましたが、アトミックアクセスを必要としない場所での計算が遅くなりますか?

4

1 に答える 1

0

std::transformは2 つの入力範囲を取ることができ、出力反復子は入力と同じである場合があります。

#include <iostream>
#include <algorithm>

int main() {
    double local_arr[] = {9.0, 8.0, 5.0, 4.0, 5.0};
    double out[] = {12.0, 24.0, 36.0, 48.0, 60.0, 72.0, 84.0};
    auto scalingFactor = 7.0;

    size_t size = 5;
    size_t pos = 1;

    std::transform(local_arr, local_arr + size, out + pos, out + pos,
                    [=](double a, double b) { return a / scalingFactor + b; });

    for (auto v : out) {
        std::cout << v << std::endl;
    }
}

これは のdata[i] = data[i] + stuff代わりにa を行うことに注意してくださいdata[i] += stuff。したがって、このコードdata[i]で の配列を作成std::atomic<double>しても、単一のアトミック命令にはなりません。

しかし、あなたの場合、異なるスレッドが配列のばらばらな部分に書き込むため、競合はなく(§1.10/4)、したがってデータ競合はなく(§1.10/21)、アトミックやロックを必要とせずにスレッドセーフです。

于 2013-10-09T19:58:18.560 に答える