c – mbind返回EINVAL

我正在使用为以下问题numa+mbind+segfault提供的代码,每次调用mbind都会返回EINVAL.我怎样才能得到完全错误的东西?我问这个是因为EINVAL可以归还很多原因.

page_size = sysconf(_SC_PAGESIZE);
objs_per_page = page_size/sizeof(A[0]);
assert(page_size%sizeof(A[0])==0);
split_three=num_items/3;
aligned_size=(split_three/objs_per_page)*objs_per_page;
remnant=num_items-(aligned_size*3);
piece = aligned_size;

nodemask=1;
mbind(&A[0],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);

nodemask=2;
mbind(&A[aligned_size],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);

nodemask=4;
bind(&A[aligned_size*2+remnant],piece*sizeof(double),MPOL_BIND,
     &nodemask,64,MPOL_MF_MOVE);

在运行程序之后(通过在每次mbind调用之前将节点掩码分别更改为1,2和4)如下所示(作为Mats Petersson的答案).它有时会出现段错误,有时会运行良好.当它发生段错误时,dmesg如下:

Stack:
Call Trace:
mpol_new+0x5d/0xb0
sys_mbind+0x125/0x4f0
finish_task_switch+0x4a/0xf0
? __schedule+0x3cf/0x7c0
system_call_fastpath+0x16/0x1b
Code: ...
kmem_cache_alloc+0x58/0x130

解决方法:

查看Linux内核的源代码,您可以获得EINVAL:

>传入无效模式值.超出“不一致”的范围(同时使用静态和相对节点)
>无效的maxnode(>页面中的位数 – > x86上的> 32K).
> nodemask的各种其他问题.
>没有MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL
> start不是页面对齐的.
>当页面对齐=启动时启动len. [也就是说,你的len至少不是一个字节]
> start len<开始 - 即负长度.
> policy = MPOL_DEFAULT,节点不为空或NULL.
>引用来自源代码的注释“如果节点掩码为空(本地分配),则MPOL_PREFERRED不能与MPOL_F_STATIC_NODES或MPOL_F_RELATIVE_NODES一起使用.所有其他模式都需要指向非空节点掩码的有效指针.

我的猜测是在开始时不是页面对齐的.

这段代码适合我:

#include <numaif.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define ASSERT(x) do { if (!(x)) do_assert(#x,(long)(x), __FILE__, __LINE__); } while(0)

static void do_assert(const char *expr, long expr_int, const char *file, int line)
{
    fprintf(stderr, "ASSERT failed %s (%d) at %s:%d\n", 
        expr, expr_int, file, line);
    perror("Error if present:");
    exit(1);
}


int main()
{ 
    size_t num_items = 6156000;
    double *A = valloc(num_items * sizeof(double));
    ASSERT(A != NULL);
    int res;
    unsigned long nodemask;


    size_t page_size = sysconf(_SC_PAGESIZE);
    size_t objs_per_page = page_size/sizeof(A[0]);
    ASSERT(page_size%sizeof(A[0])==0);
    size_t split_three=num_items/3;
    size_t aligned_size=(split_three/objs_per_page)*objs_per_page;
    size_t remnant=num_items-(aligned_size*3);
    size_t piece = aligned_size;

    printf("A[0]=%p\n", &A[0]);
    printf("A[%d]=%p\n", piece, &A[aligned_size]);
    printf("A[%d]=%p\n", 2*piece, &A[2*piece]);


    nodemask=1;
    res = mbind(&A[0],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
    ASSERT(res ==0);
    nodemask=1;
    res = mbind(&A[aligned_size],piece*sizeof(double),MPOL_BIND,&nodemask,64,MPOL_MF_MOVE);
    ASSERT(res ==0);

    nodemask=1;
    res = mbind(&A[aligned_size*2],(piece+remnant)*sizeof(double),MPOL_BIND,
     &nodemask,64,MPOL_MF_MOVE);
    ASSERT(res == 0);
}

请注意,我在所有分配中使用“nodemask = 1”,因为我的机器中只有一个四核处理器,因此没有其他节点可以绑定 – 这也给出了EINVAL.我认为你实际上系统中有多个节点.

我还将“残余”从A []移动到最后一次mbind调用的剩余大小.

上一篇:linux – 如何禁用一个CPU


下一篇:.NET 动态脚本语言