0

「たぶん」奇妙な問題に直面しています。実行可能ファイルがあるとしましょう。2 つのコアを搭載したコンピューターで実行すると、プロセスは時間 t1 にわたって実行されます。次に、プロセスの 2 つのインスタンス (同じ実行可能ファイルですが、手動または gnu 並列を使用して起動された別のディレクトリ) を実行すると、各プロセスの実行時間は t1 には近くありませんが、実際には 1.9t1 に近くなります。2 つのコアは物理的なものであることに注意する必要があります (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

2 コア マシンの場合、次のデータを取得しました。 実行時間または 1 つまたは 2 つのプロセス

時間は秒単位で表されます。たとえば、vector-1 または vector-2 はstd::vector、それぞれ 1 つまたは 2 つのプロセスを使用して実行した場合の実行時間を意味します。2 つのプロセスについては、2 つの間で最も時間がかかりました。

私が期待すること: 2 つのプロセスの実行時間は、1 つのプロセスの時間とほぼ同じになると思います。ただし、コアの数が十分であっても、複数のインスタンスが実行されている場合、時間は体系的に増加します。前述したように、これはプロセス数が 4 を超える 8 コア マシンでも発生します。

時間の測定方法:timeコマンドを使用して、ユーザー時間を選択しました。システム時間は非常に短いため、1 つまたは 2 つのプロセスが実行されている場合の違いを説明するには不十分です。

gcc 4.6、4.7、4.8、および 4.9 で確認しました。

したがって、私の質問は次のとおりです。なぜこれが起こっているのですか? おそらく、オペレーティングシステムの組み込みと、コアからコアへのプロセスの移行に関連しています。私は本当に知らない。これは私のシミュレーションの実行時間に影響を与えているため、誰かがこれに光を当てることができれば非常に感謝しています。同時に複数のプロセスを実行する必要がありますが、実行時間が増えています。対照的に、別の方法を使用した別のシミュレーション コードは、1 つのプロセスと 2 つのプロセスの両方でほぼ同じ時間で実行されます。ですので、これは自分の手順の問題であるということを、破棄または確認したいと思います。移植可能な方法でプロセッサのアフィニティを設定する方法もわかりません(MacとLinuxの間)。

前もって感謝します

4

3 に答える 3

0

多くのことが考えられます:

  1. コアの競合 - 特に Intel のハイパースレッディングは、予測できないジャンプを含まない CPU 集中型のコードを遅くする傾向があります。しかし、コアが 2 つしかない場合は、システム内の他のプロセス (ネットワーク パケット、新しいメールをチェックするためにウェイク中の電子メール ソフトウェアなど) との競合が増える可能性もあります。
  2. キャッシュの競合: コードとデータのすべてが L1 キャッシュに収まらない場合、最終的に共有キャッシュになる可能性があり、2 つのインスタンスが、誰が何をどこに格納するかをめぐって争います。また、2 つのスレッドが同じコアでスケジュールされた場合、他のプロセス (電子メール クライアント、Web ブラウザーなど) を実行する必要があるため、L1 キャッシュ コンテンツがプロセス A からスローされ、プロセス B に利益をもたらします。 L1 キャッシュ内のコンテンツを完全に埋めるのに何マイクロ秒もかかるため、非常に短い時間でもこれに影響します。2 番目のプロセスが他のプロセスに移動する可能性もあります。
  3. メモリ帯域幅の制限 - 2 つのインスタンスが 2 倍のメモリ帯域幅を使用するため、メモリの負荷が高くなります。

上記のリストは、可能性の完全なリストではなく、より一般的なものの一部に過ぎません。

oprofileまたはなどのプロファイリング ツールを使用して、これらのオプション (またはその他のオプション) のどれかを判断しperf、1 プロセスと 2 プロセスのシナリオを比較して、マシン上のさまざまなパフォーマンス カウンターを調べることができる場合があります。

于 2013-09-13T01:08:06.140 に答える
0

コンパイラのCPU がコードを自動的にスレッド化している可能性がありますしたがって、1 つのインスタンスで最大のパフォーマンスが得られます...したがって、2 つのインスタンスを実行すると、約 2 倍の時間がかかります。

于 2013-09-13T01:02:15.070 に答える
0

アプリケーションと並行して実行されている他のタスク (カーネル スレッド、バックグラウンド プロセスなど) があることに注意してください。2 つのコアで別の CPU 集中型タスクを導入すると、コア間でスレッドの移行が発生する可能性があり、基本的にそれらはリソースを競合します。より多くのコアを使用する Linux シナリオでも同じことが当てはまります。特定の制限に達すると、生成したプロセスやバックグラウンド プロセス、カーネル スレッドなど、システム上の他のプロセスと競合することになります。

于 2013-09-13T01:06:33.213 に答える