c++ - 为什么线程会减慢程序的执行速度?

标签 c++ multithreading

我有一些代码可以利用并行性来提高效率。由于我的电脑有一个双处理器,我试着在两个线程上运行代码所以我写了下面的代码(这是一个非常简单的版本):

Evaluator::evaluate(vector<inpType> input, bool parallel) {
    std::thread t0;
    if(parallel) {
        // Evaluate half of the input in a spawned thread
        t0 = std::thread(&Evaluator::evaluatePart, this, std::ref(input), 0, input.size()/2 + input.size()%2);
        // Evaluate the other half of the input in this thread
        evaluatePart(input, input.size()/2 + input.size()%2 - 1, input.size()/2);
    } else {
        // sequential evaluate all of the input
        evaluatePart(input, 0, input.size());
    }
    // some other code

    // after finishing everything join the thread
    if(parallel) t0.join();
}

Evaluator::evaluatePart(vector<inpType> &input, int start, int count) {
    for(int i=start; i<count; i++) {
        evaluateSingle(input[i]);
    }
}

Evaluator::evaluateSingle(inpType &input) {
    // do stuff with input
    // note I use a vector<int> belonging to Evaluator object in here, not sure it matters though
}

按顺序运行大约需要3毫秒,而并行运行大约需要6毫秒。这是否意味着生成一个线程需要如此多的时间,以至于只按顺序评估更有效还是我做错了什么?
注意,我没有使用任何锁定机制,因为计算是相互独立的。每个EvaluateSingle都从作为Evaluator对象的成员的向量中读取数据,但只会更改给定给它的单个输入。因此不需要任何锁定。
更新
很抱歉我没有说清楚。这更像是一个伪代码,抽象地描述了我的代码是什么样子的它将不会工作或编译,但我这样做,这不是问题无论如何,我修复了这段代码中的t0范围问题。
另外,输入大小大约是38000,我认为这足以利用并行性。
更新
我试着把投入的规模增加到5000000,但没有帮助顺序仍然比多线程快。
更新
我尝试增加运行的线程数,同时在它们之间均匀地分割向量进行计算,得到了一些有趣的结果:
enter image description here
注意,我有一个i7-7500UCPU,可以并行运行4个线程这留给我两个问题:
为什么创建4个或更多线程会比2、3个线程的性能有所提高。
为什么创建4个以上的线程比
只有4个线程(CPU可以同时运行的最大值)。

最佳答案

“为什么会这样?”有点容易回答。假设你有一个走廊,可以容纳四个人,并排。你想把所有的垃圾从一端移到另一端。最有效的人数是4人。
如果你有1-3个人,那么你就错过了一些走廊空间。如果你有5个或更多的人,那么至少其中一个基本上一直被困在另一个人后面排队。越来越多的人堵塞了走廊,这并不能加快活动速度。
所以你想有尽可能多的人,你可以不引起任何排队。排队(或瓶颈)的原因取决于以下几点。
如果不了解更多关于你的线程的性质,很难说。诊断系统性能时需要考虑的一些事项:
是进程/线程
CPU限制(需要大量CPU资源)
内存限制(需要大量RAM资源)
I/O绑定(网络和/或硬盘资源)
这三种资源都是有限的,任何一种资源都会限制系统的性能。你需要看看你的特定情况下(可能是2或3在一起)在消耗什么。
您可以使用ntopiostat以及vmstat来诊断发生了什么。
编辑1:
我试着把投入的规模增加到5000000,但没有帮助顺序仍然比多线程快。
顺序版本更快,因为在您的示例中,对每个迭代执行操作所花费的时间可能非常少,并且在创建和管理多个线程时会产生相当大的开销。
并行编程只在每次迭代的处理器时间足够昂贵时才提高效率。
要实际看到差异,请尝试增加此函数中的工作。

Evaluator::evaluateSingle(inpType &input) {
    // do stuff with input
    // note I use a vector<int> belonging to Evaluator object in here, not sure it matters though
}

编辑2:
为什么创建4个或更多线程会比2、3个线程的性能有所提高。
为什么创建多于4个线程的效率比仅仅4个线程(CPU可以运行的最大值)更有效?
同时)。
一个常见的建议是n + 1线程,n是可用的cpu核心数。这样,当一个线程在等待磁盘I/O时,线程可以工作在CPU上。线程越少,CPU资源利用率就越低(在某个时刻,总是有I/O等待),线程越多,CPU资源的争夺就越激烈。此外,您还可以参考this answer,这说明了为什么更多线程是有益的。

关于c++ - 为什么线程会减慢程序的执行速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45542851/

相关文章:

javascript - Node.js 如何用一个线程处理并发请求?

Python 多处理列表字典比较

c++ - fread() 在在线编辑器和本地计算机 (C++) 上的不同行为

c++ - C++ 是否具有指定值范围的比较运算符? (比如 E 语言中的 'in')?

c++ - 使用std set find时,程序不会编译

c++ - 无法将 MyClass* 转换为 const MyClass

c++ - 如何从线程函数返回值?

multithreading - 如何使用 Node.js 创建多线程应用程序,访问 LevelDB?

ios - 下载 JSON 时如何修复延迟的 UITableView 滚动性能?

c++ - 全等、相似和直角三角形