Friday, May 04, 2012

[Linux]使用C设置线程的CPU affinity

随着多核机器的越来越普及. 对线程设置CPU affinity变得对性能越来越重要.linux提供的affinity设置功能可以将一个线程绑定到一个CPU的集合上(该集合可以包括一个或者多个CPU), 使得这个线程只被调度在属于给定CPU集合中的CPU上执行.
与CPU集合描述有关的几个宏:
  • CPU_ZERO():清空一个cpu_set_t类型的集合
  • CPU_SET()与CPU_CLR(): 将某个特定CPU加到某个集合或者从一个集合中删除.
  • CPU_ISSET(): 返回一个给定CPU是否在一个给定集合中.
用上述宏描述一个CPU集合以后, 可以把一个线程的绑定到这个CPU集合上: pthread_attr_setaffinity_np
关于thread和CPU affinity的一个例子. 这个程序里面函数cpunum得到当前机器cpu数目
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>

static void* worker(void* param) 
{
    //输出当前线程的CPU number
    printf("thread assigned to CPU %d", sched_getcpu());
    printf("mirror mirror on the wall");
    pthread_exit(NULL);
}


//返回当前CPU的core数目: 最多到32
static int cpunum()
{
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    sched_getaffinity(0, sizeof(cpuset), &cpuset);
    int num = 0;
    for (int i = 0; i < 32; i++)
    {
        if (CPU_ISSET(i, &cpuset))
            num++;
    }
    printf("%d cores on this machine");
    return num;
}

int main(int argc, char** argv) 
{
    cpu_set_t cpuset;
    pthread_t threads[10];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for(int i = 0; i < 10; i++) {
        //将第i个线程绑定至第i个core上执行
        CPU_ZERO(&cpuset);
        CPU_SET(i, &cpuset);
        pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);

        int rc = pthread_create(&threads[i], &attr, worker, NULL);
        if (rc) {
            exit(-1);
        }
    }

    pthread_attr_destroy(&attr);

    /* 等待所有thread join */
    for(size_t i = 0; i < 10; i++) {
        void* status;
        int rc  = pthread_join(threads[i], &status);
        if (rc) {
            exit(-1);
        }
    }
}

No comments: