【问题标题】:Should the speed of producer-consumer increase with more threads? [closed]生产者-消费者的速度是否应该随着线程的增加而增加? [关闭]
【发布时间】:2022-01-10 09:57:29
【问题描述】:

我正在尝试用 C++ 实现一个生产者-消费者问题程序。其中一个线程用不同数字的向量填充队列,而其他线程将向量从队列中取出(使用条件变量/唯一锁同步)并在向量上执行简单的 for 循环,对数字执行一些操作。问题是,如果我使用超过 2 个线程,程序的速度似乎并没有增加。以下是我发现的一些东西:

  • 生产者线程比消费者线程快,这意味着向量的填充速度将比消费者处理数据的速度快
  • 处理队列中的单个向量需要很短的时间,这意味着消费者会不断地从队列中请求数据(我认为这可能是同步的瓶颈,但不确定)

在这样的程序中,是否期望更多的线程会使程序更快,或者是恒定的速度与线程数无关? 感谢您的任何回答或解释!

【问题讨论】:

  • 您的 CPU 有多少个内核?如果你有 3-4 个或更少,那么无论如何你都不会获得更多的性能。
  • 另外,您的同步开销听起来确实是这里的限制因素。您可以尝试进行批处理(每次使用多个向量),或者让生产者线程将工作分配给特定线程并减少锁争用。
  • 还要注意 std::vector 触及堆,它自己锁定。如果这是问题,切换到恒定长度数组可能会有所帮助。但是您确实需要进行概要分析才能确定。
  • 感谢所有提示。 CPU有6个核心,所以这应该不是问题。我尝试使用一个恒定长度的数组,但它并不多。批处理确实有助于提高整体时间,但不会改变超过 2 个内核根本没有区别的事实......

标签: c++ multithreading producer-consumer


【解决方案1】:

欢迎来到阿姆达尔定律:https://en.wikipedia.org/wiki/Amdahl%27s_law

如果与计算相比,您的同步需要大量时间,则您不能期望有太多的加速,因为关键部分实际上是单线程的。此外,在您的场景中,内存分配/解除分配实际上是单线程的,因为您的生产者从其自己的内存区域分配,而消费者需要将向量解除分配到同一个区域。

解决此问题的一个好方法是增加工作项的大小。不要采用单个向量,而是采用多个向量。确切的大小将需要一些基准测试。一个很好的起点是采取约。 L2 缓存大小,即累积大小约为 64-256 kiB 的向量。

【讨论】:

  • 感谢您的提示,我确实增加了工作量(单个线程一次大约需要 250 个项目),虽然它确实提高了程序的整体速度,但它仍然没有改变事实使用超过 2 个内核对速度没有影响...
  • @icyfox 您可能受到内存带宽而非计算性能的限制。单个向量有多大?你每秒产生多少数据?您对它们执行什么类型的计算?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
  • 2017-02-01
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多