0

test.fa.gz ファイルには、次のように複数の 4 行が含まれています。

@HWI-ST298:420:B08APABXX:3:1101:1244:2212 1:N:0:TCATTC
GGCAAGGCACTTACTTTACAGCTAAAGAAGTGCAGC
+
@@@FDFFDFHCFDACGHC<<CCFEHHFCCFCEE:C?

私がやりたいことは、OpenMP と並行して *.fq.gz ファイルを 4 行ごとに読み取ることです。コード ブローは正常にコンパイルできますが、正しくない結果が表示されることがあります。各 for ループで、getline() を 4 回使用してファイルを読み取りました。OpenMP が各 for ループで複数のジョブを処理する方法と、.gz ファイル ハンドルが OpenMP の for ループ間を移動する方法がわかりません。

インターネットと OpenMP ドキュメントでヘルプを検索しましたが、まだよくわかりません。そのため、どんな助けでも大歓迎です。

ありがとう、


#include <iostream>
#include <string>
#include <cstdlib>
#include <gzstream.h>
#include <omp.h>
using namespace std;

string reverseStrand (string seq);

int main (int argc, char ** argv) {
    const char* gzFqFile;
    unsigned int nReads;

    if (argc == 3) {
        gzFqFile = argv[1];
        nReads   = atoi(argv[2]); }
    else {
        printf("\n%s <*.fq.gz> <number_of_reads>\n", argv[0]);
        return 1; }

    igzstream gz(gzFqFile);
    string li, bp36, strand, revBp36;
    unsigned int i;
    #pragma omp parallel shared(gz) private(i,li,bp36,strand,revBp36)
    {
        #pragma omp for schedule(dynamic)
        for(i = 0;i < nReads;++i) {
            li      = "";
            bp36    = "";
            strand  = "";
            revBp36 = "";
            getline(gz,li,'\n');
            getline(gz,li,'\n');
            bp36 = li;
            getline(gz,li,'\n');
            strand = li;
            getline(gz,li,'\n');
            if(strand.compare("-") == 0) {
                revBp36 = reverseStrand(bp36);
            }
            cout << bp36 << " " << strand << " " << revBp36 << "\n";
        }
    }
    gz.close();
}
4

2 に答える 2

3

おそらく答えよりも拡張されたコメントのほうが多いかもしれませんが、とにかくここに行きます...

スレッド セーフであったとしてもgetline、OpenMP プログラムに複数のスレッドがあり、すべてが同じファイルを同時に読み取ろうとするのは、おそらく良い考えではありません。並列ファイル システムを使用していない限り (言及していないため、言及していないと思います)、単一の I/O チャネルでスレッドが互いに競合するプログラムを作成するリスクがあります。4 つのスレッドがそれぞれファイルの異なる部分を読み取り、すべてがディスク上の 1 つの読み取り/書き込みヘッドを使用している場合を考えてみましょう。ファイルの小さな部分を準ランダムに読み取る方法は、おそらく考えられる最も遅い方法です。

ファイル アクセスをクリティカル セクションにラップするという Haatschi の提案は、I/O アクセスを争う代わりに、スレッドがうまく連携して、それぞれが順番を丁寧に待つことを意味します。しかし、Haatschi が示唆するように、これによってファイルの読み取りが高速化される可能性は低く、(私の経験では) 速度が低下する可能性が高くなります。I/O 時間が重要でない場合は、これが適している可能性があります。

I/O 時間が気になる場合は、1 つのスレッドでファイルを読み取り、データの処理を並列化します。または、I/O リソースの競合を避けるためにクリティカル セクションを使用して、各スレッドがファイルからすべてのデータを一気に読み取るようにします。

于 2012-06-19T10:02:48.407 に答える
2

getline関数はスレッドセーフではありません。したがって、未定義の動作を取得せずに、異なるスレッドから同時に呼び出すことはできません。これを適切に行う唯一の方法は、各getline呼び出しの周りにクリティカルセクションを作成し、常に1つのスレッドだけが「gz」でgetlineを呼び出すようにすることです。ただし、コード例では、「gz」から行を読み取る以外にスレッドに対して行う作業があまりないため、複数のスレッドを使用すると高速化されるとは思えません。

于 2012-06-19T08:55:49.567 に答える