C++ 简单的线程分工并不能减少所需的时间

C++ 简单的线程分工并不能减少所需的时间,c++,linux,multithreading,c++17,C++,Linux,Multithreading,C++17,我一直在尝试通过将工作分解为任务/线程来提高项目的计算时间,但效果不是很好。所以我决定做一个简单的测试项目,看看我是否能在一个非常简单的情况下让它工作,这也不是我所期望的工作 我试图做的是: 在一个线程中执行一个任务X次-检查所花费的时间 在Y个线程中执行任务X/Y次-检查所花费的时间 因此,如果一个线程需要T秒来完成10万次“工作”迭代,那么我希望: 两个线程每次进行50'000'000次迭代需要~T/2秒 3个线程进行33'333'333次迭代,每次需要~T/3秒 以此类推,直到达到

我一直在尝试通过将工作分解为任务/线程来提高项目的计算时间,但效果不是很好。所以我决定做一个简单的测试项目,看看我是否能在一个非常简单的情况下让它工作,这也不是我所期望的工作

我试图做的是:

  • 在一个线程中执行一个任务X次-检查所花费的时间
  • 在Y个线程中执行任务X/Y次-检查所花费的时间
因此,如果一个线程需要T秒来完成10万次“工作”迭代,那么我希望:

  • 两个线程每次进行50'000'000次迭代需要~T/2秒
  • 3个线程进行33'333'333次迭代,每次需要~T/3秒
以此类推,直到达到某个线程限制(内核数或其他)

因此,我编写了代码,并在我的8核系统(AMD Ryzen)上进行了测试,当时大量的RAM大于16GB,其他什么都不做

  • 1线程:约6.5s
  • 需要2个线程:~6.7秒
  • 需要3个线程:~13.3s
  • 需要8个线程:~16.2s
很明显,这里有些不对劲

我将代码移植到Godbolt中,我看到了类似的结果。导丝螺栓只允许3个螺纹,对于1、2或3个螺纹,需要~8秒(大约1秒)才能运行。以下是godbolt的实时代码:

最后,这里是代码供参考:

#包括
#包括
#包括
#包括
#定义randf()((双)rand())/((双)(rand_MAX))
无效线程功能(uint32线程交互,uint32线程id)
{
//打印线程id/工作负载
std::cout该函数不能保证线程安全。在您的实现中,它似乎是通过使用锁或互斥锁来实现的,因此如果多个线程试图生成一个随机数轮流执行。由于您的循环主要是调用
rand
,因此多个线程会影响性能

您可以使用
头的功能,让每个线程使用自己的引擎来生成随机数。

该函数不保证线程安全。在您的实现中,它似乎是通过使用锁或互斥锁来实现的,因此如果多个线程试图轮流生成随机数oop主要只是调用
rand
,多线程会影响性能

您可以使用
标题的功能,让每个线程使用自己的引擎生成随机数。

不要介意
rand()
是否线程安全。如果统计学家告诉您“随机数”你得到的数字在某种程度上有缺陷,但它不能解释时间

解释计时的原因是,只有一个随机状态对象,它在内存中的某个位置,并且所有线程都在相互竞争以访问它

无论系统有多少个CPU,一次只能有一个线程访问主内存中的同一位置

如果每个线程都有自己独立的随机状态对象,则情况会有所不同。然后,从任何给定CPU到自己私有随机状态的大多数访问都只需到达CPU的本地缓存,并且它们不会与其他线程(在其他CPU上运行,每个线程都有自己的本地缓存)的操作发生冲突。

不要介意
rand()
是否线程安全。如果统计学家告诉您,您得到的“随机”数字在某些方面存在缺陷,这可能就是原因,但它不能解释时间

解释计时的原因是,只有一个随机状态对象,它在内存中的某个位置,并且所有线程都在相互竞争以访问它

无论系统有多少个CPU,一次只能有一个线程访问主内存中的同一位置


如果每个线程都有自己独立的随机状态对象,则情况会有所不同。然后,从任何给定CPU到自己私有随机状态的大多数访问都只需到达CPU的本地缓存,并且它们不会与其他线程(在其他CPU上运行,每个线程都有自己的本地缓存)的操作发生冲突。

<代码> RAND 不是线程安全的。如果我必须猜测,你的<代码> RAND 可以用某种形式的独占锁来实现。让我想起一个老问题,线程越慢,它就越慢。虽然它与你的情况无关。@代码包考虑为每个线程创建一个唯一的生成器。参见现代随机麻木er生成功能。这些功能应在
rand()上使用
@code\u fodder请注意,您的代码除了计时之外没有任何可见的行为。您在循环中所做的实际工作没有明显的影响。因此,更智能的编译器可能能够以您意想不到的方式优化您的基准测试,直到并包括消除模拟的工作循环。
rand
不是线程安全的。如果我不得不猜测,您可以R>代码> RAND 可以用某种形式的独占锁实现。让我想起一个老问题,线程越慢,它就越慢。虽然它与你的情况无关。@代码包考虑为每个线程创建一个唯一的生成器。参见现代随机数生成特征。这些应该用于<代码> RAND()。
@code\u fodder请注意,您的代码除了计时之外没有任何可见的行为。您在循环中所做的实际工作没有明显的影响。因此,更智能的编译器可能能够以您意想不到的方式优化您的基准测试,包括消除模拟的工作循环。因此,这解决了我这里的问题-我想我可能已经做到了在我的真实项目中类似的东西-即我使用了很多数学函数,我想我需要检查每一个函数的线程安全互斥锁:o(或者只是分析它)@code\u fodder这会令人震惊