linux将进/线程绑定核心运行(cpu亲和性)

查看cpu核心数

cpu一般有多个物理核心,但在运行进程和线程时候,可以将其绑定或者指定到某一个或者多个核心上运行。我们在系统上有两种方法可以查看cpu核心数。

1.cat /proc/cpuinfo查看cpu的核心数以及信息,这里以树莓派3B为例:

processor : 0
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 1
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 2
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 3
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

Hardware : BCM2835
Revision : a22082
Serial : 000000005a77a4ec

2.使用C代码:

#include <unistd.h>
#include <stdio.h>
#include <sys/sysinfo.h>

int main (void)
{
printf("cpu core cnt:%d\n",sysconf(_SC_NPROCESSORS_ONLN));
printf("cpu core cnt:%d\n",get_nprocs());
}
pi@raspberrypi:~/test $ gcc test.c -o test
pi@raspberrypi:~/test $ ./test
cpu core cnt:4
cpu core cnt:4

可以看到树莓派3B一共有4个物理核心。

如何将进程绑定核心运行呢?

1.可以使用tasklet命令,举例如下:

#include <stdio.h>


int main(void)
{
while(1);
}
pi@raspberrypi:~/test $ gcc loop.c -o loop
pi@raspberrypi:~/test $ ./loop &
[2] 3148
pi@raspberrypi:~/test $ taskset -p 3148
pid 3148's current affinity mask: f

编译后放后台运行,使用tasklet查pid我们可以看到mask是f,也就是二进制的1111,表明这个进程可以在4个核心上被调度。当然我们也可以使用tasklet -c来指定程序在哪些核心上运行

pi@raspberrypi:~/test $ taskset -c 0 ./loop &
[2] 3183
pi@raspberrypi:~/test $ taskset -p 3183
pid 3183's current affinity mask: 1

可以看到,程序只能在核心0上运行

2.使用C代码:

关键函数:

int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
#include <stdio.h>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>

int main(void)
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0,&cpuset);
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
while(1);
}
pi@raspberrypi:~/test $ gcc loop.c -o loop -lpthread
pi@raspberrypi:~/tes./loop &
[4] 3389
pi@raspberrypi:~/test $ taskset -p 3389
pid 3389's current affinity mask: 1

编译后运行,可以看到,程序只能在核心0上运行

如何将线程绑定核心运行呢?

使用C代码:

关键函数:

int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);
写了一个简单的示例,先不设置线程亲和性,只回读状态:

#include <stdio.h>
#include <stdlib.h>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>


void thread1(void)
{
printf("this is thread1\n");
while(1);

}

void thread2(void)
{
printf("this is thread2\n");
while(1);

}
int main(void)
{
pthread_t id1,id2;
int ret;
cpu_set_t cpuset;

ret = pthread_create(&id1,NULL,(void *)thread1,NULL);
if(ret != 0)
{
printf("create thread err!\n");
exit(1);
}

ret = pthread_create(&id2,NULL,(void *)thread2,NULL);
if(ret != 0)
{
printf("create thread err!\n");
exit(1);
}
pthread_getaffinity_np(id1, sizeof(cpu_set_t),&cpuset);
printf("thread1 affinity:%x\n",cpuset);
pthread_getaffinity_np(id2, sizeof(cpu_set_t),&cpuset);
printf("thread2 affinity:%x\n",cpuset);
while(1);
}
pi@raspberrypi:~/test $ gcc pthread.c -o pthread -lpthread
pi@raspberrypi:~/test $ ./pthread &
[3] 3689
pi@raspberrypi:~/test $

thread1 affinity:f
thread2 affinity:f
this is thread2
this is thread1

编译并执行程序后,可以看到线程1和线程2的亲和性都是f,可以在4个核心上运行。我们通过pstree也可以看到这个程序创建了两个线程。

├─sshd─┬─sshd───sshd───bash─┬─pstree
│ │ ├─pthread
│ │ └─2*[pthread───2*[{pthread}]]

接下来我们把亲和性设置加上,代码如下:

#include <stdio.h>
#include <stdlib.h>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>


void thread1(void)
{
printf("this is thread1\n");
while(1);

}

void thread2(void)
{
printf("this is thread2\n");
while(1);

}
int main(void)
{
pthread_t id1,id2;
int ret;
cpu_set_t cpuset;

ret = pthread_create(&id1,NULL,(void *)thread1,NULL);
if(ret != 0)
{
printf("create thread err!\n");
exit(1);
}

ret = pthread_create(&id2,NULL,(void *)thread2,NULL);
if(ret != 0)
{
printf("create thread err!\n");
exit(1);
}
CPU_ZERO(&cpuset);
CPU_SET(0,&cpuset);
pthread_setaffinity_np(id1,sizeof(cpu_set_t), &cpuset);
CPU_ZERO(&cpuset);
CPU_SET(1,&cpuset);
pthread_setaffinity_np(id2,sizeof(cpu_set_t), &cpuset);



pthread_getaffinity_np(id1, sizeof(cpu_set_t),&cpuset);
printf("thread1 affinity:%x\n",cpuset);
pthread_getaffinity_np(id2, sizeof(cpu_set_t),&cpuset);
printf("thread2 affinity:%x\n",cpuset);
while(1);
}
pi@raspberrypi:~/test $ gcc pthread.c -o pthread -lpthread
pi@raspberrypi:~/test $ ./pthread &
[6] 3794
pi@raspberrypi:~/test $

thread1 affinity:1
thread2 affinity:2
this is thread2
this is thread1

编译运行后可以看到,线程1只能在核心0上运行,线程2只能在核心1上运行。
————————————————
版权声明:本文为CSDN博主「Helenie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/helenie/article/details/121047915

posted on 2022-04-22 16:07  feng..liu  阅读(803)  评论(0编辑  收藏  举报