现在的位置: 首页 > 综合 > 正文

Linux CPU affinity

2013年12月17日 ⁄ 综合 ⁄ 共 4520字 ⁄ 字号 评论关闭

一.CPU affinity
    linux中将某个进程或者线程绑定到特定的一个或者多个cpu上执行。

 

二.为什么需要CPU affinity
    cache性能的提升,多个进程不断交替地在某个cpu上执行,导致缓存无效。
    多线程程序运行于某个cpu,每个线程轮流占据cpu资源,共享cache,导致cache性能下降。
    专有程序的实时性,当把专有进程保定与一个核,其余所有进程绑定与剩余的核,保证了专有程序的性能。

 

三.Linux cpu affinity 调用函数

a.进程cpu affinity设置

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

第一个函数设置进程号为pid的cpu亲和性
第二个函数获取进程号为pid的cpu亲和性

 

b.线程cpu affinity设置

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

第一个函数设置线程号为thread的cpu 亲和性
第二个函数获取线程号为thread的cpu 亲和性

四.例子

   1.  进程cpu affinity设置   task_affi.c:

#define _GNU_SOURCE

#include <stdio.h>
#include <math.h>
#include <unistd.h> 
#include <sched.h>
#include <pthread.h> 
#include <assert.h>

/*waste some time but ,ocuppy the cup*/
static waste_time(long n)
{

    double res = 0;

    long i = 0;

    while(i <n * 200000) {

        i++;

        res += sqrt(i);

    }

    return res;

}



int main()
{
        cpu_set_t cpuset;
        int ret, j, num_cpus, core;
        pid_t pid;

      
        pid = getpid();
        num_cpus = sysconf(_SC_NPROCESSORS_CONF);/*get the cpu nums*/
        assert(num_cpus > 0);

 

        printf("cpu num:%d\n", num_cpus);
        core = 0 % num_cpus;

 
        CPU_ZERO(&cpuset);
        CPU_SET(core, &cpuset);

 
        ret = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset);
        assert(ret == 0);
        

        ret = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset);
        assert(ret == 0);

 

        for (j = 0; j < CPU_SETSIZE; j++)
               if (CPU_ISSET(j, &cpuset))
                       printf("after set program bind on CPU %d\n", j);
       

        printf ("core %d result: %f\n", core, waste_time (5000));    

 

        core = 1%num_cpus;

        CPU_ZERO(&cpuset);
        CPU_SET(core, &cpuset);


        ret = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset);
        assert(ret == 0);


        ret = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset);
        assert(ret == 0);

 

        for (j = 0; j < CPU_SETSIZE; j++)
               if (CPU_ISSET(j, &cpuset))
                       printf("after set program bind on CPU %d\n", j);  

        printf ("core %d result: %f\n", core, waste_time (5000));

        return 0;

}


gcc 编译:

gcc task_affi.c -lm

2.    线程cpu affinity设置  thread_affi.c:

#define _GNU_SOURCE


#include <stdio.h>

#include <unistd.h>
#include <sched.h>
#include <pthread.h>  
#include <assert.h>

static int cpu_nums;

static waste_time(long n)
{

    double res = 0;
    long i = 0;

    while(i <n * 200000) {
        i++;
        res += sqrt(i);
    }

    return res;
}



void *function1(void *argc)
{
     pthread_t  thread_id;
     int ret, j, core;
     cpu_set_t cpuset;

 
     thread_id = pthread_self();
     printf("porgran pid:%u, the function1 pthread id is %lu\n",getpid(), thread_id);

     core = 0 % cpu_nums;
     CPU_ZERO(&cpuset);
     CPU_SET(core, &cpuset);

 
     ret = pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);

 

     /* Check the actual affinity mask assigned to the thread */
     ret = pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);

 
     printf("thread_id:%lu set the cpu:", thread_id);
     for (j = 0; j < CPU_SETSIZE; j++)
     if (CPU_ISSET(j, &cpuset))
        printf(" CPU %d\n\n", j); 
   	printf ("the function1 pthread id is %lu, bind core %d \n", thread_id, core );     
	printf("the function1 result: %f \n\n",waste_time (5000) );

     return 0;

}

 

void *function2(void *argc)
{

     pthread_t  thread_id;
     int ret, j, core;
     cpu_set_t cpuset;

 

     thread_id = pthread_self();
     printf("porgran pid:%u, the function2 pthread id is %lu\n",getpid(), thread_id);

     sleep(5);

 

     core = 1 % cpu_nums;
     CPU_ZERO(&cpuset);
     CPU_SET(core, &cpuset);

 

     ret = pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);

 

     /* Check the actual affinity mask assigned to the thread */

     ret = pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);

 

     printf("thread_id:%lu set the cup:\n", thread_id);

     for (j = 0; j < CPU_SETSIZE; j++)
     if (CPU_ISSET(j, &cpuset))
        printf(" CPU %d\n", j);

 

    	printf ("the function2 pthread id is %lu, bind core %d \n", thread_id, core);
	printf ("the function2 result is: %f\n",waste_time (5000) );

     return 0;
}

 

 

int main()
{

     pthread_t  thread_id[2];

     int ret, j, core;

     pthread_t main_thread_id;

     cpu_set_t cpuset;

     main_thread_id = pthread_self();

     

     cpu_nums = sysconf(_SC_NPROCESSORS_CONF);

     assert(cpu_nums > 0);

 

     printf("cpu num:%d\n", cpu_nums);
     core = 0 % cpu_nums;

     

     printf("porgran pid:%u, mian_thread_id:%lu\n", getpid(), main_thread_id);
     ret = pthread_create(thread_id, NULL, function1, NULL);
     assert(ret == 0);

 

     ret = pthread_create(thread_id + 1, NULL, function2, NULL);
     assert(ret == 0);

 

     ret = pthread_join(thread_id[0], NULL);
     assert(ret == 0);


     ret = pthread_join(thread_id[1], NULL);
     assert(ret == 0);

 

     core = 2 % cpu_nums;
     CPU_ZERO(&cpuset);
     CPU_SET(core, &cpuset);

 
     ret = pthread_setaffinity_np(main_thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);


     /* Check the actual affinity mask assigned to the thread */


     ret = pthread_getaffinity_np(main_thread_id, sizeof(cpu_set_t), &cpuset);
     assert(ret == 0);


     printf("mian_thread_id:%lu set the cpu:", main_thread_id);


     for (j = 0; j < CPU_SETSIZE; j++)
     if (CPU_ISSET(j, &cpuset))
        printf(" CPU %d \n\n", j);

 

     printf ("the main function pthread id is %lu, bind core %d result: %f\n", main_thread_id, core, waste_time (5000));

     return 0;

}

gcc 编译:

$ gcc thread_affi.c -lpthread -lm

执行程序时可以通过top命令,然后按‘1’,查看各个cpu的使用情况.

抱歉!评论已关闭.