将每个线程的内存页在NUMA架构(Move memory pages per-thread in N

2019-10-18 10:37发布

我有一个2个问题:

(一)假设线程X在CPU运行Y.是否可以使用系统调用migrate_pages - 甚至更好move_pages(或其libnuma包装) - 移动其中Y连接在被X到节点相联系的网页?

这个问题棱,因为这两个系统调用的第一个参数是PID(我需要每个线程的方法对于一些研发我做)

(二)对(我)肯定答复的情况下,我怎样才能使用的一些线索中的所有网页? 我的目标是,将包含与他们的记忆页数组M []对于为例...如何“链接”的数据结构的页面(S),对使用上述系统调用的缘故?

一个额外的信息:我用C与并行线程。 提前致谢 !

Answer 1:

你想用更高级别的libnuma接口,而不是低层次的系统调用。

该libnuma库提供了一个简单的编程接口,以Linux内核支持的NUMA(非一致内存访问)政策。 在NUMA架构某些内存区域比别人不同的延迟和带宽。

可用策略是页交织(即,分配在从所有循环的方式,或一个子集,该系统上的节点的),优选的节点分配(即,优选在特定节点上分配),本地分配(即,分配在其上的任务正在执行仅关于特定节点的节点),或分配上(即,分配的可用节点的一些子集)。 也可以绑定任务特定节点。

该手册页低水平numa_*系统调用警告你远离使用它们:

与链接-lnuma获得系统调用的定义。 libnuma和所需<numaif.h>报头是在可用numactl包。

但是,应用程序不应该直接使用这些系统调用。 取而代之的是,通过所提供的更高级别的接口numa(3)中的函数numactl包建议。 所述numactl包可在<ftp://oss.sgi.com/www/projects/libnuma/download/> 该软件包还包括在一些Linux发行版。 一些分布包括在分开的发展库和头numactl-devel包。



Answer 2:

下面是我使用的钉扎线到一个CPU和移动堆栈到相应的NUMA节点的代码(略适合于移除别处定义一些常量)。 请注意,我通常先创建线程,然后调用SetAffinityAndRelocateStack()从内螺纹下方。 我觉得这是更好的,然后试图创建自己的堆栈,因为堆有在增长的情况下达到的底部特别支持。

该代码也可以适用于从外面新创建的线程上运行,但是这可能会引起竞争条件(例如,如果线程执行I / O到它的堆栈),所以我不会推荐它。

void* PreFaultStack()
{
    const size_t NUM_PAGES_TO_PRE_FAULT = 50;
    const size_t size = NUM_PAGES_TO_PRE_FAULT * numa_pagesize();
    void *allocaBase = alloca(size);
    memset(allocaBase, 0, size);
    return allocaBase;
}

void SetAffinityAndRelocateStack(int cpuNum)
{
    assert(-1 != cpuNum);
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpuNum, &cpuset);
    const int rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    assert(0 == rc);

    pthread_attr_t attr;
    void *stackAddr = nullptr;
    size_t stackSize = 0;
    if ((0 != pthread_getattr_np(pthread_self(), &attr)) || (0 != pthread_attr_getstack(&attr, &stackAddr, &stackSize))) {
        assert(false);
    }

    const unsigned long nodeMask = 1UL << numa_node_of_cpu(cpuNum);
    const auto bindRc = mbind(stackAddr, stackSize, MPOL_BIND, &nodeMask, sizeof(nodeMask), MPOL_MF_MOVE | MPOL_MF_STRICT);
    assert(0 == bindRc);

    PreFaultStack();
    // TODO: Also lock the stack with mlock() to guarantee it stays resident in RAM
    return;
}


文章来源: Move memory pages per-thread in NUMA architecture