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 进程绑定,也称为进程固定(用英特尔的话说)。绑定(或固定)限制每个 MPI 进程的 CPU 亲和集,即允许进程执行的 CPU 集。如果关联集仅包含一个逻辑 CPU,则该进程将仅在该逻辑 CPU 上执行。逻辑 CPU 通常对应于具有 SMT/超线程的 CPU 上的硬件线程或非 SMT/非超线程 CPU 上的 CPU 内核。给定包含多个逻辑 CPU 的关联集,允许调度程序迁移进程以保持集合中的 CPU 同等繁忙。默认关联集通常包括所有可用的逻辑 CPU,即可以安排进程在任何核心或硬件线程上执行。

只有当 MPI 进程绑定到位并且每个进程都绑定到单个逻辑 CPU 时,才有意义实际向操作系统查询进程的位置。您必须查阅 MPI 实施手册以了解如何启用它。例如,使用 Open MPI,您可以执行以下操作:

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

--bind-to-core告诉 Open MPI 将每个进程绑定到单个 CPU 内核,并--bycore告诉它在多插槽机器上连续分配内核(即首先在第一个插槽中分配所有内核,然后在第二个插槽中,等等)。使用英特尔 MPI 绑定(英特尔称为pinning)通过将环境变量设置I_MPI_PIN1. 进程放置策略由 的值控制I_MPI_PIN_DOMAIN。要实现与上面显示的 Open MPI 命令行相同,可以使用 Intel MPI 执行以下操作:

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

要以独立于平台的方式获取进程的位置,您可以hwloc_get_last_cpu_location()使用hwloc library。它是作为 Open MPI 项目的一部分开发的,但可以用作独立库。它提供了一个抽象接口来查询系统拓扑并操作进程和线程的亲和性。hwloc支持 Linux、Windows 和许多其他操作系统。

于 2013-11-13T16:29:23.147 回答
2

我们可以通过使用 utmpx.h 头文件示例程序中的 sched_getcpu() 函数从 net 获取核心 id,如下所示

#include <stdio.h>
#include<mpi.h>
#include <utmpx.h>

int main( int argc , char **argv )
{
MPI_Init(&argc, &argv);
printf( "cpu = %d\n", sched_getcpu() );
MPI_Finalize();
return 0;
}
于 2013-11-13T12:20:25.677 回答
1

您可以使用 Linux 特定的getcpu(2)系统调用(或者,正如Krishna 回答的那样,包装它的 Linux 特定的sched_getcpu(3)函数)。仔细阅读手册页(该getcpu系统调用没有任何 libc 包装器!)。请注意,它可能会为您提供一些过时的信息(因为内核可以 - 并且确实 -进程或任务 - 例如线程 -随时从一个 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(第 39字段给出处理器编号)......也许只是显示所有这些是最简单的方法:

{
   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 回答