c++ - 大数组总和的优化(多线程)

标签 c++ multithreading

所以我想优化一个非常大的数组的总和,为了做到这一点,我编写了一个多线程代码。问题是,使用这段代码,我只使用一个线程而不是 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的功能单元饱和了。为了使线程能够提供帮助,它甚至不能是同一内核上的超线程,它需要完全位于不同的内核上(因为超线程会竞争浮点单元)。

要对此进行测试,您可以尝试在启动计时器之前创建所有踏板,并在计时器停止后将它们全部停止(让它们设置完成标志而不是等待加入)。

3- 您所有的 localsum 变量都共享相同的缓存行。更好的做法是在堆栈上创建 localsum 变量并将结果放入数组而不是直接添加到数组中:https://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html

如果出于某种原因,您需要让该数组中的其他人可以观察到总和,请像这样填充局部总和 vector 条目,这样它们就不会共享相同的缓存行:

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

关于c++ - 大数组总和的优化(多线程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53288646/

相关文章:

c++ - 将数组作为参数传递给外部 ASM(程序集)x86 并访问它

java - Callable<T> call() + 输入参数 + Spring

c++ - OpenMP自动更新数组值

c++ - MSVC 2008 错误 'Type' 不是结构(尽管它是)

c++ - 是否有任何指令集支持 MIMD 架构?

c++ - 使用 openMP 进行并行化 - 堆栈或堆变量

c++ - Visual Studio 2013 分析 Cinder 项目时,没有出现单个函数调用

c++ - 这种使用指向实例的指针创建分离的 std::thread 的方法是否错误?

c# - 我的一个集成测试是在杀死 MSTest 的备用线程上抛出异常。管理这个的好模式是什么?

multithreading - 是否可以按随机顺序执行 celery 任务?