在过去的几个月里,我一直在尝试用 C 多核编写我的程序,但我一直遇到这个奇怪的问题。也许你们中的一些人可以帮助我一点?
我遇到的问题是,当我让它只使用一个线程进行计算时,我的程序会给出正确的结果。但是,当我选择更多线程时,我的值开始发生变化,即使执行的计算应该完全相同(除了随机数生成器,但这不应该是问题,因为每个核心都有自己独特的播种机和众所周知,生成器可以与 openmp 多核处理一起使用)。
无论如何,由于程序本身是保密的,我不能给你整个代码(它太大了不方便使用)所以我会尽力提供部分代码,这可能会进一步解释问题。
首先我包括的库:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <omp.h> /* openmp header */
#include <limits.h>
#include <float.h>
#include <gsl/gsl_rng.h> /*RNG header*/
#include <gsl/gsl_randist.h> /*RNG header*/
然后我定义了一些结构等,但我知道这些工作是因为程序确实在单核模式下工作。然后我有 main 函数,其中我的 openMP 并行循环如下所示:
//perform multicore calculations (loop over all photons)
#pragma omp parallel for default(none) \
num_threads(thread_cnt) \
private(icount,thread_id,i) \
shared(calc,imstr,sum_irefl,leaks) \
copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib)
for(icount=0; icount <= cap.ndet; icount++){
thread_id = omp_get_thread_num();
printf("\nthread %d scat:\n",thread_id);
for(i=0;i<NDIM;i++) printf("%f\t",scat[i]);
do{
do{
start(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, calc, &thread_id);
do capil(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, leaks, scat,
calc, &thread_id);
while (calc[thread_id].iesc == 0); /* perform capil until iesc not equal to 0 anymore */
}
while(calc[thread_id].iesc == -2); /* only do count etc if iesc!=-2, else redo start */
count(absmu, ctvar, &cap, &icount, profile, leaks, &imstr,calc, &thread_id);
}
while(calc[thread_id].iesc == -3);
sum_irefl[thread_id] = sum_irefl[thread_id] + calc[thread_id].i_refl;
if(icount%1000 == 0 && thread_id == 0) printf("%d\t%ld\t%f\n",icount,calc[0].i_refl,
calc[0].rh[2]);
}
在这些子函数 ( start, capil, count
) 中,一些变量被写入了新值,这就是 和 的calc,imstr,sum_irefl
情况leaks
。我将它们设置为共享,因此每个线程都可以访问它们。但是,我不相信内存竞争的机会,例如calc
实际上是在一个数组中拆分的,其中每个线程都有自己的变量(通过它们的 unique 访问thread_id
),而其他共享变量可能会因为它们而竞争任何时候都不要阅读。也许我误解了记忆竞赛的危险,但我不认为这会造成问题......
变量之前是线程安全的copyin
(此处未显示,但编译器不会抱怨,所以我认为这不是问题)并且它们仅在并行循环期间被读取,所以我再次看不出问题可能是什么。此外,我检查了并行循环开始时的每个变量是否具有它应该具有的值。因此,在并行部分的某个地方,当我使用 1 个或更多内核运行程序时,获得的值会有所不同。
我知道这不是很多,但我希望你们中的一些人有一个想法。如果您需要更多信息,请随时问我,因为我可能能够提供更多信息。
所以我想知道的事情是:我到底有没有可能进行有害的记忆竞赛?您还看到其他可能出错的地方吗?你知道我可以用来检查我的多核程序的任何(相对)易于使用的程序吗?