改进多线程的一般技巧(在 C++ 中)

Posted

技术标签:

【中文标题】改进多线程的一般技巧(在 C++ 中)【英文标题】:General tips to improve multithreading (in C++) 【发布时间】:2016-12-05 21:52:03 【问题描述】:

我已经构建了一个 C++ 代码,但没有想到我以后需要对它进行多线程处理。我现在已经使用 openMP 对 3 个主要的 for 循环进行了多线程处理。以下是性能比较(使用来自 bash 的 time 测量)

单线程

real    5m50.008s
user    5m49.072s
sys     0m0.877s

多线程(24 线程)

real    1m22.572s
user    28m28.206s
sys     0m4.170s

使用 24 个内核将实时时间减少了 4.24 倍。当然,我没想到代码会快 24 倍。我真的不知道会发生什么。

- 是否有经验法则可以让人们预测与单线程相比,使用n 线程的给定代码运行速度会快多少?

- 是否有一般提示可以提高多线程进程的性能?

【问题讨论】:

你有一台24核的机器? @pm100 是(24 个逻辑核心)。我不拥有它,它属于我的实验室。 【参考方案1】:

我相信您知道障碍成本等显而易见的问题。但是很难在微不足道的事情和对某人有帮助的事情之间划清界限。以下是一些使用中的经验教训,如果我想到更多,我会添加它们:

始终尝试尽可能长时间地使用线程私有变量,考虑到即使是减少,也只能提供少量的集体结果。

更喜欢并行运行较长的代码段和较长的并行段 (#pragma omp parallel ... #pragma omp for),而不是单独并行化循环 (#pragma omp parallel for)。

不要并行化短循环。在二维迭代中,并行化外循环通常就足够了。如果您确实使用 collapse 并行化整个事情,请注意 OpenMP 会将其线性化,引入一个融合变量并单独访问索引会产生开销。

使用线程私有堆。尽可能避免共享池和集合,即使集合的不同成员会被不同的线程独立访问。

分析您的代码并查看在忙等待上花费了多少时间以及可能发生的位置。

了解使用不同日程安排策略的后果。尝试什么更好,不要假设。

如果您使用关键部分,请为其命名。所有未命名的 CS 都必须互相等待。

如果您的代码使用随机数,请使其可重现:定义线程局部 RNG,以可控方式播种所有内容,对减少进行排序。确定性地进行基准测试,而不是统计性的。

在 Stack Overflow 上浏览类似问题,例如精彩答案here。

【讨论】:

以上是关于改进多线程的一般技巧(在 C++ 中)的主要内容,如果未能解决你的问题,请参考以下文章

C++多线程同步技巧--- 互斥体

c++多线程——锁技巧

C++多线程同步技巧--- 事件

Linux VM(重型多线程应用程序)的性能改进

C++服务器设计:多线程模型设计

多线程递归程序c++