我正面临一个“也许”奇怪的问题。假设我有一个可执行文件。当我在具有两个内核的计算机上运行它时,该过程运行时间为 t1。然后,如果我运行进程的两个实例(相同的可执行文件但在不同的目录上,手动或使用 gnu 并行启动),每个进程的运行时间并不接近 t1,但实际上更大,有时接近 1.9t1。我必须注意这两个核心是物理的(macbook pro mid 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;
}
编译测试完成为
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
对于两核机,我得到如下数据:
其中时间以秒为单位,例如vector-1或vector-2分别表示使用astd::vector
和运行一个或两个进程时的运行时间。对于这两个过程,我在两者之间花费的时间最长。
我的期望:我希望两个进程的运行时间与单个进程的时间相似。但是,当运行多个实例时,时间会系统性地增加,即使核心数量足够。正如我所说,这也发生在八核机器上,当进程数大于 4 时。
我如何测量时间:我使用了time
命令,并选择了用户时间。系统时间如此之小,不足以解释运行一两个进程时的差异。
我检查了 gcc 4.6、4.7、4.8 和 4.9。
因此,我的问题是:为什么会发生这种情况?也许与操作系统的某些内在特性以及进程从核心到核心的迁移有关。我真的不知道。我非常感谢有人能对此有所了解,因为这会影响我的模拟运行时间。我需要同时运行多个进程,但运行时间正在增加。相比之下,另一个具有不同方法的模拟代码在一个和两个进程中运行的时间几乎相同。所以我想放弃或确保这是我自己的程序的问题。我也不知道如何以可移植的方式(在 mac 和 linux 之间)设置处理器亲和力。
提前致谢