如何与OpenMP并行读取每四行.gz文件?

时间:2012-06-19 08:46:30

标签: for-loop openmp filehandle gz

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

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

我想要做的是与OpenMP并行读取每四行* .fq.gz文件。代码打击可以成功编译,但有时会显示不正确的结果。在每个for循环中,我使用4次getline()来读取文件。我不确定OpenMP将如何处理每个for循环中的多个作业以及.gz文件句柄如何在forMP循环之间移动。

我搜索了互联网和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();
}

2 个答案:

答案 0 :(得分:3)

更多的是延伸评论而不是答案,但无论如何都要进行......

即使getline是线程安全的,在OpenMP程序中让多个线程同时尝试同时读取同一个文件也许不是一个好主意。除非你有一个并行文件系统(因为你没有提到它,我认为你没有),你冒着编写一个程序的风险,在这个程序中,线程为单个I / O通道互相争斗。考虑4个线程的情况,每个线程使用磁盘上的1个读/写磁头读取文件的不同部分。准随机读取文件的小位可能是您能想到的最慢的方法。

Haatschi建议将文件访问包装在一个关键部分,这只是意味着不是为I / O访问而战,线程一起玩得很好,每个人都礼貌地轮流等待。但是,正如Haatschi所说,这不太可能导致文件阅读的任何加速,更有可能(根据我的经验)导致减速。如果I / O时间不重要,这可能是一种方法。

如果您关心I / O时间,那么要么在一个线程中读取文件并且并行处理数据;或者,让每个线程从文件中读取所有数据,使用关键部分来避免争用I / O资源

答案 1 :(得分:2)

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