2012-07-02 3 views
5

가끔씩 실행되는 병렬 프로그램이 있는데 가끔씩 세분화 오류가 발생합니다. 실행 파일은 3 개의 스레드로 실행되도록 강제 실행될 때 정상적으로 실행됩니다 (기본적으로 직렬로 연결된 단일 스레드로 실행됩니다). 그러나 다른 스레드 값으로 실행해야 할 경우 세그먼트 화 오류가 발생합니다. 여기에 시나리오는 다음과 같습니다병렬 프로그래밍의 흥미로운 사례

main.c에서 주요 기능 내부 : 나는 t을했다

int bf_dup_eleminate_read (const bloom_filter *bf, FILE *fp, int j) 
{ 
    //some stuff here 
    printf ("before while loop. j is %d ** workder id: **********%d***********\n", j, __cilkrts_get_worker_number()); 
    while (/*somecondition*/) 
    {/*some stuff*/} 
    //some stuff 
} 

: bloom-filter.c 파일에서

int bf_dup_eleminate (const bloom_filter *bf, const char *file_name, int j) 
{ 
    int count=-1; 
    FILE *fp = fopen (file_name, "rb"); 
    if (fp) 
    { 
     count = bf_dup_eleminate_read (bf, fp, j); 
     fclose (fp); 
    } 
    else 
    { 
     printf ("Could not open file\n"); 
    } 
    return count; 
} 

bf_dup_eleminate_read :

cilk_for (line_count = 0; line_count != no_of_lines ; ++line_count) 
{ 
    //some stuff here 
    for (j=line_count+1; j<no_of_lines; ++j) 
    { 
     //some stuff here 
     final_result[line_count][j] = bf_dup_eleminate (table_bloom[line_count], file_names[j], j); 
     //some stuff here 
    } 
    //some stuff here 
} 

bf_dup_eleminate 기능 파일 bloom-filter.c에서

ID | Problem       | Sources  
P1 | Unhandled application exception | bloom-filter.c 

및 호출 스택은 다음과 같습니다 : intel inspector에서보고 자신의 오류는

마찬가지로
exec!bf_dup_eleminate_read - bloom-filter.c:550 
exec!bf_dup_eleminate - bloom-filter.c:653 
exec!__cilk_for_001.10209 - main.c:341 

gdb도 동일한 위치에 오류를보고하고있다 : 이제

gdb이 있음을 알려줍니다 다음 오류가 있습니다.

0x0000000000406fc4 in bf_dup_eleminate_read (bf=<error reading variable: Cannot access memory at address 0x7ffff7edba58>, fp=<error reading variable: Cannot access memory at address 0x7ffff7edba50>, j=<error reading variable: Cannot access memory at address 0x7ffff7edba4c>) at bloom-filter.c:536

다음과 같이

이제 내 블룸 필터가이 할당에 대한

struct bloom_filter 
{ 
    int64_t m;  //size of bloom filter. 
    int32_t k;  //number of hash functions. 
    uint8_t *array; 
    int64_t no_of_elements_added; 
    int64_t expected_no_of_elements; 
}; 

메모리로 정의 된 structture입니다 :

bloom_filter *bf = (bloom_filter *)malloc(sizeof(bloom_filter)); 
    if (bf != NULL) 
    { 
     bf->m = filter_size*8;  /* Size of bloom filter */ 
     bf->k = num_hashes; 
     bf->expected_no_of_elements = expected_no_of_elements; 
     bf->no_of_elements_added = (int64_t)0; 
     bf->array = (uint8_t *)malloc(filter_size); 
     if (bf->array == NULL) 
     { 
      free(bf); 
      return NULL; 
     } 
    } 

가 63,210

Line 536int bf_dup_eleminate_read (const bloom_filter *bf, FILE *fp, int j)

추가 세부 사항입니다 bloom_filter의 복사본 하나와 각 스레드가 액세스해야합니다. 같은 (내가 독서 만 바꾸는 것은 아니다).

