我开发了MPI程序,它可以在分布式环境中的不同核心上执行matrix multiplication,我可以通过获取节点的主机名来演示在不同节点上的执行。但是,当我们在单个节点上运行程序时,我可以获得核心ID,该核心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;
}
答案 0 :(得分: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,通过将环境变量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_get_last_cpu_location()
中的hwloc library。它是作为Open MPI项目的一部分开发的,但可以用作独立的库。它提供了一个抽象接口,用于查询系统拓扑并操纵进程和线程的关联。 hwloc 支持Linux,Windows和许多其他操作系统。
答案 1 :(得分:1)
您可以使用特定于Linux的getcpu(2)系统调用(或Krishna answered,包含它的Linux特定sched_getcpu(3)函数。仔细阅读手册页(getcpu
系统调用没有任何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
(39 th 字段提供处理器号码)...也许只显示所有这些是最简单的方法:
{
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内核。所以查询是无用的(任务可能在您查询它和显示它的那一刻之间迁移。)
答案 2 :(得分:1)
我们可以通过使用utmpx.h头文件中的sched_getcpu()函数来获取核心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;
}