Linux CPU亲和性

CPU亲合力就是指在linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行。
一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行。在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能。

一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作:

cpu_set_t mask;
CPU_ZERO(&mask) 清空一个集合
CPU_SET(0, &mask) 将cpu0添加到集合mask中,本质为对应bit置1
CPU_CLR(0, &mask); 将cpu0从集合mask中移除,本质为对应bit清零
CPU_ISSET(1, &mask); 判断cpu1是否在集合mask中,在返回非零,不在返回0
CPU_COUNT(&mask);  返回集合set2中的CPU的个数
CPU_AND(&result, &set1, &set2);  set1和set2的所有bit按位与,结果存入result
CPU_OR(&result, &set1, &set2);  按位或
CPU_XOR(&result, &set1, &set2);  按位异或
CPU_EQUAL(&set1, &set2);  集合set1和集合set2相等的话,返回非零,不相等,返回0
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

函数简介
设置进程CPU亲和力
 
参数说明
pid: 进程ID,如果pid的值为0,则表示指定的是当前进程
cpusetsize:  mask所指定的数的长度
mask: CPU集合

返回值
执行成功,返回0,执行失败,返回-1,更新errno.
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

函数简介
获取进程CPU亲和力
 
参数说明
pid: 进程ID,如果pid的值为0,则表示指定的是当前进程
cpusetsize:  mask所指定的数的长度
mask: CPU集合

返回值
执行成功,返回0,执行失败,返回-1,更新errno.

绑核成功确认方法

taskset -pc [PID]

表明当前进程在cpu0,cpu1上运行

/* cpu亲和性设置 */

#define _GNU_SOURCE   /* 该宏不可缺少 */
#include <sched.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>

int test()
{
    int ret = 0;
    cpu_set_t mask;
    int num_cpus;
    int total = 0;
    int i, j, k;

    // 1.参数校验

    // 2.获取当前系统的cpu核数
    /*
    知识补充
        int sysconf(_SC_NPROCESSORS_CONF);
        返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因此该值并不代表当前系统中可用的核数

        int sysconf(_SC_NPROCESSORS_ONLN);
        返回值真正的代表了系统当前可用的核数
    */
    num_cpus = (int)sysconf(_SC_NPROCESSORS_ONLN);

    // 3.清空当前cpu集合
    CPU_ZERO(&mask);
    
    // 4.设置需要绑定的逻辑核
    /*
    设计说明:
        a. cpu绑核是从0开始的
        b. 进程绑定多个逻辑核时,现象不是在多个逻辑核之间切换,而是固定跑在一个逻辑核上,但是同时启动多个进程时,会发现每个进程跑在不同的逻辑核上
    */
    // 将cpu0添加到集合mask中,本质为对应bit置1
    CPU_SET(0, &mask);
    // 将cpu1添加到集合mask中,本质为对应bit置1
    CPU_SET(1, &mask);

    // 5.为当前进程绑核
    if (sched_setaffinity(0, sizeof(mask), &mask))
    {
        ret = -1;
        printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
        return ret;
    }

    // 6.计算操作
    for (k = 0; k < 100000; k += 1)
    {
        for (i = 0; i < 10000; i++)
        {
            for (j = 0; j < 1000; j++)
            {
                total = (i + j) * k;
            }
            total = i * k;
        }
    }

    printf("num_cpus %d, total %d\n", num_cpus, total);

    return ret;
}

int main()
{
    test();
    return 0;
}

 

posted on 2023-02-01 22:03  寒魔影  阅读(627)  评论(0编辑  收藏  举报

导航