Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.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++中使用并行化。_C++ - Fatal编程技术网

如何在C++;让代码更快? 我试图在C++中使用并行化。

如何在C++;让代码更快? 我试图在C++中使用并行化。,c++,C++,下面是我编写的示例代码 我听说我需要足够数量的N才能使并行化工作 所以我提出了三维数组。(我增加了“堆栈保留大小”的大小以运行下面的代码。) 我用“chrono”来测量经过的时间 但在这段代码中,并行化实际上会使代码变慢 所以我想知道发生这种情况的原因是什么 这是因为运行并行化的固定成本与我这里的“i”的数量相比仍然很大吗 int main() { omp_set_num_threads(8); double AAA[1000][1000][10]; double A[1

下面是我编写的示例代码

我听说我需要足够数量的N才能使并行化工作

所以我提出了三维数组。(我增加了“堆栈保留大小”的大小以运行下面的代码。)

我用“chrono”来测量经过的时间

但在这段代码中,并行化实际上会使代码变慢

所以我想知道发生这种情况的原因是什么

这是因为运行并行化的固定成本与我这里的“i”的数量相比仍然很大吗

int main() {
    omp_set_num_threads(8);
    double AAA[1000][1000][10];
    double A[1000];
    fill(&AAA[0][0][0], &AAA[0][0][0] + sizeof(AAA) / sizeof(AAA[0][0][0]), 1);
    fill(&A[0], &A[0] + sizeof(A) / sizeof(AAA[0]), 2);

    system_clock::time_point start = system_clock::now();
    #pragma omp parallel for private(A)
    for (int i = 0; i < 1000; i++) {
        for (int j = 0; j < 1000; j++) {
            for (int k = 0; k < 10; k++) {
                AAA[i][j][k] = A[i] + A[j] + A[k];
            }
        }
    }
    system_clock::time_point end = system_clock::now();
    std::chrono::duration<double> sec = end - start;
    cout << sec.count() << endl;
}
intmain(){
omp_设置_数量_线程(8);
双AAA[1000][1000][10];
双A[1000];
填充(&AAA[0][0][0],&AAA[0][0]+sizeof(AAA)/sizeof(AAA[0][0][0]),1);
填充(&A[0],&A[0]+sizeof(A)/sizeof(AAA[0]),2);
系统时钟::时间点开始=系统时钟::现在();
#pragma omp并行专用(A)
对于(int i=0;i<1000;i++){
对于(int j=0;j<1000;j++){
对于(int k=0;k<10;k++){
AAA[i][j][k]=A[i]+A[j]+A[k];
}
}
}
系统时钟::时间点结束=系统时钟::现在();
标准::计时::持续时间秒=结束-开始;
你的问题是内存不足。
这意味着程序在内存/缓存之间移动数据的时间比实际计算要长得多。
事实上,计算只包括两个加法。
您可以增加数组(当然是在堆上,而不是在堆栈中),内存传输和计算时间之间的比率将是相同的,甚至更糟(因为数据不完全适合缓存)。
从处理器的角度来看,让八个内核等待内存传输(写缓冲区)并没有比只有一个内核等待更大的帮助(除非您有不同的内存控制器,并且在NUMA系统上物理内存使用的良好平衡)

如果您希望通过并行化观察增益,则需要增加使用相同数据量执行的计算量。 下面是你的例子修改了一个非常愚蠢的方式,只是为了观察这个增益(4.365到0.652153秒在我的系统上)

/**
g++-std=c++17-o prog_cpp prog_cpp.cpp\
-pedantic-Wall-Wextra-Wconversion-Wno符号转换\
-O3-march=本地-fopenmp
**/
#包括
#包括
#包括
#包括
#包括
int
main()
{
constexpr auto ni=2000,nj=ni,nk=100;
自动AAA=std::vector(ni*nj*nk,1.0);
自动A=标准::向量(ni,2.0);
#如果定义了OPENMP
omp_设置_数量_线程(8);
#恩迪夫
const auto start=std::chrono::system_clock::now();
#pragma-omp并行
对于(自动i=0;i您的问题是内存受限。
这意味着程序在内存/缓存之间移动数据的时间比实际计算要长得多。
事实上,计算只包括两个加法。
您可以增加数组(当然是在堆上,而不是在堆栈中),内存传输和计算时间之间的比率将是相同的,甚至更糟(因为数据不完全适合缓存)。
从处理器的角度来看,让八个内核等待内存传输(写缓冲区)并没有比只有一个内核等待更大的帮助(除非您有不同的内存控制器,并且在NUMA系统上物理内存使用的良好平衡)

如果您希望通过并行化观察增益,则需要增加使用相同数据量执行的计算量。 下面是你的例子修改了一个非常愚蠢的方式,只是为了观察这个增益(4.365到0.652153秒在我的系统上)

/**
g++-std=c++17-o prog_cpp prog_cpp.cpp\
-pedantic-Wall-Wextra-Wconversion-Wno符号转换\
-O3-march=本地-fopenmp
**/
#包括
#包括
#包括
#包括
#包括
int
main()
{
constexpr auto ni=2000,nj=ni,nk=100;
自动AAA=std::vector(ni*nj*nk,1.0);
自动A=标准::向量(ni,2.0);
#如果定义了OPENMP
omp_设置_数量_线程(8);
#恩迪夫
const auto start=std::chrono::system_clock::now();
#pragma-omp并行

对于(auto i=0;我想这是一个愚蠢的问题,但如果我只是增加堆栈的大小并保存每个进位堆栈而不是堆,会有问题吗?如果我使用堆栈而不是堆,并行化会不会行不通?我已经用ni=1000和nk=100更改了你的示例。当我使用“release”时,它看起来像结果与“#pragma omp parallel for”相同,没有“#pragma omp parallel for.”0.37秒。但是,如果使用“debug”,我会看到两个结果之间的一些差异。因此我想知道并行化是否只在debug中起作用?@ChangseokMa堆栈空间通常非常有限(千字节到几兆字节,取决于系统),因此,为了避免由于堆栈溢出而导致崩溃;^)我们通常在堆中分配大量数据(无论问题是什么,并行化与否)。这不会改变并行化的任何内容。@ChangseokMa关于您系统上的调试/发布问题,我没有任何线索……在我的系统上,我在启用优化的情况下进行了测试(请参见命令行)在优化后,你的编译器在优化<代码> > <代码> >和数学调用,使得并行化没有可测量的效果。谢谢。我有一个附加的问题……如果我使用Ni=2000,NK=100当你上传时。不知为什么我的C++不工作,所以我需要把大小缩小到Ni=1000和NK=1。0.据我所知,vector不需要动态分配权…?那么这只是我的计算机内存问题吗?谢谢你的评论。我认为这是一个愚蠢的问题,但如果我只是增加堆栈的大小,并在堆栈中保存每个进位而不是堆,会有问题吗?如果我使用堆栈而不是堆,并行化不会进行吗去工作吗
/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -O3 -march=native -fopenmp
**/

#include <iostream>
#include <chrono>
#include <vector>
#include <cmath>
#include <omp.h>

int
main()
{
  constexpr auto ni=2000, nj=ni, nk=100;
  auto AAA=std::vector<double>(ni*nj*nk, 1.0);
  auto A=std::vector<double>(ni, 2.0);

#if defined _OPENMP
  omp_set_num_threads(8);
#endif
  const auto start=std::chrono::system_clock::now();
  #pragma omp parallel for
  for(auto i=0; i<ni; ++i)
  {
    for(auto j=0; j<nj; ++j)
    {
      for(auto k=0; k<nk; ++k)
      {
        const auto idx=i*(nj*nk)+j*nk+k;
        if(j<k)
        {
          AAA[idx]+=std::sqrt(A[i])+std::log(A[j]);
        }
        else
        {
          AAA[idx]+=std::log(A[j])+std::cos(A[k]);
        }
      }
    }
  }
  const auto end=std::chrono::system_clock::now();
  const auto duration=std::chrono::duration<double>{end-start};
  std::cout << duration.count() << '\n';
  return 0;
}