首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么两个核上的两个实例的运行时间会大于一个实例的运行时间?

为什么两个核上的两个实例的运行时间会大于一个实例的运行时间?
EN

Stack Overflow用户
提问于 2013-09-13 08:51:04
回答 2查看 112关注 0票数 0

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

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

代码语言:javascript
运行
复制
#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;
}

编译测试是这样完成的:

for a in 0 1 2 3; do printf "\n\nOPT=$a\n\n"; g++-4.8 -O${a} -o tmp.x tmp.cpp; cp tmp.x simul01/ ; cp tmp.x simul02/; time simul01/tmp.x ; parallel 'time {}/tmp.x' ::: simul01 simul02 ; done

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

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

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

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

我已经和gcc核实了4.6,4.7,4.8和4.9。

因此,我的问题是:为什么会发生这种情况?可能与操作系统的某些固有特性以及进程从一个内核迁移到另一个内核有关。我真的不知道。如果有人能对此有所了解,我将非常感激,因为这会影响我的模拟运行时间。我需要同时运行多个进程,但是运行时间越来越长。相比之下,对于一个和两个进程,另一个具有不同方法的模拟代码几乎在相同的时间内运行。因此,我希望丢弃或确保这是我自己的过程的问题。我也不知道如何以可移植的方式设置处理器亲和性(在mac和linux之间)。

提前感谢

EN

回答 2

Stack Overflow用户

发布于 2013-09-13 09:06:33

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

票数 0
EN

Stack Overflow用户

发布于 2013-09-13 09:08:06

可能有很多东西:

  1. 核心竞争--特别是英特尔的超线程技术往往会降低不包含不可预知跳转的cpu密集型代码的速度。但也有可能是,如果您只有两个核心,则与系统中的其他进程(网络数据包、电子邮件软件唤醒以检查新邮件等)之间存在更多的争用。
  2. 缓存争用:如果代码和数据不能全部放入L1缓存,那么它很可能最终会出现在共享缓存中,并且两个实例会争夺谁可以存储什么内容以及存储在哪里。此外,如果两个线程被安排在同一个核心上,因为必须运行其他进程(例如,您的电子邮件客户端、web浏览器等),那么L1缓存内容将从进程A中丢弃以使进程B受益。完全填充L1缓存中的内容并不需要那么多微秒,因此即使是非常短的时间也会影响这一点。第二个进程也有可能被转移到另一个进程。
  3. 内存带宽限制-两个实例使用两倍的内存带宽,导致更多的内存负载。

上面的列表远远不是一个完整的可能性列表,而只是一些更常见的可能性。

您可以通过使用评测工具(如oprofileperf )来判断这些选项中的哪一个(或其他一些),并检查机器上的各种性能计数器,将1进程方案与2进程方案进行比较。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18776518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档