从中提供的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";
}
}
}
}
请注意,这将在线程之间引入大量的同步,性能将受到影响。