CPU亲和性是linux 2.6后出现的新功能,在多核环境下,能将进程或线程绑定到指定的CPU上,减少多进程或线程切换引起处理器的频繁迁移带来的性能损耗。
DPDK是Intel提供的高性能网络包采集库,能支持千兆万兆网卡数据采集,原因是其实现用到了CPU affinity,大内存管理,环形缓冲区等技术。将采集线程绑定不同的CPU上,避免线程在不同核上的切换,提高采集效率。
一. 测试
taskset 命令获取和设置cpu亲和性。
tasket -pc 0 1234 将pid为1234的进程绑定到cpu0上,top命令下输入1查看各cpu核心的内存占用情况
二. cpu affinity调度函数
1.1 进程调度
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);
2.1 线程调度
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, onst cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);
cpu_set_t 参数指定cpu掩码,通过下面几组函数设置:
CPU_ZERO(&cpuset) // 清空掩码
CPU_SET(1,&cpuset) // 设置cpu1
三.测试
3.1 线程
#include <unistd.h> // sysconf
#include <stdio.h>
#define __USE_GNU // CPU_ZERO,CPU_SET使用需引入该宏
#include <pthread.h>
void *fun( void *arg );
void test_thread_affnity();
static int ncpus;
int main(int arg,char **argv)
{
// 获取cpu核心数
ncpus = sysconf(_SC_NPROCESSORS_CONF);
printf("cpus:%d\n",ncpus);
// 测试线程绑定
test_thread_affnity();
pause();
return 0;
}
// 将耗时任务绑定至cpu0上
void *fun( void *arg )
{
int i = 1;
// attach to cpu0
cpu_set_t cpuset;
CPU_ZERO( &cpuset );
CPU_SET( 0%ncpus,&cpuset );
// set thread affinity
pthread_setaffinity_np( pthread_self(),sizeof(cpuset),&cpuset );
// 死循环
while(1)
{
if(i%10000000000 == 0)
{
printf("th-%u:I'm busying\n",pthread_self());
i = 0;
}
i++;
}
return (void*)NULL;
}
void test_thread_affnity()
{
int i = 0;
pthread_t tid;
for( i=0;i<2;i++ )
{
pthread_create( &tid,NULL,fun,NULL );
}
}
3.2 进程
// 测试进程绑定
void test_process_affnity()
{
pid_t pid = fork();
if( pid == 0 )
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET( 0%ncpus,&cpuset );
// 将子进程绑定至cpu0
sched_setaffinity( getpid(),sizeof(cpuset),&cpuset );
waste_time(); // 干活中 ...
}else
{
printf("father do nothing\n");
}
}