c++ - 为什么这个包含 rand() 的 C++11 代码多线程比单线程慢?

标签 c++ multithreading performance c++11

我正在尝试使用新的 C++11 线程,但我的简单测试具有糟糕的多核性能。作为一个简单的例子,这个程序将一些平方随机数相加。

#include <iostream>
#include <thread>
#include <vector>
#include <cstdlib>
#include <chrono>
#include <cmath>

double add_single(int N) {
    double sum=0;
    for (int i = 0; i < N; ++i){
        sum+= sqrt(1.0*rand()/RAND_MAX);
    }
    return sum/N;
}

void add_multi(int N, double& result) {
    double sum=0;
    for (int i = 0; i < N; ++i){
        sum+= sqrt(1.0*rand()/RAND_MAX);
    }
    result = sum/N;
}

int main() {
    srand (time(NULL));
    int N = 1000000;

    // single-threaded
    auto t1 = std::chrono::high_resolution_clock::now();
    double result1 = add_single(N);
    auto t2 = std::chrono::high_resolution_clock::now();
    auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
    std::cout << "time single: " << time_elapsed << std::endl;

    // multi-threaded
    std::vector<std::thread> th;
    int nr_threads = 3;
    double partual_results[] = {0,0,0};
    t1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < nr_threads; ++i) 
        th.push_back(std::thread(add_multi, N/nr_threads, std::ref(partual_results[i]) ));
    for(auto &a : th)
        a.join();
    double result_multicore = 0;
    for(double result:partual_results)
        result_multicore += result;
    result_multicore /= nr_threads;
    t2 = std::chrono::high_resolution_clock::now();
    time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
    std::cout << "time multi: " << time_elapsed << std::endl;

    return 0;
}

在 Linux 和 3 核机器上使用 'g++ -std=c++11 -pthread test.cpp' 编译,典型结果为

time single: 33
time multi: 565

所以多线程版本慢了一个数量级以上。我使用了随机数和 sqrt 来使示例变得不那么琐碎并且易于编译器优化,所以我没有想法。

编辑:

  1. 此问题适用于较大的 N,因此问题不在于运行时间短
  2. 创建线程的时间不是问题。排除它不会显着改变结果

哇,我发现了问题。确实是 rand()。我将其替换为 C++11 等效项,现在运行时可以完美扩展。谢谢大家!

最佳答案

在我的系统上,行为是相同的,但正如 Maxim 所说,rand 不是线程安全的。当我将 rand 更改为 rand_r 时,多线程代码会像预期的那样更快。

void add_multi(int N, double& result) {
double sum=0;
unsigned int seed = time(NULL);
for (int i = 0; i < N; ++i){
    sum+= sqrt(1.0*rand_r(&seed)/RAND_MAX);
}
result = sum/N;
}

关于c++ - 为什么这个包含 rand() 的 C++11 代码多线程比单线程慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16716005/

相关文章:

c++ - 如何从 C FILE* 创建 C++ streambuf 对象,与指向的 FILE 对象共享其缓冲区(和缓冲区状态)?

c++ - 花 : How do I create a tuple of types from a variant?

c++ - 为什么我的weighted_grade变量不起作用?

c++ - 字符串和函数对象

linux - 如何使用 shell 脚本运行 2 个命令

c# - 与 C# 相比,F# 的性能如何?

c++ - 使用构造函数参数将仿函数传递给 std::thread。是否可以?

C - 如何运行一个线程几秒钟,然后继续运行第二个线程

java - 图形加载缓慢或什至无法加载

java - 比较两个非常大的列表的最佳方法