【问题标题】:efficient use of NUMA architecture高效使用 NUMA 架构
【发布时间】:2014-07-10 19:07:50
【问题描述】:

我正在编写一个占用大量 CPU 和内存的多线程 Java 程序。 该程序的目标是在图上执行一些算法。该程序在运行 linux 的 NUMA 机器上执行,我希望获得最佳性能。

为此,我为每个 NUMA 节点制作了多个图形副本,以便每个线程都能够访问本地内存上的图形。

本地内存分配部分已经通过在分配图的每个新副本之前设置亲和性来完成。这是用 jna 完成的,所以如果可能的话,我更愿意继续使用这个库而不是添加 jni 代码。

我的问题是如何检查工作线程在哪个核心上运行,以便从本地内存中进行读取?

我了解线程到内核的绑定在执行期间可能会发生变化。但是,内核尝试在所有时间片上在同一个 NUMA 节点上运行线程。因此,在大多数情况下,仅在开始时检查线程运行在哪个内核上才有效。

【问题讨论】:

  • 由于 NUMA 库的质量/支持不佳,即使在 C/C++ 中也很难做到这一点。
  • 我不需要专门的 NUMA 库。只是想知道线程在哪个核心上运行。从 core-id 我可以毫无问题地知道 NUMA 节点。
  • 我非常怀疑你可以用 Java 做到这一点。唯一真正的选择是 C++(我自己也是一名 Java 开发人员)。但对于 NUMA 架构及其上的并行处理,C++ 和 MPI 是唯一的选择。
  • Alexandros,您可能会惊讶于还有多少选择。 C、Python 和 Go 只是其他几种可以很好地利用 NUMA 系统的语言。它们中的每一个都有自己的同步和 IPC 选项,从 mmap 到管道到套接字到 SHMEM 和其他库,再到特定于语言的功能。如果您担心其中一些选项不包含用于确定您的 NUMA 拓扑的标准化功能,那可能是正确的,尽管man 7 numa 在 Linux 上有一些帮助。

标签: java multithreading memory-management numa


【解决方案1】:

你说的是线程亲和性。也许这会有所帮助。

Java thread affinity

如果没有涵盖它,您需要做的另一件事是使用本机代码来确定哪个核心位于哪个 numa 上。

【讨论】:

  • 我已经使用线程亲和性,在每个 NUMA 节点上制作图形的本地副本(如问题中所述)。在启动阶段,我可以使用线程关联运行。但我不想将整个并行算法绑定到特定的内核。我依赖的操作系统会比我提供更好的负载平衡。关于你回答的“本机代码”部分 - 这就是问题所在。
【解决方案2】:

我发现完成上述任务的最简单方法是运行 shell 命令并解析输出。

鉴于我知道当前线程的进程 id 和线程 id(可通过 jna 实现),我运行以下命令:

ps -p <pid> -L -o tid,psr | grep <tid>

结果是一行有两个数字,第一个是线程id,第二个是这个线程正在执行的核心id。

在一个循环中,我将线程关联设置到不同的内核,并检查了上述命令的输出。输出总是正确的。

【讨论】:

    【解决方案3】:

    原来有一个方法可以通过jna调用来获取想要的信息。 方法名称为:sched_getcpu。而完整的代码sn-p是这样的

    public interface CLibrary extends Library{
        public static final CLibrary INSTANCE = 
               (CLibrary) Native.loadLibrary("c", CLibrary.class);
        public int sched_getcpu() throws LastErrorException;
    }
    

    现在,当你制作时

    CLibrary.INSTANCE.sched_getcpu();
    

    您将获得当前线程正在运行的核心 id。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-09
      • 2021-12-10
      • 2012-10-21
      • 2012-12-16
      • 1970-01-01
      • 2023-04-03
      • 2017-04-29
      • 2020-08-08
      相关资源
      最近更新 更多