【发布时间】:2012-11-08 01:27:55
【问题描述】:
我们刚买了一台 32 核的 Opteron 机器,我们得到的加速有点令人失望:超过 24 个线程,我们根本看不到加速(实际上总体上变慢了),大约 6 个线程后它变得明显低于-线性。
我们的应用程序对线程非常友好:我们的工作分解为大约 170,000 个小任务,每个小任务都可以单独执行,每个任务需要 5-10 秒。它们都从同一个大小约为 4Gb 的内存映射文件中读取。他们偶尔会对其进行写入,但每次写入可能需要 10,000 次读取 - 我们只是在 170,000 个任务的每一个结束时写入一点数据。写入受锁定保护。分析表明锁不是问题。每个线程在非共享对象中使用大量 JVM 内存,它们对共享 JVM 对象的访问很少,其中只有一小部分访问涉及写入。
我们在启用了 NUMA 的 Linux 上使用 Java 进行编程。我们有 128Gb 内存。我们有 2 个 Opteron CPU(型号 6274),每个 CPU 有 16 个内核。每个 CPU 有 2 个 NUMA 节点。在 Intel 四核(即 8 核)上运行的相同作业几乎可以线性扩展到 8 个线程。
我们已尝试将只读数据复制为每个线程一个,希望大多数查找可以在 NUMA 节点本地进行,但我们观察到这样做并没有加速。
对于 32 个线程,“top”显示 CPU 的 74%“us”(用户)和大约 23%“id”(空闲)。但是没有睡眠,几乎没有磁盘 i/o。使用 24 个线程,我们得到 83% 的 CPU 使用率。我不确定如何解释“空闲”状态 - 这是否意味着“等待内存控制器”?
我们尝试打开和关闭 NUMA(我指的是需要重新启动的 Linux 级别设置),但没有发现任何区别。启用 NUMA 后,“numastat”仅显示大约 5% 的“分配和访问未命中”(95% 的缓存未命中发生在 NUMA 节点本地)。 [编辑:] 但是添加“-XX:+useNUMA”作为 java 命令行标志给了我们 10% 的提升。
我们的一个理论是我们正在最大限度地使用内存控制器,因为我们的应用程序使用大量 RAM,并且我们认为存在大量缓存未命中。
我们可以做些什么来 (a) 加速我们的程序以接近线性可扩展性,或 (b) 诊断正在发生的事情?
另外:(c) 我如何解释“top”结果——“idle”是否意味着“blocked on memory controllers”? (d) Opteron 与 Xeon 的特性有什么不同?
【问题讨论】:
-
没有任何适用于 Java 的硬件级分析器吗?如果您的代码是用 C、C++、Fortran 或其他编译语言编写的,我会向您指出
likwid或PAPI之类的东西,以便获得硬件计数器读数。请注意,与至强不同,Bulldozer 的每对内核共享大量资源——指令解码器、L1 指令缓存和 L2 缓存、FP 调度程序、2 个 FMAC/AVX 引擎等。那么每个 Bulldozer 处理器本身也是一个 NUMA 设备——它基本上是一个包中的两个处理器,它们之间有一个 HT 链接。
标签: parallel-processing cpu multicore numa