zoukankan      html  css  js  c++  java
  • Linux中线程与CPU核的绑定

    最近在对项目进行性能优化,由于在多核平台上,所以了解了些进程、线程绑定cpu核的问题,在这里将所学记录一下。

        不管是线程还是进程,都是通过设置亲和性(affinity)来达到目的。对于进程的情况,一般是使用sched_setaffinity这个函数来实现,网上讲的也比较多,这里主要讲一下线程的情况。
        与进程的情况相似,线程亲和性的设置和获取主要通过下面两个函数来实现:
    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);
        从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的宏来进行清除、设置以及判断:
    //初始化,设为空
          void CPU_ZERO (cpu_set_t *set); 
          //将某个cpu加入cpu集中 
           void CPU_SET (int cpu, cpu_set_t *set); 
           //将某个cpu从cpu集中移出 
           void CPU_CLR (int cpu, cpu_set_t *set); 
           //判断某个cpu是否已在cpu集中设置了 
           int CPU_ISSET (int cpu, const cpu_set_t *set); 
           cpu集可以认为是一个掩码,每个设置的位都对应一个可以合法调度的 cpu,而未设置的位则对应一个不可调度的 CPU。换而言之,线程都被绑定了,只能在那些对应位被设置了的处理器上运行。通常,掩码中的所有位都被置位了,也就是可以在所有的cpu中调度。       
          以下为测试代码:

    点击(此处)折叠或打开

    1. #define _GNU_SOURCE
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <string.h>
    5. #include <unistd.h>
    6. #include <pthread.h>
    7. #include <sched.h>
    8. void *myfun(void *arg)
    9. {
    10.     cpu_set_t mask;
    11.     cpu_set_t get;
    12.     char buf[256];
    13.     int i;
    14.     int j;
    15.     int num = sysconf(_SC_NPROCESSORS_CONF);
    16.     printf("system has %d processor(s)\n", num);
    17.     for (= 0; i < num; i++) {
    18.         CPU_ZERO(&mask);
    19.         CPU_SET(i, &mask);
    20.         if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
    21.             fprintf(stderr, "set thread affinity failed\n");
    22.         }
    23.         CPU_ZERO(&get);
    24.         if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
    25.             fprintf(stderr, "get thread affinity failed\n");
    26.         }
    27.         for (= 0; j < num; j++) {
    28.             if (CPU_ISSET(j, &get)) {
    29.                 printf("thread %d is running in processor %d\n", (int)pthread_self(), j);
    30.             }
    31.         }
    32.         j = 0;
    33.         while (j++ < 100000000) {
    34.             memset(buf, 0, sizeof(buf));
    35.         }
    36.     }
    37.     pthread_exit(NULL);
    38. }
    39. int main(int argc, char *argv[])
    40. {
    41.     pthread_t tid;
    42.     if (pthread_create(&tid, NULL, (void *)myfun, NULL) != 0) {
    43.         fprintf(stderr, "thread create failed\n");
    44.         return -1;
    45.     }
    46.     pthread_join(tid, NULL);
    47.     return 0;
    48. }
           这段代码将使myfun线程在所有cpu中依次执行一段时间,在我的四核cpu上,执行结果为  :
           system has 4 processor(s)        
           thread 1095604544 is running in processor 0        
           thread 1095604544 is running in processor 1        
           thread 1095604544 is running in processor 2        
           thread 1095604544 is running in processor 3 
           在一些嵌入式设备中,运行的进程线程比较单一,如果指定进程线程运行于特定的cpu核,减少进程、线程的核间切换,有可能可以获得更高的性能。
  • 相关阅读:
    1、Jenkins的安装与简单配置
    2、jenkins+svn自动发布和回滚
    关于kafka生产者相关监控指标的理解(未解决)
    Zabbix中获取各用户告警媒介分钟级统计
    2-4、配置Filebeat使用logstash
    JS基础 浏览器弹出的三种提示框(提示信息框、确认框、输入文本框)
    C# winform 托盘控件的使用
    c# 将两个表的有效数据合到一个表中
    C# 认识 接口
    let 和 var 定义变量的区别
  • 原文地址:https://www.cnblogs.com/vanishfan/p/2773325.html
Copyright © 2011-2022 走看看