繁体   English   中英

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

[英]Why are threads slowing down the execution of my program?

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

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毫秒。 这是否意味着产生一个线程会花费大量时间,以至于仅顺序进行评估会更有效率? 还是我做错了什么?

请注意,我没有使用任何锁定机制,因为评估彼此独立。 每个validateSingle均从作为Evaluator对象成员的向量中读取,但仅更改为其提供的单个输入。 因此,不需要任何锁定。

更新资料

抱歉,我没有说清楚。 这更多是伪代码,抽象地描述了我的代码的样子。 它不会工作或编译,但是我的却不是,这不是问题。 无论如何,我在这段代码中解决了t0范围问题。

另外,输入大小约为38,000,我认为足以使用并行性。

更新资料

我尝试将输入大小增加到5,000,000,但这没有帮助。 顺序仍然比多线程快。

更新资料

我尝试增加运行线程的数量,同时在它们之间平均分配向量以进行评估,并得到一些有趣的结果:

在此处输入图片说明

请注意,我有一个i7-7500U CPU,它可以并行运行4个线程。 这给我留下了两个问题:

  1. 与2、3相比,为什么创建4个或更多线程开始出现性能提升。
  2. 为什么创建4个以上的线程比4个线程(CPU可以同时运行的最大值)更有效。

“为什么会这样?” 很容易回答。 假设您有一个走廊,可以同时容纳四个人。 您想将所有垃圾一端移动到另一端。 最有效率的人数是4。

如果您有1-3个人,那么您会错过使用一些走廊空间的机会。 如果您有5个或更多的人,那么这些人中至少有一个基本上总是一直排在另一个人后面。 增加越来越多的人只会阻塞走廊,但不会加快活动速度。

因此,您希望拥有尽可能多的人员而不会造成任何排队。 为什么要排队(或出现瓶颈)取决于以下情况。

如果不了解线程的本质,很难说。 诊断系统性能时应考虑的一些事项:

是进程/线程

  1. CPU限制(需要大量的CPU资源)
  2. 内存限制(需要大量RAM资源)
  3. 绑定了I / O(网络和/或硬盘资源)

这三种资源都是有限的,任何一种资源都可能限制系统的性能。 您需要查看您的特定情况正在消耗哪种(可能是2或3)。

您可以使用ntopiostat以及vmstat来诊断正在发生的事情。

编辑1:

我尝试将输入大小增加到5,000,000,但这没有帮助。 顺序仍然比多线程快。

顺序版本速度更快,因为示例中每次迭代所花费的时间可能非常小,并且创建和管理多个线程会涉及相当大的开销。

并行编程仅在每次迭代的处理器时间足够昂贵时才提高效率。

要实际看到差异,请尝试增加此功能的工作量。

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:

  1. 与2、3相比,为什么创建4个或更多线程开始出现性能提升。
  2. 为什么创建4个以上的线程比4个线程(CPU可以同时运行的最大值)更有效。

常见的建议是n + 1线程, n是可用的CPU内核数。 这样, n线程可以在1个线程等待磁盘I / O时使CPU工作。 线程较少将无法充分利用CPU资源(在某些时候总会有I / O等待),线程过多将导致线程争用CPU资源。 此外,您还可以参考此答案该答案说明了为什么更多线程是有益的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM