从http://matpalm.com/resemblance/jaccard_coeff/中提供的C ++代码开始,我正在努力快速比较文件名相似性。到目前为止,我设法得到"相似性"使用g ++和-fopenmp开关在我的Windows 7(x64)上编译好的代码。下面显示了代码的基本部分:
#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倍。任何指导和评论将不胜感激。
答案 0 :(得分:0)
您有多个帖子同时写入file
。这最多导致数据竞争和未定义的行为。您需要同步对file
的访问权限或将结果存储在线程本地容器中,组合它们,并在循环完成时生成输出。
答案 1 :(得分:0)
最简单的解决方案是将文件写入操作放在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";
}
}
}
}
请注意,这将在线程之间引入大量同步,性能将受到影响。