我们刚刚购买了一台 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 节点。在英特尔四核(即 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)我如何解释“顶部”结果-“空闲”是否意味着“在内存控制器上被阻塞”?(d) Opteron 与 Xeon 的特性有什么不同吗?