-1

私は、ファイルからギガバイトのシーケンスをロードして処理する必要があるプロジェクトに取り組んでいます。大量のデータを扱っているため、RAMに保存できません。したがって、1つのスレッドを使用してこのファイルからデータをロードし、キューに保存し、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;
}

これは私のメインコードです

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

私が検出したいくつかのエラー:

1-new_queue_item()行のmallocエラー:new-> seq =(char *)malloc((n + 1)* sizeof(char));

*glibcが検出されました* /home / pedro /Dropbox/Programação/C/ Queue / fila_teste:ダブルフリーまたは破損(出力):0x00000000006f3bd0 * glibcが検出されました/ home / pedro /Dropbox/Programação/C/ Queue / fila_teste:malloc():メモリ破損(高速):0x00000000006f3b70 *

2-new_queu_item()行のmallocエラー:new =(QueueItem *)malloc(sizeof(QueueItem));

3-seq_to_file()行のフリーエラー:free(seq);

*glibcが検出されました* /home / pedro /Dropbox/Programação/C/ Queue / fila_teste:ダブルフリーまたは破損(出力):0x0000000000cdd3f0 *

gdbで確認すると、次のようになります。(gdb)print * f $ 16 = {first = 0x0、end = 0x611180、size = 426}

この3番目のエラーにより、これは実際には競合状態の状況であると思います。

「end_flag」でセマフォをシミュレートしようとしましたが、十分ではないと思います。また、「クリティカル」句と「アトミック」句は、メモリではなくコード領域へのアクセスのみを保護するため、ここで役立つとは思わないでください。

この問題を解決する方法はありますか?

4

1 に答える 1

1

このコードを再利用する予定がない場合は、次を使用できます。

#pragma omp critical(queueLock)

このディレクティブは、上記の例では「名前付き」ミューテックス「queueLock」として機能します。この場合、enqueue、dequeue、queue_size関数で使用する必要があります。これらはすべて、共有データを使用するためです。

このコードを再利用する場合は、OpenMPロックについて学ぶ必要があります(omp_lock_t)。

于 2012-09-21T22:16:55.987 に答える