并行文件名相似性比较



从中提供的C++代码开始http://matpalm.com/resemblance/jaccard_coeff/我正在努力以一种快速的方式比较文件名的相似性。到目前为止,我在我的Windows7(x64)上使用g++和-fopenmp开关成功地编译了"相似"代码。下面显示了代码的重要部分:

#pragma omp parallel num_threads(2)
{
    ofstream file(output_filename_for_thread().c_str());
    int window_finish = number_lines;
    #pragma omp for schedule(dynamic, 1000)
    for(int i=0;i<number_lines;i++) {
        int window_start = i+1;
        // compare each pair output high resemblances
        for (int j=window_start; j<window_finish; j++) {
            if (lines[i][5] == lines[j][5]){ 
            float resemblance = shingles_array[i]->resemblance_to(*shingles_array[j]);
            if (resemblance >= min_resemblance - 0.0001)
                file << lines[i] << "n"
                     << lines[j] << "n";
           }
        }
    }
    file.close();
}

与原始代码相比,我在这段代码中最大的变化是输出类似的文件名,而不是索引和分数。此外,我只想比较以同一个字母开头的文件名。问题的定义来了。当我只指定2个线程时,这段代码运行良好,但当我将线程数增加到3个或更多(最多8个)时,不知何故,程序执行提前完成,没有得到任何输出。如何进一步调试或更好地解决此问题?如果我能让这些代码在任意数量的线程中正常工作,那就太好了。我的初步测试表明,与Python版本相比,这个C++代码的速度大约快了10倍,当它在Python中的8个进程上运行时,在单个线程上的速度至少快了2倍。如有任何指导和意见,我们将不胜感激。

您有多个线程同时写入file。这充其量会导致数据竞争和未定义的行为。您需要同步对file的访问,或者将结果存储在线程本地容器中,组合这些结果,并在循环完成时生成输出。

最简单的解决方案是将文件写入操作放在OpenMP关键部分中,如下所示:

    // compare each pair output high resemblances
    for (int j=window_start; j<window_finish; j++) {
        if (lines[i][5] == lines[j][5]){ 
        float resemblance = shingles_array[i]->resemblance_to(*shingles_array[j]);
        if (resemblance >= min_resemblance - 0.0001) {
            #pragma omp critical
            {
            file << lines[i] << "n"
                 << lines[j] << "n";
            }
          }
       }
    }

请注意,这将在线程之间引入大量的同步,性能将受到影响。

最新更新