尝试并行化算法时遇到了一些问题。目的是对100x100矩阵进行一些修改。当我在没有openMP的情况下运行算法时,一切都在大约34-35秒内顺利运行,当我在2个线程上并行化时(我需要它只有2个线程)它会下降到22秒,但是输出是错误的,我认为它是我无法解决的同步问题。
以下是代码:
for (p = 0; p < sapt; p++){
memset(count,0,Nc*sizeof(int));
for (i = 0; i < N; i ++){
for (j = 0; j < N; j++){
for( m = 0; m < Nc; m++)
dist[m] = N+1;
omp_set_num_threads(2);
#pragma omp parallel for shared(configurationMatrix, dist) private(k,m) schedule(static,chunk)
for (k = 0; k < N; k++){
for (m = 0; m < N; m++){
if (i == k && j == m)
continue;
if (MAX(abs(i-k),abs(j-m)) < dist[configurationMatrix[k][m]])
dist[configurationMatrix[k][m]] = MAX(abs(i-k),abs(j-m));
}
}
int max = -1;
for(m = 0; m < Nc; m++){
if (dist[m] == N+1)
continue;
if (dist[m] > max){
max = dist[m];
configurationMatrix2[i][j] = m;
}
}
}
}
memcpy(configurationMatrix, configurationMatrix2, N*N*sizeof(int));
#pragma omp parallel for shared(count, configurationMatrix) private(i,j)
for (i = 0; i < N; i ++)
for (j = 0; j < N; j++)
count[configurationMatrix[i][j]] ++;
for (i = 0; i < Nc; i ++)
fprintf(out,"%i ", count[i]);
fprintf(out, "\n");
}
其中:sapt = 100; 计数 - &gt;它是一个向量,它包含了我在每一步中所拥有的矩阵的每个元素的数量;
(EX:count[1] = 60
- &gt;我的矩阵中有'1'元素60次,依此类推)
dist --> vector
保持距离元素i的最大距离,j表示将值K表示为元素k,m为相同值K.
(EX:dist[1] = 10
- &gt;从值1的元素到值1的最远元素的距离<)
然后我在输出文件中写下了东西,但是输出错误了。
答案 0 :(得分:1)
如果我在这行中正确理解了您的代码
count[configurationMatrix[i][j]] ++;
在索引为count
的元素处递增configurationMatrix[i][j]
。我没有看到您的代码采取任何步骤来确保线程不会同时尝试增加count
的相同元素。完全可行的是configurationMatrix
的两个不同元素向count
提供相同的索引,并且这两个元素由不同的线程处理。由于++
不是原子操作,因此您的代码具有数据竞争;多个线程可以争用对同一个变量的更新访问,并且您在结果中失去了对正确性或确定性的任何保证。
我认为您的代码的其他部分也可能有其他相同问题的示例。与串行程序的结果相比,您对并行程序的结果中观察到的错误保持沉默,但这些错误在诊断问题时通常非常有用。例如,如果并行程序的结果在每次运行时都不相同,那就非常暗示代码中某处的数据竞争。
如何解决这个问题?由于您只有2个线程,因此最简单的解决方法是不将此部分程序并行化。您可以将数据竞争包装在OpenMP critical
部分中,但这实际上只是序列化代码的另一种方式。最后,您可以修改算法和数据结构以完全避免此问题。