为什么这个C 11代码包含rand()慢与多线程而不是一个?

我试图在新的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和3core机器上编译’g -std = c 11 -pthread test.cpp’,典型结果是

time single: 33
time multi: 565

所以多线程版本的速度要慢一个数量级。我使用随机数和sqrt使这个例子不那么平凡,容易进行编译器优化,所以我的想法。

编辑:

>这个问题比较大的N,所以问题不是短的运行时
>创建线程的时间不是问题。排除它不会显着改变结果

哇我发现了问题。它确实是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 11代码包含rand()慢与多线程而不是一个? - 代码日志