2013-01-27 3 views
4

Я использую код, представленный по следующему вопросу numa+mbind+segfault, каждый вызов mbind возвращает EINVAL. Как я могу получить то, что точно неправильно? Я спрашиваю об этом, потому что EINVAL можно вернуть по многим причинам.mbind возвращает 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); 

После запуска программы (путем изменения nodemask перед каждым вызовом mbind 1,2 и 4 соответственно), показанной ниже (в качестве ответа от Матса Петерсона). Иногда это происходит, а иногда и отлично. Когда 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 
+0

Похоже, что я попал в ядро. Не знаете, почему - какое точное ядро ​​вы используете? Боюсь, я не уверен, что это легко исправить. Ваша система в целом стабильна и работает хорошо, да? –

+0

@MatsPetersson Это Ubuntu 12.10. Linux 3.5.0-19-generiC# 30, x86_64. Благодарю. – tiki

+0

Он выглядит как соответствующий код в 3.5 (http://lxr.linux.no/#linux+v3.5/mm/slub.c#L2305) и 3.7.4 (http://lxr.linux.no /#linux+v3.7.4/mm/slub.c#L2317) несколько изменился, но не значительно. Конечно, любая ошибка может быть в нескольких сотнях строк кода до вызова kmem_cache_alloc. Я не могу понять, где это будет неправильно. –

ответ

2

Глядя на источнике ядра Linux, вы можете получить EINVAL для:

  • переходящих в недопустимом значении режима. Либо вне диапазона «непоследовательных» (с одновременным использованием как статических, так и относительных узлов)
  • Недопустимый maxnode (> количество бит на странице -> 32K на x86).
  • Различные другие проблемы с nodemask.
  • Не имеет одного из MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL
  • start не выровнено по странице.
  • start+len при выводе на страницу = начало. [т. е. ваш len не является по крайней мере одним байтом]
  • start+len < start - то есть отрицательная длина.
  • Политика = MPOL_DEFAULT и nodes не является пустым или NULL.
  • процитировать комментарий от источника «MPOL_PREFERRED не может быть использована с MPOL_F_STATIC_NODES или MPOL_F_RELATIVE_NODES если nodemask пуст (местное размещение). Все остальные режимы требуют действительный указатель на непустой nodemask.

Мое предположение было бы на 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); 
} 

Обратите внимание, что я использую «nodemask = 1» на всех распределений, так как я получил только один четырехъядерный процессор процедура essor в моей машине, поэтому никакие другие узлы, к которым нужно привязываться, - это также дает EINVAL. Я полагаю, у вас на самом деле есть несколько узлов в вашей системе.

Я также переместил «остаток» от A[] до piece+remnant размер для последних mbind звонок.

+0

Я запускал его для РАЗМЕР 6156000, я получаю кусок = 2051584, aligned_size = 2051584, а остаток = 1248. Благодарю. – tiki

+0

Итак, давайте вычислим это: 6156000 - 769500 ​​удваивается.Каждая группа должна иметь 256500 удвоений. Но это не ровное число страниц. 256500 есть. Это 2048000. Это означает, что второй запуск не будет выровнен при использовании параметра aligned_size. Можете ли вы вставить вычисления, чтобы получить aligned_size и остаток в своем вопросе, пожалуйста. –

+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;" Благодарю. – tiki

Смежные вопросы