저는 파일에서 시퀀스를로드하고 처리해야하는 프로젝트에서 작업하고 있습니다. 많은 데이터를 다루고 있기 때문에 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"를 사용하여 세마포를 시뮬레이트하려했지만 충분하지 않다고 생각합니다. 또한 메모리가 아닌 코드 영역에 대한 액세스 만 보호하기 때문에 "임계"및 "원자"절이 여기에서 도움이 될 것이라고 생각하지 마십시오.
이 아이디어를 어떻게 해결할 수 있습니까? 이 코드를 재사용 할 계획이없는 경우
한 번에 하나의 스레드 만 대기열에 액세스 할 수 있도록해야합니다. 두 개가 동시에 대기열에서 제외하려고하면 대기열과 대기열에서 동시에 대기열에서 대기열에서 제거를 시도하면 대기열이 손상 될 수 있습니다. –