Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.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,我正面临一个“可能”的奇怪问题。假设我有一个可执行文件。当我在一台有两个内核的计算机上运行它时,这个过程会运行一段时间t1。然后,如果我运行两个进程实例(相同的可执行文件,但在不同的目录上,手动启动或使用gnu并行启动),每个进程的运行时间不接近t1,但实际上更大,有时接近1.9t1。我必须指出,这两个核心是物理的(MacBookPro 2009年年中,Mountain Lion)。我还在一台8核的linux机器上测试了这种行为。如果我运行1、2、3和4个实例,每个实例的运行时间大约为t1。但是

我正面临一个“可能”的奇怪问题。假设我有一个可执行文件。当我在一台有两个内核的计算机上运行它时,这个过程会运行一段时间t1。然后,如果我运行两个进程实例(相同的可执行文件,但在不同的目录上,手动启动或使用gnu并行启动),每个进程的运行时间不接近t1,但实际上更大,有时接近1.9t1。我必须指出,这两个核心是物理的(MacBookPro 2009年年中,Mountain Lion)。我还在一台8核的linux机器上测试了这种行为。如果我运行1、2、3和4个实例,每个实例的运行时间大约为t1。但是,在5个、6个、7个和8个实例之后,每个实例的运行时间越来越大于t1

我在运行模拟时检测到这种行为。我能够将测试用例简化为下面介绍的简单测试。我想在几个编译级别上检查
std::vector
std::array
,静态和动态数组。测试代码如下所示:

#include <iostream>
#include <vector>
#include <array>
#include <cstdlib>

struct Particle {
private:
  int nc;
public:
  void reset(void) { nc = 0; };
  void set(const int & val) { nc = val; };
};

#define N 10000 // number of particles
#define M 200000 // number of steps

#define STDVECTOR 0
#define STDARRAY  0
#define ARRAY     1
#define DYNARRAY  0

int main (void)
{
#if STDVECTOR
  std::vector<Particle> particles(N);
#elif STDARRAY
  std::array<Particle, N> particles;
#elif ARRAY
  Particle particles[N];
#elif DYNARRAY
  Particle *particles; particles = new Particle [N];
#endif

  int jj = 0;
  for (int ii = 0; ii < M; ++ii) {
    //for (auto & body : particles) body.reset();
    for (int idx = 0; idx < N; ++idx) particles[idx].reset();
    jj = ii;
  }
  particles[0].set(jj*drand48());

  return 0;
}
#包括
#包括
#包括
#包括
结构粒子{
私人:
int nc;
公众:
无效重置(无效){nc=0;};
空集(const int&val){nc=val;};
};
#定义N 10000//粒子数
#定义M 200000//步数
#定义STDVECTOR 0
#定义标准数组0
#定义数组1
#定义DYNARRAY 0
内部主(空)
{
#中频机顶盒
std::矢量粒子(N);
#埃利夫·斯达雷
阵列粒子;
#elif阵列
粒子[N];
#艾利夫·戴纳雷
粒子*粒子;粒子=新粒子[N];
#恩迪夫
int jj=0;
对于(int ii=0;ii
编译测试如下所示

用于0 1 2 3中的a;执行printf“\n\nOPT=$a\n\n”;g++-4.8-O${a}-O tmp.x tmp.cpp;cp tmp.x simul01/;cp tmp.x simul02/;时间模拟01/tmp.x;并行'time{}/tmp.x'::simul01 simul02;完成

对于双核机器,我获得了以下数据:

其中时间以秒为单位,例如,vector-1或vector-2表示分别使用
std::vector
和运行一个或两个进程时的运行时间。对于这两个过程,我用了两个过程之间最长的时间

我期望:我期望两个进程的运行时间与单个进程的运行时间相似。但是,当有多个实例在运行时,即使内核的数量足够多,时间也会系统性地增加。正如我所说,当进程数大于4时,8核机器也会发生这种情况

如何测量时间:我使用
time
命令,选择用户时间。系统时间太少,不足以解释一个或两个进程运行时的差异

我已经检查了GCC4.6、4.7、4.8和4.9

因此,我的问题是:为什么会发生这种情况?可能与操作系统的某些固有特性以及进程从核心到核心的迁移有关。我真的不知道。我非常感谢有人能解释这一点,因为这会影响我模拟的运行时间。我需要同时运行几个进程,但运行时间正在增加。相反,对于一个进程和两个进程,使用不同方法的另一个模拟代码的运行时间大致相同。因此,我想放弃或确保这是我自己的程序的问题。我也不知道如何以可移植的方式(在mac和linux之间)设置处理器相关性


提前感谢

您的编译器CPU可能会自动执行代码线程。因此,您将通过1个实例获得最大性能。。。因此,运行2个实例将花费大约两倍的时间。

请记住,在2个内核上,还有其他任务与应用程序一起运行(内核线程、后台进程等)。引入另一个CPU密集型任务意味着可能会有线程跨内核迁移,本质上它们是在争夺资源。对于具有更多内核的Linux场景也是如此。一旦达到某个限制,您将与系统上的其他进程竞争,无论是您生成的进程还是后台进程和内核线程等……

可能有很多事情:

  • 核心竞争——特别是英特尔的超线程技术往往会降低cpu密集型代码的速度,而这些代码不包含不可预测的跳转。但也可能是,如果您只有两个内核,那么与系统中的其他进程(网络数据包、检查新邮件的电子邮件软件等)的争用会更多
  • 缓存争用:如果代码和数据不能全部放在一级缓存中,那么很可能最终会放在共享缓存中,而这两个实例会为谁存储什么以及存储在哪里而争吵。此外,如果两个线程被安排在同一个核心上,因为必须运行其他进程(例如,电子邮件客户端、web浏览器等),那么一级缓存内容将从进程A中抛出,以利于进程B。完全填充一级缓存并替换一级缓存中的内容不需要多少微秒,所以即使是很短的时间也会影响到这一点。第二个进程也有可能被转移到另一个进程
  • 内存带宽限制-两个实例使用两倍的内存带宽,导致内存负载增加 上面的列表远不是一个完整的可能性列表,只是一些更常见的可能性


    您可以通过使用分析工具(如
    oprofile
    perf
    )来判断这些选项中的哪一个(或其他),并检查机器上的各种性能计数器,比较1进程与2进程场景

    它可能使用1个物理内核和hyper-thre