当前位置: 首页 > 知识库问答 >
问题:

为什么这个包含rand()的C++11代码使用多个线程比使用一个线程慢?

何峰
2023-03-14

我正在尝试新的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
    null

哇,我发现问题了。确实是兰德()。我用一个C++11等价物替换了它,现在运行时可以完美地伸缩。谢谢大家!

共有1个答案

督建柏
2023-03-14

在我的系统中,行为是相同的,但正如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;
}
 类似资料:
  • 在这段代码中,两个连接和断开是什么意思?导致停止,直到终止?

  • 我编写了代码示例: 每100毫秒提交一个新任务(总任务量-20)。每个任务持续时间-0.5秒。因此,可以并行执行5个任务,最佳执行时间为:20*100 500=2.5秒,池应创建5个线程 但我的实验显示为9.6秒。我打开jsvisualvm查看池创建了多少线程,我看到只创建了一个线程: 请更正我的线程池配置不正确的地方。

  • 本文向大家介绍为什么要使用多线程?相关面试题,主要包含被问及为什么要使用多线程?时的应答技巧和注意事项,需要的朋友参考一下 先从总体上来说: 从计算机底层来说:线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。 从当代互联网发展趋势来说:现在的系统动不动就要求百万级甚至千万级的并

  • 在我的程序中,我需要多个线程使用和编辑同一个变量,但它似乎不起作用。这是我的意思的一个例子,这将是我的主要课程。 这将是我的Thread类: 我当场编写了这段代码,所以可能会有一些错误,但没关系。我的程序基本上需要这样做,但不是每次打印数字加1,而是所有线程只需多次打印相同的数字0。请帮帮我,谢谢。

  • 我正在解决一个生产者/消费者问题,我想创建几个生产者和消费者(几个线程),我有一个问题,我如何才能正确地创建几个线程,使一个任务不由两个线程执行(每个线程执行一个不同的任务)。 代码:我试着做一个循环,就像下面这样: 输出:但它不起作用,因为线程相互重叠