1

分散環境のさまざまなコアで行列乗算を実行できる MPI プログラムを開発しました。ノードのホスト名を取得することで、さまざまなノードでの実行を実証できます。しかし、単一ノードでプログラムを実行している場合、複数ノードでの実行を示すコア ID を取得できますか? サンプル コードを以下に示します。

#include"stdio.h"
#include"stdlib.h"
#include"mpi.h"

int main(int argc , char **argv)
{
int size,rank;
int a,b,c;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank==0)
{
for(i=0;i<size;i++)
{
    printf("insert a and b");
    scanf("%d",&b);
    scanf("%d",&c);
    MPI_Send(&b,1,MPI_INT,i+1,6,MPI_COMM_WORLD);
    MPI_Send(&c,1,MPI_INT,i+1,6,MPI_COMM_WORLD);
}
} 

if(rank!=0)
{
MPI_Recv(&b,1,MPI_INT,0,6,MPI_COMM_WORLD,&s);
MPI_Recv(&c,1,MPI_INT,0,6,MPI_COMM_WORLD,&s);
a=b*c;
printf("Mul = %d\n",a);
//Print name of core on which my process is running
}

MPI_Finalize();
return 0;
}
4

3 に答える 3

4

現在コードを実行している論理プロセッサの ID を取得することは可能ですが、MPI プロセス バインディングを有効にしない限り意味がないことがよくあります。、プロセスピニングとも呼ばれます (Intel の用語で)。バインド (またはピニング) は、各 MPI プロセスの CPU アフィニティ セット、つまりプロセスが実行できる CPU のセットを制限します。アフィニティ セットに論理 CPU が 1 つしか含まれていない場合、プロセスはその論理 CPU でのみ実行されます。論理 CPU は通常、SMT/ハイパースレッディングを使用する CPU のハードウェア スレッド、または非 SMT/非ハイパースレッディング CPU の CPU コアに対応します。複数の論理 CPU を含むアフィニティ セットを指定すると、スケジューラは、セット内の CPU を均等にビジー状態に保つためにプロセスを移行できます。デフォルトのアフィニティ セットには通常、使用可能なすべての論理 CPU が含まれます。つまり、プロセスは任意のコアまたはハードウェア スレッドで実行するようにスケジュールできます。

MPI プロセスのバインドが行われ、各プロセスが単一の論理 CPU にバインドされている場合にのみ、実際に OS にプロセスの場所を問い合わせることが理にかなっています。有効にする方法については、MPI 実装マニュアルを参照する必要があります。たとえば、Open MPI では次のようにします。

mpiexec --bind-to-core --bycore -n 120 ...

--bind-to-core各プロセスを単一の CPU コアにバインドするように Open MPI に--bycore指示し、マルチソケット マシンにコアを連続して割り当てるように指示します (つまり、最初にすべてのコアを最初のソケットに割り当て、次に 2 番目のソケットに割り当てるなど)。 (インテルではピニングと呼ばれます) は、環境変数I_MPI_PINを に設定することで有効になります1。プロセス配置戦略は、 の値によって制御されますI_MPI_PIN_DOMAIN。上記の Open MPI コマンドラインと同じことを実現するには、Intel MPI で次のようにします。

mpiexec -n 120 -env I_MPI_PIN 1 -env I_MPI_PIN_DOMAIN "core:compact" ...

プラットフォームに依存しない方法でプロセスの場所を取得するには、 hwlocライブラリhwloc_get_last_cpu_location()から使用できます。Open MPI プロジェクトの一部として開発されていますが、スタンドアロン ライブラリとして使用できます。システム トポロジを照会し、プロセスとスレッドのアフィニティを操作するための抽象インターフェイスを提供します。hwlocは、Linux、Windows、およびその他の多くの OS をサポートしています。

于 2013-11-13T16:29:23.147 に答える
1

Linux 固有のgetcpu(2) syscall (または、Krishna が答えたように、それをラップする Linux 固有のsched_getcpu(3)関数) を使用できます。man ページを注意深く読んでください ( getcpusyscall には libc ラッパーがありません!)。古い情報を提供する場合があることに注意してください (カーネルはプロセスやタスク (スレッドなど) をある CPU コアから別の CPU コアにいつでも移行できるため)。

それ以外の場合、MPI実装はおそらくスレッドまたはプロセスを使用しています。スレッドの場合はgettid(2) (ラッパーが必要)、プロセスの場合はgetpid(2)でクエリできます。

次のようにコーディングできます。

#include <unistd.h>
#include <asm/unistd.h>
#include <sys/syscall.h>

static inline long my_gettid(void)
{ return syscall(SYS_gettid); }

そしておそらくgetcpu....に似たもの。

proc(5)/proc/self/statを使用することもできます。

{
   char line[128];
   FILE *fs = fopen("/proc/self/stat","r");
   if (!fs) { perror("/proc/self/stat"); exit(EXIT_FAILURE); };
   while (!feof(fs)) {
     memset(line, 0, sizeof(line));
     fgets(line, sizeof(line), fs);
     fputs(line, stdout);
   };
   fclose(fs);
 }

Linux カーネル (そのスケジューラ) は、ある CPU コアから別の CPU コアにタスク (つまり、プロセスまたはスレッド) をいつでも移行していることを思い出してください。そのため、ほとんど役に立たないクエリを実行します (クエリを実行した瞬間と表示した瞬間にタスクが移行した可能性があります)。

于 2013-11-13T07:28:57.290 に答える