5

次の質問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 呼び出しの前に nodemask をそれぞれ 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
4

1 に答える 1

4

Linux カーネルのソースを見ると、次の EINVAL を取得できます。

  • 無効なモード値を渡しています。「矛盾」の範囲外 (静的ノードと相対ノードの両方を同時に使用)
  • 無効な maxnode (> ページ内のビット数 -> x86 では 32K)。
  • ノードマスクに関するその他のさまざまな問題。
  • いずれかを持っていないMPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL
  • startページ揃えではありません。
  • start+lenpage-aligned = start の場合。[つまり、あなたの len は少なくとも 1 バイトではありません]
  • start+len< start - つまり、負の長さです。
  • policy = MPOL_DEFAULTandnodesは空ではありません or NULL.
  • ソースからのコメントを引用 「ノードマスクが空の場合 (ローカル割り当て)、MPOL_PREFERRED を MPOL_F_STATIC_NODES または MPOL_F_RELATIVE_NODES と一緒に使用することはできません。他のすべてのモードでは、空でないノードマスクへの有効なポインターが必要です。

私の推測でstartは、ページが整列されていません。

このコードは私のために働きます:

#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);
}

私のマシンにはクアッドコアプロセッサが1つしかないため、すべての割り当てで「nodemask = 1」を使用していることに注意してください。そのため、バインドする他のノードはありません-これもEINVAL. システムには実際に複数のノードがあると思います。

また、最後の呼び出しのサイズA[]から「残り」を移動しました。piece+remnantmbind

于 2013-01-27T13:49:47.450 に答える