• linux 将进程或者线程绑定到指定的cpu上


    基本概念

    cpu亲和性(affinity)
    CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将指定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提高。

    软亲和性(affinity)
    就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。
    硬亲和性(affinity)
    简单来说就是利用linux内核提供给用户的API,强行将进程或者线程绑定到某一个指定的cpu核运行。

    相关函数

    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)。*/
    

    进程与cpu的绑定

    #include <sched.h>
    
    int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
    int sched_getaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
    

    代码示例:

    #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
    ", 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
    ", 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
    ", 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
    ", getpid(), i); 
            }    
        }
        sleep(10); //让程序停在这儿,方便top命令查看
           
        return 0;
    }
    

    结果:

    线程与cpu的绑定

    #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, const cpu_set_t *cpuset);
    

    代码示例:

    #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)
    ", 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
    ");
        }   
        
        /* 查看cpu 亲和性(affinity)*/
        CPU_ZERO(&get);
        if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
            fprintf(stderr, "get thread affinity failed
    ");
        }   
    
        /* 查看当前线程所运行的所有cpu*/
        for (i = 0; i < cpus; i++) {
            if (CPU_ISSET(i, &get)) {
                printf("this thread %d is running in processor %d
    ", (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
    ");
            return -1; 
        }   
    
        pthread_join(tid, NULL);
        return 0;
    }
    

    结果:

    指定在哪个CPU上运行:

    void *threadfunc(void *arg)
    {
        cpu_set_t mask;
        
        cpu_set_t mask;
        int cpuid = 1;
        CPU_ZERO(&mask);
        CPU_SET(cpuid, &mask);
    
        /* 设置cpu 亲和性(affinity)*/
        if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
            fprintf(stderr, "set thread affinity failed
    ");
        }       
    }
    
  • 相关阅读:
    oracle数据库基础知识汇总—30天(一)
    SQL server
    mySQL 黑窗口运行命令
    MySQL
    常用网址
    常见浏览器JS引擎和内核
    nodejs
    audio标签自动播放在安卓播放正常,IOS不能自动播放
    Microsoft.Office.Interop.Excel Find 操作
    python 的os.getenv("PATH")和os.environ.get("PATH")的区别
  • 原文地址:https://www.cnblogs.com/chay/p/10587452.html
Copyright © 2020-2023  润新知