Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.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++ 游戏中发布版本和调试版本之间奇怪的加速比;“生活”;_C++_Multithreading_Parallel Processing_Openmp - Fatal编程技术网

C++ 游戏中发布版本和调试版本之间奇怪的加速比;“生活”;

C++ 游戏中发布版本和调试版本之间奇怪的加速比;“生活”;,c++,multithreading,parallel-processing,openmp,C++,Multithreading,Parallel Processing,Openmp,我写了一个经典的游戏“生活”和四人邻居。当我在调试中运行它时,它显示: 连续版本:4.2s 并行版本:1.5s 好的,很好。但如果我在发布版中运行它,它会显示: 连续版本:0.46s 并行版本:1.23s 为什么??我用4个内核在计算机上运行它。我在并行部分运行4个线程。答案是正确的。但有些地方漏水,我不知道那个地方。有人能帮我吗 我尝试在VisualStudio2008和2012中运行它。结果是一样的。在项目设置中启用OMP 要重复我的问题,您可以找到定义的常量PARALLEL,并将

我写了一个经典的游戏“生活”和四人邻居。当我在调试中运行它时,它显示:

  • 连续版本:4.2s
  • 并行版本:1.5s
好的,很好。但如果我在发布版中运行它,它会显示:

  • 连续版本:0.46s
  • 并行版本:1.23s
为什么??我用4个内核在计算机上运行它。我在并行部分运行4个线程。答案是正确的。但有些地方漏水,我不知道那个地方。有人能帮我吗


我尝试在VisualStudio2008和2012中运行它。结果是一样的。在项目设置中启用OMP

要重复我的问题,您可以找到定义的常量
PARALLEL
,并将其设置为1或0以相应地启用和禁用OMP。答案将出现在
out.txt
(-正确答案示例)中。输入必须在in.txt(我的输入-)中。有一些俄文符号,您不需要理解它们,但是
in.txt
中的第一个数字表示并行部分中要运行的线程数(示例中为
4

主要部分位于
启动模拟功能中。如果运行该程序,您将在控制台中看到一些俄文文本和运行时间

程序代码足够大,因此我将其添加到文件托管中-(l2对我来说意味着“实验室2”)


关于
启动模拟
函数的一些注释。我将带有单元格的二维曲面切割成小矩形。这是通过
调整内核参数
功能完成的。

我觉得这个比率并不奇怪。让多个线程协作是一项复杂的业务,并且会产生开销

对共享内存的访问需要序列化,这通常涉及某种形式的锁定机制和线程之间的争用,线程必须等待释放锁。 这样的共享变量需要在处理器内核之间同步,这会导致显著的速度减慢。此外,编译器需要将这些关键区域作为“序列点”进行不同的处理

当每个线程使用共享变量时,所有这些都减少了每个线程在处理器硬件和编译器中的每线程优化范围

在这种情况下,并行化的开销似乎超过了单线程情况下的优化可能性


如果在需要访问共享变量之前,每个线程都有更多的独立工作要做,那么这些开销就不那么重要了。

您使用的是
引导的
循环计划。这是一个非常糟糕的选择,因为您正在处理一个常规问题,如果将域简单地划分为大小相等的块,则每个任务可以轻松地完成与其他任务完全相同的工作量

计划(引导)
替换为
计划(静态)
。在
livingCount
上也使用总和缩减,而不是使用锁定增量:

#if PARALLEL == 1
#pragma omp parallel for schedule(static) num_threads(kernelsCount) \
                         reduction(+:livingCount)
#endif
for (int offsetI = 0; offsetI < n; offsetI += kernelPartSizeN)
{
  for (int offsetJ = 0; offsetJ < m; offsetJ += kernelPartSizeM)
  {
    int boundsN = min(kernelPartSizeN, n - offsetI), 
        boundsM = min(kernelPartSizeM, m - offsetJ);

    for (int kernelOffsetI = 0; kernelOffsetI < boundsN; ++kernelOffsetI)
    {
      for (int kernelOffsetJ = 0; kernelOffsetJ < boundsM; ++kernelOffsetJ)
      {
        if(BirthCell(offsetI + kernelOffsetI, offsetJ + kernelOffsetJ))
        {
          ++livingCount;
        }
      }
    }
  }
}
#如果并行==1
#用于调度(静态)num_线程(内核计数)的pragma omp并行\
减少(+:存活计数)
#恩迪夫
for(int offsetI=0;offsetI
请不要将源文件放在文件托管服务上。相反,使用一个专门的服务,比如它也为许多语言和文件格式提供语法着色。@Hristo Iliev,我将来会考虑它。最终版本与减少:你是对的。我用
livingCount
而不是原子
#omp critical
添加了
减少(+:livingCount)
。现在的加速比大约为3.8。非常感谢,我已经被这个问题折磨了三个星期。谢谢。我之前做过(请参阅更高的注释),您还应该按照说明更改循环计划。这将进一步减少OpenMP开销,并改进编译器的选项,以优化和可能矢量化代码<代码>静态版
引导版
慢2.5%,这没有什么意义,但我对MS OpenMP运行时的特性不太熟悉。