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"); } }