Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C OpenMP不同结果1核与多核_C_Multithreading_Openmp_Multicore - Fatal编程技术网

C OpenMP不同结果1核与多核

C OpenMP不同结果1核与多核,c,multithreading,openmp,multicore,C,Multithreading,Openmp,Multicore,在过去的几个月里,我一直试图用C多核语言编写我的程序,但我一直遇到这个奇怪的问题。也许你们中的一些人能帮我一点忙 我遇到的问题是,当我让程序只使用一个线程进行计算时,它会给出正确的结果。然而,当我选择更多线程时,我的值开始改变,即使执行的计算应该完全相同(除了随机数生成器之外,但这不应该是问题,因为每个内核都有自己独特的种子,并且已知生成器与openmp多核处理一起工作) 无论如何,由于程序本身是保密的,我不能给你完整的代码(因为它太大了,不便于使用),所以我会尽量给出部分代码,这可能会进一步解

在过去的几个月里,我一直试图用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*/
#包括
#包括
#包括
#包括
#include/*openmp头*/
#包括
#包括
#包含/*RNG头*/
#包含/*RNG头*/
然后我定义了一些结构等,但我知道这些工作,因为程序在单核模式下工作。然后我有一个主函数,其中我的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]);
   }
//执行多核计算(循环所有光子)
#默认值为pragma omp parallel(无)\
线程数(线程数)\
私有(i计数,线程id,i)\
共享(计算、imstr、总和、泄漏)\
复制(scat、cap、pcap_ini、配置文件、absmu、ctvar、lib)

对于(icount=0;icount要在我的注释上展开,代码看起来是这样的。虽然循环中仍然使用线程相关的值,但它们不必在每次传递时都重新初始化,这至少会为您节省一些开销。但我仍然不确定您的示例中的问题出在哪里。是否都是o如果共享变量仅由线程id引用?您提到它们不被读取,但它们是如何更新的,您是否对它们进行求和或以其他方式累积值

#pragma omp parallel default(none) \
   num_threads(thread_cnt) \
   shared(calc,imstr,sum_irefl,leaks) \
   copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib)
{
 int icount, thread_id, i; //note, private by definition in the region
 thread_id = omp_get_thread_num();
 printf("\nthread %d scat:\n",thread_id);
 //perform multicore calculations (loop over all photons)
 #pragma omp for
 for(icount=0; icount <= cap.ndet; icount++){

   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]);
   }
}
#pragma omp并行默认值(无)\
线程数(线程数)\
共享(计算、imstr、总和、泄漏)\
复制(scat、cap、pcap_ini、配置文件、absmu、ctvar、lib)
{
int icount,thread_id,i;//注意,根据区域中的定义是私有的
thread_id=omp_get_thread_num();
printf(“\n读取%d个扫描:\n”,线程id);
//执行多核计算(在所有光子上循环)
#pragma omp for

对于(icount=0;icount要在我的注释上展开,代码看起来是这样的。虽然循环中仍然使用线程相关的值,但它们不必在每次传递时都重新初始化,这至少会为您节省一些开销。但我仍然不确定您的示例中的问题出在哪里。是否都是o如果共享变量仅由线程id引用?您提到它们不被读取,但它们是如何更新的,您是否对它们进行求和或以其他方式累积值

#pragma omp parallel default(none) \
   num_threads(thread_cnt) \
   shared(calc,imstr,sum_irefl,leaks) \
   copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib)
{
 int icount, thread_id, i; //note, private by definition in the region
 thread_id = omp_get_thread_num();
 printf("\nthread %d scat:\n",thread_id);
 //perform multicore calculations (loop over all photons)
 #pragma omp for
 for(icount=0; icount <= cap.ndet; icount++){

   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]);
   }
}
#pragma omp并行默认值(无)\
线程数(线程数)\
共享(计算、imstr、总和、泄漏)\
复制(scat、cap、pcap_ini、配置文件、absmu、ctvar、lib)
{
int icount,thread_id,i;//注意,根据区域中的定义是私有的
thread_id=omp_get_thread_num();
printf(“\n读取%d个扫描:\n”,线程id);
//执行多核计算(在所有光子上循环)
#pragma omp for

对于(icount=0;icount此处肯定缺少某些内容。为什么在并行循环上下文中获取并使用线程id?您是通过完全独立于循环的方式访问calc变量的,它是否在稍后的某个位置合并?至少,应该将其拆分为一个omp并行区域,该区域获取线程id并执行以下操作:es线程特定的工作,以及扩展线程无关工作的封闭for worksharing构造。calc变量确实在parallel for循环后合并。我也认为我理解你最后的评论,但“问题”是在for循环期间也完成了线程特定的工作(例如calc[thread_id].iesc获得了新的值等).因此,在我看来,我无法使for循环独立于线程。但也许我误解了你…你能用我在原始问题中提到的代码给我写一个拆分并行和for区域的代码示例吗?@user2257570你能告诉我们你使用的是哪种随机数生成器吗?我对要使用的生成器感兴趣与openmp相比,这里肯定缺少一些东西。为什么在并行循环上下文中获取并使用线程id?您正在通过完全独立于循环的方式访问calc变量,它是否在稍后的某个位置合并?至少,应该将其拆分为一个omp并行区域,该区域获取线程id并执行以下操作es线程特定的工作,以及扩展线程无关工作的封闭for worksharing构造。calc变量确实在parallel for循环后合并。我也认为我理解你最后的评论,但“问题”是在for循环期间也完成了线程特定的工作(例如calc[thread_id].iesc获得了新的值等).因此,在我看来,我无法使for循环独立于线程。但也许我误解了你…你能用我在原始问题中提到的代码给我写一个拆分并行和for区域的代码示例吗?@user2257570你能告诉我们你使用的是哪种随机数生成器吗?我对要使用的生成器感兴趣非常感谢openmp。感谢您提供的代码示例!我以为您打算这样做,但不确定;)我认为,通过添加值,您也走上了正轨……在for循环期间,所有共享变量中的值实际上都是求和或累积的。基本上,它们是标记某些事件发生的计数器。我应该为此做些什么吗?我读了一篇关于reduce子句的文章,我可能不得不使用它,但我并不真正理解它还有,你还有什么建议吗,njustn?