为啥使用更多线程会导致运行时间变慢?

Posted

技术标签:

【中文标题】为啥使用更多线程会导致运行时间变慢?【英文标题】:Why does using more threads results in slower runtime?为什么使用更多线程会导致运行时间变慢? 【发布时间】:2019-10-14 13:08:56 【问题描述】:

我在具有 32 个 CPU(1 个插槽,每个插槽 16 个内核,每个内核 2 个线程)的机器上运行 Ubuntu。

我有一个包含 ~100-1000 个对象的 std::vector,我正在尝试并行化一个 for 循环,该循环从向量中的每个对象读取数据并写入文件以记录每个对象的状态。每个对象都有一个文件。我玩过omp_set_num_threads(8),发现有大约8 个线程的最佳位置。如果我增加或减少线程数,运行时性能将会下降。鉴于我有 32 个可用 CPU,我不确定为什么将线程数增加到 8 以上会降低运行时性能。我知道以前有人问过很多类似的问题,但我似乎无法找到解决我的特定问题的方法。

#include <algorithm>
#include <experimental/filesystem>
#include <omp.h>
namespace fs = std::experimental::filesystem;  

void log() 
    omp_set_num_threads(8);

    // Log all object states
    if(this->logstate)
        #pragma omp parallel for
        for(auto i = vObject.begin(); i < vObject.end(); ++i)   
            fs::path filename = (*i)->get_filename();
            std::ofstream OutputFile;
            OutputFile.open(filename, std::ios::app);
            OutputFile << std::setw(30) << (*i)->get_EPOCH() << std::setw(20) << std::scientific << std::setprecision(5) << (*i)->get_state() << std::endl;
            OutputFile.close();
        
    

任何想法或建议将不胜感激。

【问题讨论】:

只是一个疯狂的猜测:如果线程数超过 8 个,那么同时您将有超过 8 个“进程”写入磁盘。可能会造成一些瓶颈 我猜你只能同时写入 8 个文件。 一个只有 100-1000 个对象的向量足够小,可以在不注意的情况下迭代单线程。即使对每个对象进行单线程文件处理也会非常快。尤其是考虑到可能来自多个线程竞争同一设备的 IO 争用。 创建和销毁线程是有代价的。在线程之间切换是有代价的。线程之间的同步是有代价的。添加线程不是可以加快速度的神奇银弹。如果问题中没有足够的并行性来克服使用线程的开销,那么您很可能通过添加更多线程来减慢代码的速度。 你没有给出任何时间度量。如果整个过程花费的时间少于几秒钟,那么由于 Some dude 和 Jesper 解释的原因,您将开始失去添加超过 8 个线程的过程。 【参考方案1】:

我在具有 32 个 CPU(1 个插槽,每个插槽 16 个内核,每个内核 2 个线程)的机器上运行 Ubuntu。

线程不是 CPU。 内核甚至不是真正的 CPU;每个内核都可以独立执行代码,但它们都共享一个内存总线和各种其他资源。

因此,您有 32 个线程在 16 个内核上运行,所有内核共享一个总线。在某些时候会发生争用某事,这意味着很多线程必须坐下来等待。更多线程 -> 更多争用 -> 更多等待。

现在,我们都可以对资源争用的位置做出有根据的猜测——是文件系统、内存总线还是其他什么?但是我们对您的系统以及可能发生的其他事情知之甚少,因此这可能毫无意义。分析在更多线程上运行的代码以查看它在哪里做了很多等待可能会提出一些答案。请记住,这些答案可能特定于您当前的情况;如果您更改需要为每个对象完成的计算工作,或更改收集输出的方式等,这可能会影响最佳位置。

【讨论】:

以上是关于为啥使用更多线程会导致运行时间变慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在IOS上运行torchscript模型推理会导致线程错误?

为啥我的触摸事件频率在 iOS 4.0 上变慢了?

为啥使用了线程池速度没有变化呢python

为啥运行单线程 Java 程序会导致许多内核处于活动状态?

jvm 虚拟机优化

使用 Circe Json 为啥隐式解析在运行时会变慢