내가 지난 4 일간 여기에 갇혀 있기 때문에 아무도 도와주지 않을 수 있습니다. 그리고 나는 탈출구를 생각할 수 없습니다. 최악의 부분은 3 개의 스레드를 실행 중입니다 !!!

참고 : cilk_for는 cilk로 스레드를 생성하는 키워드 일뿐입니다.

+0

bloom_filter 할당에 결함이있는 것처럼 보입니다. bf-> array에 대해 malloc()을 수행 한 후 bf-> array 대신 bf의 NULL을 확인합니다. 이것은 당신의 문제가 아니며, 내가 알아 차린 것입니다. –

+0

나는 그것이 실수 였다는 것을 인정하지만 업데이트 된 코드를 실행했는데 제대로 작동하지 않았다. 그런 오류에 대한 다른 가능성을 제안 해주십시오. –

+0

당신이 속하지 않은 메모리에 액세스하는 중에 오류가 발생합니다. 다른 즉각적인 변경 사항은 cilk_for() 조건문에 나와 있습니다. line_count 대신 no_of_lines를 사용합니다. no_of_lines가 실제로 실행될 동시 스레드 수라고 가정 할 수 있습니까? 작업의 일부분을 수행하기 위해 bf_dup_eleminate()를 사용할 다수의 쓰레드로 작업을 나눠서 처리하는 것으로 보이지만, final_result 테이블을 인덱싱하는 방법에는 코드가 의미가 없습니다. –

답변

8

디버거는이 같은 오류 알려줍니다

0x0000000000406fc4 in bf_dup_eleminate_read (
    bf=<error reading variable: Cannot access memory at address 0x7ffff7edba58>, 
    fp=<error reading variable: Cannot access memory at address 0x7ffff7edba50>, 
    j=<error reading variable: Cannot access memory at address 0x7ffff7edba4c> 
) at bloom-filter.c:536 

536: int bf_dup_eleminate_read (const bloom_filter *bf, FILE *fp, int j) 

는 보통 (기능 "프롤로그"라고 함) 함수 진입 코드가 충돌을 나타냅니다합니다. 즉, 스택이 손상되어 CPU가 3 개의 로컬 변수의 주소를 계산하고 스택에 공간을 할당 할 때 충돌이 발생합니다.

  1. 것은 당신이 어떤 오버런 있지 않은지 확인 : 내가 확인 또는 (어느 것도 작동하도록 보장하고 있으며, 일부는 그 중 이미 시도 할 수있다)이 오류를 수정하려고 할

    것들 프로그램의 다른 부분에서 선언 한 지역 변수에 의해 사용 된 공간.

  2. 로컬 변수로 선언 된 포인터에 쓰지 말고 프로그램의 다른 부분에있는 함수에서 리턴 한 포인터인지 확인하십시오.

  3. 선언 한 모든 로컬 변수를 처리하기에 충분한 스레드 공간이 각 스레드에 있는지 확인하십시오. 대형 스택 기반 버퍼를 선언 하시겠습니까? 기본 스레드 별 스택 크기는 컴파일러 설정에 따라 다르며이 경우 cilk 라이브러리에 따라 달라집니다. 컴파일 시간에 스레드 당 스택 크기를 늘려 충돌이 사라지는지 확인하십시오.

위의 사항 중 하나는 문제의 원인을 좁혀 야합니다.

+1

Thax man !! 너는 최고야. 나는 지난 5 일 동안 여기에 갇혀 있었고 나는 모든 것을 시도했다. 나는 3 개의 새로운 소프트웨어를 배웠고 내가 할 수있는 모든 것을했지만 도움이되지 못했다. 그것은 세 번째 포인트 때문이었고 충돌은 사라졌습니다. :). 다시 한번 고마워요 –

+1

@Aman, 나는 비슷한 상황에 처해있었습니다. aps2012, 당신은 나에게 많은 좌절감을 안겨주었습니다 :) 함수 - 로컬에서 글로벌 범위로 몇 개의 큰 배열을 이동 시키면 문제가 해결되었습니다 : D. 함수 선언에서 segfaults를 얻고있었습니다. –