You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否查询当前线程所属的NUMA系统内存存储体?

NUMA节点信息获取方案(JVM + C/C++)

JVM 基于 OSHI 的实现

OSHI可先获取系统NUMA拓扑,但没有直接提供线程绑定NUMA节点的API,需结合JNI或底层系统调用实现:

  • 步骤1:枚举系统NUMA节点拓扑
    先通过OSHI获取全系统NUMA节点布局,了解每个节点关联的CPU和内存:

    import oshi.hardware.HardwareAbstractionLayer;
    import oshi.SystemInfo;
    import oshi.hardware.NumaNode;
    
    public class NumaInfo {
        public static void main(String[] args) {
            SystemInfo si = new SystemInfo();
            HardwareAbstractionLayer hal = si.getHardware();
            for (NumaNode node : hal.getNumaNodes()) {
                System.out.printf("NUMA节点%d: 内存大小%.2fGB, 关联CPU核心:%s%n",
                        node.getNodeNumber(),
                        node.getMemory() / (1024.0 * 1024.0 * 1024.0),
                        node.getProcessorIds());
            }
        }
    }
    
  • 步骤2:获取当前线程绑定的NUMA节点
    通过JNI调用C代码实现底层查询,示例如下:
    C代码片段(编译为动态链接库):

    #include <jni.h>
    #include <numa.h>
    #include <pthread.h>
    
    JNIEXPORT jint JNICALL Java_com_example_NumaInfo_getCurrentThreadNumaNode(JNIEnv *env, jobject obj) {
        cpu_set_t cpuset;
        CPU_ZERO(&cpuset);
        pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    
        for (int i = 0; i < CPU_SETSIZE; i++) {
            if (CPU_ISSET(i, &cpuset)) {
                int node = numa_node_of_cpu(i);
                if (node >= 0) {
                    return node;
                }
            }
        }
        return -1;
    }
    

    Java端调用代码:

    public class NumaInfo {
        static {
            System.loadLibrary("numahelper");
        }
    
        private native int getCurrentThreadNumaNode();
    
        public static void main(String[] args) {
            NumaInfo info = new NumaInfo();
            int node = info.getCurrentThreadNumaNode();
            if (node >= 0) {
                System.out.printf("当前线程所属NUMA节点: %d%n", node);
            } else {
                System.out.println("系统不支持NUMA或无法获取节点信息");
            }
        }
    }
    

C/C++ 实现方案

Linux 平台(依赖libnuma)

直接调用libnuma接口获取线程亲和CPU对应的NUMA节点:

#include <numa.h>
#include <pthread.h>
#include <iostream>

int getCurrentThreadNumaNode() {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

    for (int cpu = 0; cpu < CPU_SETSIZE; ++cpu) {
        if (CPU_ISSET(cpu, &cpuset)) {
            int node = numa_node_of_cpu(cpu);
            if (node != -1) {
                return node;
            }
        }
    }
    return -1;
}

int main() {
    if (!numa_available()) {
        std::cerr << "系统不支持NUMA" << std::endl;
        return 1;
    }

    int node = getCurrentThreadNumaNode();
    if (node >= 0) {
        std::cout << "当前线程所属NUMA节点: " << node << std::endl;
    } else {
        std::cout << "无法获取当前线程的NUMA节点" << std::endl;
    }
    return 0;
}

编译命令:g++ numa_test.cpp -o numa_test -lnuma

Windows 平台

通过Windows API获取线程亲和CPU,再映射到NUMA节点:

#include <windows.h>
#include <iostream>

int getCurrentThreadNumaNode() {
    HANDLE hThread = GetCurrentThread();
    GROUP_AFFINITY groupAffinity;
    if (!GetThreadGroupAffinity(hThread, &groupAffinity)) {
        return -1;
    }

    USHORT cpuMask = groupAffinity.Mask;
    int targetCpu = 0;
    while ((cpuMask >>= 1) != 0) {
        targetCpu++;
    }

    ULONG nodeNumber;
    if (GetNumaProcessorNode(targetCpu, &nodeNumber)) {
        return static_cast<int>(nodeNumber);
    }
    return -1;
}

int main() {
    int node = getCurrentThreadNumaNode();
    if (node >= 0) {
        std::cout << "当前线程所属NUMA节点: " << node << std::endl;
    } else {
        std::cout << "无法获取当前线程的NUMA节点或系统不支持NUMA" << std::endl;
    }
    return 0;
}

注意事项

  • 所有方法仅在支持NUMA的硬件上有效,否则返回-1或提示不支持。
  • JVM线程池中的线程可能被复用,需在任务执行时重新获取NUMA节点。
  • Linux下需确保libnuma库已安装,Windows需使用Windows 10/Server 2016及以上版本。

内容的提问来源于stack exchange,提问作者Dave11ar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 03:24:22