|
|
1
7
两者之间存在一些根本区别 Mystical's answer 和您的代码。 差异#1您的代码为每个CPU创建一个工作块,并让它运行到完成。这意味着一旦一个线程完成,CPU使用量将急剧下降,因为一个CPU将处于空闲状态,而其他线程将运行到完成状态。这是因为日程安排并不总是公平的。一个线程的进度和完成速度可能比其他线程快得多。
OpenMP解决方案通过声明
最终,这成为一种平衡行为,即挑选足够大的块。太大,CPU可能在任务结束时没有达到最大值。太小,可能会有很大的开销。 差异#2
您正在写入变量,
OpenMP解决方案通过以下方式解决了这一问题
reducing
通过
了解了OpenMP是如何拆分、安排工作和合并结果的,我们可以修改您的代码,使其行为类似。
这仍然不是OpenMP示例行为的完美再现。例如,这更接近OpenMP
即使有这些差异,我也能够在很长一段时间内最大限度地使用所有CPU。
展望未来。。。
您可能注意到OpenMP版本的可读性要高得多。这是因为它旨在解决这样的问题。因此,当我们试图在没有库或编译器扩展的情况下解决它们时,我们最终会重新发明轮子。幸运的是,为了将这种功能直接引入C++,我们做了很多工作。具体来说
在C++11中,在Boost的帮助下,此算法可以写成:
为了将算法并行化,您只需要
这就是让我乐于阅读的代码。 注:绝对没有花时间优化此算法。如果我们要做任何优化,我会研究类似于 Sieve of Eratosthenes 它使用以前的素数计算来帮助将来的计算。 |
|
|
2
5
首先,您需要意识到OpenMP通常有一个相当复杂的线程池,因此(精确地)匹配它可能至少有些困难。 其次,在我看来,在优化线程之前 应该 尝试至少从一个中等水平的基本算法开始。在这种情况下,您正在实现的基本算法基本上相当糟糕。它检查数字是否是质数,但做了很多工作,却没有完成任何有用的事情。
虽然它可能不会影响速度,但我也发现使用一个函数来检查
仅有一个的
数字是质数,只返回
你 可以 通过消除更多的因素来优化算法,但这并没有给我带来“优化”的印象,我只是简单地避免了完全不必要的悲观。
至少在我看来,它(在这种情况下)也更容易使用
那么,让我们从修复开始
现在,让我指出,这已经足够快了(即使是单线程),如果我们只想让工作完成得比完美的线程伸缩快4倍左右,我们就完成了,即使根本不使用线程。就你给出的极限而言,这在1秒钟内完成。 然而,为了便于讨论,让我们假设我们希望获得更多,并且也使用多个内核。这里需要认识到的一点是,我们通常希望至少比内核多几个线程。问题相当简单:每个核只有一个线程,我们没有什么可以弥补的事实是,我们甚至没有在线程之间真正分配负载——处理最大数量的线程比处理最小数量的线程要做的工作多得多——但如果我们有一台(例如)4核机器,只要一个线程完成,我们只能使用75%的CPU。然后当另一条线结束时,它会下降到50%。然后25%,最后完成,只使用一个核心。 我们 能够 可能会进行一些计算以尝试更均匀地分配负载,但只需将负载拆分为核心线程数的六到八倍就容易多了。这样,计算可以继续使用所有内核,直到只剩下三个线程为止 1. . 将所有这些放入代码中,我们可以得到如下结果:
注意几点:
至少当我运行这个程序时,它的行为似乎与我们预期/希望的一样:它使用100%的CPU时间,直到它接近尾声,当它在完成之前开始下降时(即,当我们要执行的线程少于要执行的内核时)。
|
|
|
3
1
OpenMP示例对sum变量使用“reduction”
或者可以使用数组模拟OpenMP缩减
|
|
|
user107586 · 如何处理等待句柄不会导致无限循环? 1 年前 |
|
|
ron burgundy · 获取-释放语义是否跨线程传递?[副本] 1 年前 |
|
|
BenjiFB · C#内存缓存:在一次操作中追加到列表? 1 年前 |
|
|
András Takács · Python多线程问题 2 年前 |
|
|
András Takács · Python多线程错误 2 年前 |