首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >英特尔OpenMP库通过设置KMP_AFFINITY=scatter来显著降低KMP_AFFINITY=scatter平台上的内存带宽

英特尔OpenMP库通过设置KMP_AFFINITY=scatter来显著降低KMP_AFFINITY=scatter平台上的内存带宽
EN

Stack Overflow用户
提问于 2020-10-18 03:52:20
回答 1查看 922关注 0票数 4

对于内存绑定程序,使用许多线程并不总是更快,比如使用与内核相同的数目,因为线程可能会争夺内存通道。通常在双套接字机器上,较少的线程更好,但我们需要设置关联策略,将线程分布在套接字上,以最大化内存带宽。

英特尔OpenMP声称,KMP_AFFINITY=scatter就是为了达到这个目的,相反的价值“紧凑”是把线程尽可能的靠近。我已经使用ICC构建了用于基准测试的Stream程序,这一说法很容易在Intel机器上得到验证。如果设置了OMP_PROC_BIND,则忽略OMP_PLACES和OMP_PROC_BIND等原生OpenMP env。你会收到这样的警告:

代码语言:javascript
运行
复制
        OMP: Warning #181: OMP_PROC_BIND: ignored because KMP_AFFINITY has been defined

然而,在我获得的最新AMD EPYC机器上的基准显示了非常奇怪的结果。KMP_AFFINITY=scatter 提供了最慢的内存带宽(可能是)。看起来,这个设置在AMD机器上做的正好相反:尽可能靠近线程,这样甚至连每个NUMA节点上的L3缓存都没有得到充分的利用。如果我显式地设置了OMP_PROC_BIND=spread,英特尔OpenMP就会忽略上面的警告。

AMD机器有两个插座,每个插座有64个物理核心。我使用了128、64和32个线程进行了测试,我希望它们能够扩展到整个系统。使用OMP_PROC_BIND=spread,Stream给我的三合一速度分别为225、290和300 GB/s。但是,一旦我设置了KMP_AFFINITY=scatter,即使OMP_PROC_BIND=spread仍然存在,流也会提供264、144和72 GB/s。

注意,对于128个核心上的128个线程,设置KMP_AFFINITY=scatter可以提供更好的性能,这进一步表明,实际上所有线程都尽可能地放置在一起,而不是分散在一起。

总之,KMP_AFFINITY=scatter在AMD上显示完全相反的行为(以坏的方式显示),它甚至会覆盖本机OpenMP环境,而不管它的品牌是什么。整个情况听起来有点可疑,因为众所周知,ICC检测CPU品牌,并使用MKL中的CPU调度器在非Intel计算机上启动较慢的代码。那么,如果国际商会检测到一个非英特尔CPU,为什么不能简单地禁用KMP_AFFINITY并恢复OMP_PROC_BIND呢?

有人知道这件事吗?或者有人能证实我的发现?

为了提供更多的上下文,我是商业计算流体力学程序的开发人员,不幸的是,我们将我们的程序与ICC OpenMP库连接起来,KMP_AFFINITY=scatter默认设置,因为在CFD中我们必须解决大规模稀疏线性系统,而这部分是非常内存限制的。我发现通过设置KMP_AFFINITY=scatter,我们的程序比程序在AMD机上所能达到的实际速度慢4X (当使用32个线程)。

更新:

现在,使用hwloc,我可以确认,KMP_AFFINITY=scatter实际上是在我的AMD线程程序3机器上执行“紧凑”操作。我已经附上了结果。我用16个线程运行我的CFD程序(由ICC2017构建)。OPM_PROC_BIND=spread可以在每个CCX中放置一个线程,以便充分利用L3缓存。Hwloc-ps -l -t提供:

在设置KMP_AFFINITY=scatter时,我得到了

我将尝试最新的ICC/Clang OpenMP运行时,看看它是如何工作的。

EN

Stack Overflow用户

回答已采纳

发布于 2020-10-18 15:35:09

TL;博士:不要使用KMP_AFFINITY。它不是便携式的。更喜欢OMP_PROC_BIND (它不能与KMP_AFFINITY同时使用)。您可以将它与OMP_PLACES混合起来,手动将线程绑定到内核。此外,应该使用numactl来控制内存通道绑定,或者更一般地控制NUMA效应。

长答案

线程绑定OMP_PLACES可用于将每个线程绑定到特定的核心(减少上下文切换和NUMA问题)。理论上,OMP_PROC_BINDKMP_AFFINITY应该正确地做到这一点,但在实践中,它们在某些系统上没有做到这一点。请注意,OMP_PROC_BINDKMP_AFFINITY是独占的选项:它们不应该一起使用(OMP_PROC_BIND是旧的KMP_AFFINITY环境变量的一个新的便携替代品)。当核心的拓扑从一台机器改变到另一台机器时,您可以使用hwloc工具获取OMP_PLACES所需的PU ids列表。更特别的是,hwloc-calc获得列表,hwloc-ls检查CPU拓扑。所有线程都应该分开绑定,这样就不可能移动。您可以使用hwloc-ps检查线程的绑定。

NUMA效应:AMD处理器是通过将多个CCX与高带宽连接(AMD )连接在一起来构建的。因此,AMD处理器是NUMA系统。如果不考虑到NUMA效应,则会导致性能显著下降。numactl工具旨在控制/减轻NUMA效应:可以使用--membind选项将进程绑定到内存通道,并且可以将内存分配策略设置为--interleave (如果进程是NUMA感知的,则设置为--localalloc )。理想情况下,进程/线程应该只对本地内存通道分配和第一次接触的数据工作。如果要在给定的CCX上测试配置,可以使用--physcpubind--cpunodebind

我的猜测是,在设置KMP_AFFINITY=scatter时,因错误的PU映射(可能来自操作系统错误、运行时错误或用户/管理设置错误),英特尔/Clang运行时运行时不会执行良好的线程绑定。可能是由于CCX (因为包含多个NUMA节点的主流处理器非常少见)。

在AMD处理器上,访问另一个CCX内存的线程通常要支付额外的巨大代价,因为数据通过(相当慢的)无限结构互连,并且可能由于它的饱和以及内存通道的饱和。我建议您不要信任OpenMP运行时的自动线程绑定(使用OMP_PROC_BIND=TRUE),而是手动执行线程/内存绑定,然后在需要时报告错误。

下面是一个生成命令行的示例,以便运行应用程序:numactl --localalloc OMP_PROC_BIND=TRUE OMP_PLACES="{0},{1},{2},{3},{4},{5},{6},{7}" ./app

PS:小心PU/核心ID和逻辑/物理ID。

票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64409563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档