1. 程式人生 > >程序,執行緒,核心設定cpu親和性

程序,執行緒,核心設定cpu親和性

程序與cpu繫結

sched_setaffinity可以將某個程序繫結到一個特定的CPU。

SCHED_SETAFFINITY(2)                                                                      Linux Programmer's Manual                                                                     SCHED_SETAFFINITY(2)

NAME
       sched_setaffinity, sched_getaffinity - set and get a process's CPU affinity mask

SYNOPSIS
       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <sched.h>

       int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
       /*該函式設定程序為pid的這個程序,讓它執行在mask所設定的CPU上.如果pid的值為0,
        *則表示指定的是當前程序,使當前程序執行在mask所設定的那些CPU上.
        *第二個引數cpusetsize是mask所指定的數的長度.通常設定為sizeof(cpu_set_t).
        *如果當前pid所指定的程序此時沒有執行在mask所指定的任意一個CPU上,
        *則該指定的程序會從其它CPU上遷移到mask的指定的一個CPU上執行.*/

       int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
       /*該函式獲得pid所指示的程序的CPU位掩碼,並將該掩碼返回到mask所指向的結構中.
        *即獲得指定pid當前可以執行在哪些CPU上.
        *同樣,如果pid的值為0.也表示的是當前程序*/

RETURN VALUE
       On success, sched_setaffinity() and sched_getaffinity() return 0.  On error, -1 is returned, and errno is set appropriately.

設定cpu affinity還需要用到一下巨集函式

void CPU_ZERO (cpu_set_t *set)
/*這個巨集對 CPU 集 set 進行初始化,將其設定為空集。*/
void CPU_SET (int cpu, cpu_set_t *set)
/*這個巨集將 指定的 cpu 加入 CPU 集 set 中*/
void CPU_CLR (int cpu, cpu_set_t *set)
/*這個巨集將 指定的 cpu 從 CPU 集 set 中刪除。*/
int CPU_ISSET (int cpu, const cpu_set_t *set)
/*如果 cpu 是 CPU 集 set 的一員,這個巨集就返回一個非零值(true),否則就返回零(false)。*/

下面下一個具體的例子:將當前程序繫結到0、1、2、3號cpu上

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/* sysconf( _SC_NPROCESSORS_CONF ) 檢視cpu的個數;列印用%ld長整。
 * sysconf( _SC_NPROCESSORS_ONLN ) 檢視在使用的cpu個數;列印用%ld長整 */
int main(int argc, char **argv)
{
    int cpus = 0;
    int  i = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_CONF);
    printf("cpus: %d\n", cpus);

    CPU_ZERO(&mask);    /* 初始化set集,將set置為空*/
    CPU_SET(0, &mask);  /* 依次將0、1、2、3號cpu加入到集合,前提是你的機器是多核處理器*/
    CPU_SET(1, &mask);
    CPU_SET(2, &mask);
    CPU_SET(3, &mask);
    
    /*設定cpu 親和性(affinity)*/
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
        printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    }   
    usleep(1000); /* 讓當前的設定有足夠時間生效*/

    /*檢視當前程序的cpu 親和性*/
    CPU_ZERO(&get);
    if (sched_getaffinity(0, sizeof(get), &get) == -1) {
        printf("get CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    }   
    
    /*檢視執行在當前程序的cpu*/
    for(i = 0; i < cpus; i++) {

        if (CPU_ISSET(i, &get)) { /*檢視cpu i 是否在get 集合當中*/
            printf("this process %d of running processor: %d\n", getpid(), i); 
        }    
    }
    sleep(3); //讓程式停在這兒,方便top命令檢視
       
    return 0;
}

執行結果如下:

[[email protected] test]# ./test    
cpus: 24
this process 2848 of running processor: 0
this process 2848 of running processor: 1
this process 2848 of running processor: 2
this process 2848 of running processor: 3

另外一份我自己寫的參考程式碼位置:繫結程序到指定cpu


執行緒與cpu繫結

執行緒綁定於程序的區別是所用函式不一樣,執行緒繫結用到下面兩個函式

NAME
       pthread_setaffinity_np, pthread_getaffinity_np - set/get CPU affinity of a thread

SYNOPSIS
       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <pthread.h>

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

       Compile and link with -pthread.

DESCRIPTION
       The  pthread_setaffinity_np()  function  sets the CPU affinity mask of the thread thread to the CPU set pointed to by cpuset.  If the call is successful, and the thread is not
       currently running on one of the CPUs in cpuset, then it is migrated to one of those CPUs.

       The pthread_getaffinity_np() function returns the CPU affinity mask of the thread thread in the buffer pointed to by cpuset.

       For more details on CPU affinity masks, see sched_setaffinity(2).  For a description of a set of macros that can be used to manipulate and inspect CPU sets, see CPU_SET(3).

       The argument cpusetsize is the length (in bytes) of the buffer pointed to by cpuset.  Typically, this argument would be specified as sizeof(cpu_set_t).  (It may be some  other
       value, if using the macros described in CPU_SET(3) for dynamically allocating a CPU set.)

RETURN VALUE
       On success, these functions return 0; on error, they return a nonzero error number

下面同樣是個具體的例子:將當前執行緒繫結到0、1、2、3號cpu上

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>

void *testfunc(void *arg)
{
    int i, cpus = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_CONF);
    printf("this system has %d processor(s)\n", cpus);
    
    CPU_ZERO(&mask);
    for (i = 0; i < 4; i++) { /*將0、1、2、3新增到集合中*/
        CPU_SET(i, &mask);
    }   

    /* 設定cpu 親和性(affinity)*/
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
        fprintf(stderr, "set thread affinity failed\n");
    }   
    
    /* 檢視cpu 親和性(affinity)*/
    CPU_ZERO(&get);
    if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
        fprintf(stderr, "get thread affinity failed\n");
    }   

    /* 檢視當前執行緒所執行的所有cpu*/
    for (i = 0; i < cpus; i++) {
        if (CPU_ISSET(i, &get)) {
            printf("this thread %d is running in processor %d\n", (int)pthread_self(), i); 
        }   
    }   
    sleep(3); //檢視
    
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[])
{
    pthread_t tid;
    if (pthread_create(&tid, NULL, (void *)testfunc, NULL) != 0) {
        fprintf(stderr, "thread create failed\n");
        return -1; 
    }   

    pthread_join(tid, NULL);
    return 0;
}

執行結果如下:

[[email protected] thread]# ./test                      
this system has 24 processor(s)
this thread 2812323584 is running in processor 0
this thread 2812323584 is running in processor 1
this thread 2812323584 is running in processor 2
this thread 2812323584 is running in processor 3

核心中繫結cpu

在核心裡如果要指定cpu, smp_call_function_single(),定義在kernel/smp.c


參考文章

  1. linux程序、執行緒與cpu的親和性(affinity)