大数组和的优化(多线程)



所以我想优化一个非常大的数组的和,为了做到这一点,我写了一个多线程代码。问题是,使用这段代码,我只使用一个线程而不是2、3或4个线程就可以获得更好的计时结果。。。

有人能解释一下为什么会发生这种事吗?(而且我这学期才开始用C++编码,在那之前我只知道C,所以我对可能出现的愚蠢错误感到抱歉(

这是线程代码

    *localSum = 0.0;
    for (size_t i = 0; i < stop; i++)
            *localSum += v[i];

主要流程代码

    int numThreads = atoi(argv[1]);
    int N = 100000000;
    // create the input vector v and put some values in v
    vector<double> v(N);
    for (int i = 0; i < N; i++)
            v[i] = i;
    // this vector will contain the partial sum for each thread
    vector<double> localSum(numThreads, 0);
    // create threads. Each thread will compute part of the sum and store
    // its result in localSum[threadID] (threadID = 0, 1, ... numThread-1)
    startChrono();
    vector<thread> myThreads(numThreads);
    for (int i = 0; i < numThreads; i++){
            int start = i * v.size() / numThreads;
            myThreads[i] = thread(threadsum, i, numThreads, &v[start], &localSum[i],v.size()/numThreads);
    }

    for_each(myThreads.begin(), myThreads.end(), mem_fn(&thread::join));
    // calculate global sum
    double globalSum = 0.0;
    for (int i = 0; i < numThreads; i++)
            globalSum += localSum[i];
    cout.precision(12);
    cout << "Sum = " << globalSum << endl;
    cout << "Runtime: " << stopChrono() << endl;
    exit(EXIT_SUCCESS);
}

有以下几点:

1-数组不够大。矢量化流媒体添加真的很难击败。您需要一个比add更复杂的函数才能真正看到结果。或者一个非常大的数组。

2-相关的,所有线程创建和连接的开销将淹没线程带来的任何性能收益。添加速度非常快,而且可以很容易地使CPU的功能单元饱和。为了帮助线程,它甚至不能是同一个核心上的超线程,它需要完全在不同的核心上(因为超线程都会争夺浮点单元(。

要测试这一点,可以尝试在启动计时器之前创建所有踏板,并在停止计时器之后停止所有踏板(让它们设置一个done标志,而不是等待连接(。

3-所有localsum变量共享同一个缓存行。最好是在堆栈上设置localsum变量,并将结果放入数组中,而不是直接添加到数组中:https://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html

如果出于某种原因,您需要保持该数组中其他人可以观察到的和,请像这样填充localsum矢量条目,这样它们就不会共享同一个缓存行:

struct localsumentry {
  double sum;
  char pad[56];
};

最新更新