0

test.fa.gz 文件包含多个 4 行作为打击:

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

我想要做的是与 OpenMP 并行读取每四行 *.fq.gz 文件。code blow 可以编译成功,但有时会显示不正确的结果。在每个 for 循环中,我使用了 4 次 getline() 来读取文件。我不确定 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 时间,则可以在一个线程中读取文件并并行处理数据;或者,让每个线程一次性从文件中读取所有数据,使用临界区来避免争用 I/O 资源

于 2012-06-19T10:02:48.407 回答
2

getline 函数不是线程安全的。因此,您不能同时从不同的线程调用它而不会得到未定义的行为。正确执行此操作的唯一方法是在每个 getline 调用周围创建关键部分,强制任何时候只有一个线程在“gz”上调用 getline。但是,在您的代码示例中,我怀疑使用多个线程是否会有任何加速,因为除了从“gz”读取行之外,线程没有太多工作要做。

于 2012-06-19T08:55:49.567 回答