2012-09-21 3 views
-1

저는 파일에서 시퀀스를로드하고 처리해야하는 프로젝트에서 작업하고 있습니다. 많은 데이터를 다루고 있기 때문에 RAM에 저장할 수 없습니다. 그래서 하나의 스레드를 사용하여이 파일에서 데이터를로드하고 대기열에 한 스레드를 저장하면 대기열에 무언가가 있음을 감지하고 임시 파일로 언로드합니다.OpenMP에서 메모리 액세스의 경쟁 조건을 해결하는 방법은 무엇입니까?

이 작업을 수행하는 데 문제가 있습니다. 경주 조건이있는 것처럼 보입니다. 때로는 작동하지만 때로는 세그먼트 오류를 ​​반환합니다.

버그로 최소한의 코드 예제를 작성했습니다.

이 내 큐 코드입니다 : 내가 발견

Queue *f; 
int i; 
int end_flag; 
char *seq; 

f = create_queue(); 
end_flag = 0; 

#pragma omp parallel shared(f) shared(end_flag) 
{ 
    #pragma omp sections 
    { 
     #pragma omp section 
     { 
      FILE *tmp; 
      tmp = fopen("tmp","w"); 
      while(!end_flag){ 
       if(queue_size(f) > 0) 
        seq_to_file(dequeue(f),tmp); 
      } 

      fclose(tmp);  
     } 
     #pragma omp section 
     { 
      seq = (char*)malloc(21*sizeof(char)); 
      strcpy(seq,"ABCDEFGHIJKLMNOPQRST"); 

      for(i=0;i < NSEQS;i++) 
       enqueue(f,seq); 
      end_flag = 1; 
     } 
    } 
}  

일부 오류 :이 내 주요 코드

//#################### 
// STRUCTS 
//#################### 
struct queue_item{ 
    char *seq; 
    struct queue_item *prox;//Next element 
}; 
typedef struct queue_item QueueItem; 

struct Queue{ 
    QueueItem *first;//First element on queue 
    QueueItem *end;//Last element on queue 
    int size;//Queue size 
}; 
typedef struct Queue Queue; 

//#################### 

Queue* create_queue(){ 
    Queue *f; 
    f = (Queue*)malloc(sizeof(Queue)); 
    f->size = 0; 
    return f; 
} 

QueueItem* new_queue_item(char *seq){ 
    QueueItem* new; 
    int n; 

    n = strlen(seq); 
    new = (QueueItem*)malloc(sizeof(QueueItem)); 
    new->seq = (char*)malloc((n+1)*sizeof(char)); 

    strcpy(new->seq,seq); 

    return new; 
} 

void enqueue(Queue *f,char *seq){ 
    QueueItem* new; 
    new = new_queue_item(seq); 

    switch(f->size){ 
     case 0: 
      f->first = new; 
     break; 
     case 1: 
      f->end = new; 
      f->first->prox = f->end; 
     break; 
     default: 
      f->end->prox = new; 
      f->end = new; 
     break; 
    } 

    f->size = f->size + 1; 
    return; 
} 

char* dequeue(Queue *f){ 
    QueueItem *hold; 
    char *seq; 

    if(f->size > 0){ 
     hold = f->first; 
     seq = f->first->seq; 
     f->first = f->first->prox; 
     free(hold); 
     f->size--; 
    } 

    return seq; 
} 

int queue_size(Queue *f){ 
    return f->size; 
} 

void seq_to_file(char *seq,FILE *f){ 
    if(seq != NULL){ 
     fputs(seq,f); 
     free(seq); 
    } 
    return; 
} 

입니다

1 - new_queue_item에 malloc에 ​​오류가() 행 : new-> seq = (char *) malloc ((n + 1) * sizeof (char));

* glibc에 감지 */홈/페드로/보관/Programação/C/큐/fila_teste : 더블 무료 또는 (아웃) 손상 : 0x00000000006f3bd0 * 의 glibc 감지 /홈/페드로/보관/Programação/C/대기열/fila_teste :의 malloc(), (고속) 메모리 손상 : 0x00000000006f3b70 *

2 - new_queu_item에 malloc에 ​​에러() 라인 : 새로운 = (QueueItem *)의 malloc (sizeof 연산자 (QueueItem));

seq_to_file() 줄에 3 개의 공백 오류 : free (seq);

* glibc에 감지 */홈/페드로/보관/Programação/C/큐/fila_teste : 더블 무료 또는 (아웃) 손상 : 0x0000000000cdd3f0 *

는 GDB와 함께 확인 내가 가진 : (GDB) print * f $ 16 = {first = 0x0, end = 0x611180, size = 426}

이 세 번째 오류는 이것이 정말로 경쟁 조건이라고 생각하게 만듭니다.

"end_flag"를 사용하여 세마포를 시뮬레이트하려했지만 충분하지 않다고 생각합니다. 또한 메모리가 아닌 코드 영역에 대한 액세스 만 보호하기 때문에 "임계"및 "원자"절이 여기에서 도움이 될 것이라고 생각하지 마십시오.

이 아이디어를 어떻게 해결할 수 있습니까? 이 코드를 재사용 할 계획이없는 경우

+0

한 번에 하나의 스레드 만 대기열에 액세스 할 수 있도록해야합니다. 두 개가 동시에 대기열에서 제외하려고하면 대기열과 대기열에서 동시에 대기열에서 대기열에서 제거를 시도하면 대기열이 손상 될 수 있습니다. –

답변

1

, 당신은 다음을 사용할 수 있습니다 :

#pragma omp critical(queueLock)

이 지시문은 위의 예에서는, "이름"뮤텍스 "queueLock"역할을합니다. 여러분 모두가 공유 데이터를 사용하기 때문에 enqueue, dequeue 및 queue_size 함수에서 사용해야합니다.

이 코드를 다시 사용하려면 OpenMP 잠금 (omp_lock_t)에 대해 알아야합니다.

관련 문제