使用mbind在NUMA系统中移动页面

时间:2012-11-30 15:30:47

标签: c linux numa

我试图了解Linux上的numa(3)库。

我分配了一个大型数组(许多GB内存)。在随机NUMA节点上运行的线程写入它,因为这些页面在随机NUMA内存节点上出现故障(默认NUMA策略)。

在线程计算结束时,我有一个单线程作业来总结结果。为此,我首先压缩数组,删除大量元素,然后将剩余部分移动到主线程的NUMA节点。

move_pages系统调用不适合作业,因为它需要每个页面的数组条目 - 开销太大。

文档不清楚是否可以强制numa_tonode_memory移动故障内存。

所以,我看到的唯一方法是将mbindMPOL_MF_MOVE一起使用,但我无法理解创建一个正确的nodemask参数(或其他内容失败) 。就我而言:

#define _GNU_SOURCE
#include <stdlib.h>
#include <sched.h>
#include <numa.h>
#include <numaif.h>

int master_node;
nodemask_t master_nodemask;

// initializer
// has to be called from master/main thread
void numa_lock_master_thread() {
    int curcpu = sched_getcpu();
    if (curcpu >= 0) {
        // master_node = numa_node_of_cpu(curcpu);
        numa_run_on_node(master_node = numa_node_of_cpu(curcpu));
        if (master_node >= 0) {
            struct bitmask * bindmask = numa_bitmask_alloc(numa_num_possible_nodes());
            numa_bitmask_clearall(bindmask);
            numa_bitmask_setbit(bindmask, master_node);
            copy_bitmask_to_nodemask(bindmask, &master_nodemask);
            numa_bitmask_free(bindmask);
        }
    } else { // has never failed before
        perror("sched_getcpu");
    }
}

static inline void numa_migrate_pages_to_master_node(void * addr, unsigned long len) {
    if (master_node < 0)
        return;

    if ( mbind(   addr
                , len
                , MPOL_BIND
                , master_nodemask.n
                , numa_max_node()
                , MPOL_MF_MOVE)) {
        perror("mbind");
    }

}

来自/usr/include/numa.h

typedef struct {
        unsigned long n[NUMA_NUM_NODES/(sizeof(unsigned long)*8)];
} nodemask_t;

有时我得到mbind: Bad address,有时调用会成功,但后续的内存访问会产生SIGSEGV

addr始终是

返回的有效指针
mmap(NULL, (num_pages) * sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | (flags), -1, 0);

len是页面对齐的。

如何使用尽可能少的系统调用来完成此工作,并且没有move_pages带来的大量开销?

nodemask设置mbind参数的正确方法是什么?

0 个答案:

没有答案