Linux绑核效率优化

2023-11-20

Linux绑核效率优化

原理概述:

cpu一般有多个物理核心,但在运行进程和线程时候,可以将其绑定或者指定到某一个或者多个核心上运行。这样做的好处是:一般在核数比较多的机器上,会有多个CPU共享三级缓存cache的情况。当出现跨cache数据通信时,效率会比同一个cache内通信慢上一些。默认情况下程序运行时不会考虑cache的分组,哪个核空闲就会用哪一个。

在Linux上一般会用0-n给cpu进行编号,在目录/sys/devices/system/cpu/下不同的目录存放不同cpu的信息。

假如一个cpu有8个核,0-3共享一个cache,4-7共享一个cache,经测试程序运行时绑核在0,1,2,3会比由系统自行调度效率高出10-14%

在核数低于4核的CPU上,一般都只有一组缓存,这种情况下绑核不会有效率上的提升。

哪几个CPU在同一组并不是固定的,需要查看系统的配置信息,一般/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_map文件里以16进制数的形式记录了与cpu0共享三级缓存的cpu,比如00ff,其实就是00001111,就代表0-3号cpu与cpu0共享了同一块三级缓存,一般编程获取的方式使用此文件。

人为观察一般查看/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_list文件,一般的写法诸如0-5,12-17则代表0-5,12-17号cpu共享同一块三级缓存。

绑核方式

命令绑核:taskset

# 平时启动wps
./wps
# 绑核启动WPS
taskset -c 0,1,2,3 ./wps
# 代表将使用cpu0-cpu3执行wps进程

线程绑核

#include <stdio.h>
#include <stdlib.h>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>

#define NUM_OF_TASKS 5

long shared_cache_cpus;
cpu_set_t cpu_set;

int get_cpu_topo()
{
    int last_cache;
    char cache_info_path[100];
    char str[100];
    FILE *fp;

    //获取cpu有最后一级cache
    int i;
    for (i = 0;i < 5;++i) {
        sprintf(cache_info_path, "/sys/devices/system/cpu/cpu0/cache/index%d/shared_cpu_map", i);
        fp = fopen(cache_info_path, "r");
        if (fp == NULL)
            break;
        fclose(fp);
    }
    last_cache = i -1;

    //读取LLC中shared cache信息
    sprintf(cache_info_path, "/sys/devices/system/cpu/cpu0/cache/index%d/shared_cpu_map", last_cache);
    fp = fopen(cache_info_path, "r");
    if (fp == NULL) {
        perror("open file failed!!!");
        return -1;
    }
    fgets(str, 100, fp);
    shared_cache_cpus = strtol(str, NULL, 16);

    fclose(fp);

    return 0;
}

int bind_thread()
{
    long cpus;

    CPU_ZERO(&cpu_set);
    cpus = shared_cache_cpus;
    for (int i = 0;i < 64; ++i) {
        printf("cpu %d:: ", cpus);
        if (cpus&1) {
            CPU_SET(i, &cpu_set);
            printf("bind to cpu: %d\n", i);
        }

        cpus = cpus >> 1;
    }

    return 0;
}

void WasteTime(void)
{
    int abc = 1000;
    int temp = 0;

    while(abc--)
        temp = 10000*10000;

    sleep(1);
}
 
void *thread_func(void *param)
{
    while(1)
    {
        if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set) < 0)
            perror("pthread_setaffinity_np");
        WasteTime();
    }
}

int main()
{
    pthread_t my_thread[NUM_OF_TASKS];

    if (get_cpu_topo() == 0) {
        bind_thread();
    }

    for (int t = 0;t < NUM_OF_TASKS; ++t) {
        if (pthread_create(&my_thread[t], NULL, thread_func, NULL) != 0) {
            perror("pthread_create ERROR!!!");
            return -1;
        }
    }

    for (int t = 0;t < NUM_OF_TASKS; ++t) {
        pthread_join(my_thread[t], NULL);
    }

    pthread_exit(NULL);

    return 0;
}

进程绑核

#include <unistd.h>
#include <sched.h>
#include <sys/sysinfo.h>
#define MAX_CPU_CACHE_LEVEL 5  // cpu最高三级缓存,从0开始循环,取到4确保能拿到最高值

int bindProcess()
{
    //根据cpu共享cache的情况进行绑核,提升运行效率。
    if (get_nprocs() <= 4)
        return 0;

    char cache_info_path[100] = {'\0'};
    char str[100] = {'\0'};

    //获取cpu有最后一级cache
    int i;
    for (i = 0; i < MAX_CPU_CACHE_LEVEL; ++i) 
    {
        sprintf(cache_info_path, "/sys/devices/system/cpu/cpu0/cache/index%d/shared_cpu_map", i);

        if (0 != access(cache_info_path, R_OK))
            break;
    }

    int last_cache = i - 1;

    //读取LLC中shared cache信息
    sprintf(cache_info_path, "/sys/devices/system/cpu/cpu0/cache/index%d/shared_cpu_map", last_cache);
    FILE *fp = fopen(cache_info_path, "r");
    if (fp == NULL) 
    {
        perror("open file failed!!!");
        return -1;
    }
    fgets(str, 100, fp);
    //移除str中的',',否则在有些多核系统上转long会失败
    int j = 0, k = 0;
    while(str[j] != '\0')
    {
        if (str[j] != ',')
        {
            str[k++] = str[j];
        }
        j++;
    }
    str[k] = str[j];
    long shared_cache_cpus = strtol(str, NULL, 16);

    fclose(fp);

    cpu_set_t cpu_set;
    CPU_ZERO(&cpu_set);
    for (int i = 0; i < 64; ++i) 
    {
        if (shared_cache_cpus & 1) 
        {
            CPU_SET(i, &cpu_set);
        }
        shared_cache_cpus = shared_cache_cpus >> 1;
    }
    
    sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
    return 0;
}

在自己的项目代码中嵌入

只需要在main函数执行Exec前,调用上述bindProcess函数即可

参考资料

• https://en.wikipedia.org/wiki/CPU_cache#Cache_miss
• https://blog.csdn.net/fanyun_01/article/details/102788269
• https://blog.csdn.net/ethercat_i7/article/details/105717152

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux绑核效率优化 的相关文章

  • 从父类调用子类方法

    a doStuff 方法是否可以在不编辑 A 类的情况下打印 B did stuff 如果是这样 我该怎么做 class Program static void Main string args A a new A B b new B a
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj

随机推荐

  • element 中 datepicker设置,只能选中今天以及之前日期

    1 只能选择当前及以后的日期
  • 六,RBAC简介

    六 RBAC RBAC 基于角色的权限控制 role base access control 是一种设计模式 是用来设计和管理权限相关数据的一种模型 RBAC权限数据的管理 都是重复的CRUD的操作 这里我们就不再重复的从0到1开发 我们只
  • 在预训练时使用Warm Up的理解以及loss plateau。

    在预训练时使用Warm Up的理解 之前在wikitext 103上预训练Bert base的时候 发现loss曲线会平一段然后再下降 大概是像下图这样 横轴是step 纵轴是loss 当时的warm up是前16K step 一直以为第二
  • Python3 pip

    Python3 中的 pip 是一个常用的包管理工具 它可以用来下载 安装和卸载 Python 包 以下是一些常用的 pip 命令 1 安装包 pip install package name 例如 要安装 Flask 框架 可以使用命令
  • C++中vector删除指定位置的元素

    1 可以用erase方法删除vector指定位置的元素 2 例程 include
  • IAR 编译异常记录

    问题一 问题描述 WARNING the connected j link is defective proper operation cannot be guaranteed 连接的J Link不良 无法保证正确操作 问题原因 驱动版本与
  • 138-139-----JS基础-----二级菜单-完成基本功能、过渡效果

    一 代码 这两节的代码还是有点的难度的 有这样的需求时 按照类似的接口去做即可 不一定要和他的需求完全一样 因为我看他的需求好像点开另一个 已经打开的选项会被自动关闭 这样感觉不好 因为可能用户有时想要看到所有的选项的要求
  • 五大学科竞赛(五)2018年第二十四届全国青少年信息学奥林匹克联赛初赛

  • 音频增加噪声低通滤波降噪的过程

    啊 clear all close all clc s Fsample B wavread music wav Ts 1 Fsample M length s 获取音频的数据长度 m 0 M 1 figure subplot 3 1 1 p
  • 微服务框架

    微服务框架 1 SOA思想 面向服务的架构 SOA 是一个组件模型 它将应用程序的不同功能单元 称为服务 进行拆分 并通过这些服务之间定义良好的接口和协议联系起来 接口是采用中立的方式进行定义的 它应该独立于实现服务的硬件平台 操作系统和编
  • 区块链数据的存储和更新

    目录 1 引言 2 主要流程 2 1数据库读取 2 1 1 从数据库加载块数据 2 1 2从数据库读取账户信息 2 2 区块链数据更新与回滚 2 2 1 交易数据 2 2 2 块数据 1 引言 在第一篇文章里我们从静态的角度讲解了以太坊的数
  • elasticsearch ES搜索权重设置(boost参数)

    摘要 7 Elasticsearch boost的搜索条件权重 lm324114的专栏 CSDN博客 boost es 摘要2 elasticsearch boost 简书 摘要3 Elasticsearch 10 Boost 提升权重 简
  • flutter ListView 滚动到最后一个items位置

    flutter 想要实现一个listview初始化时和数据变化后显示到列表的最末 简单地说就是像聊天窗或者是日志输出那样的情景 要在Flutter中实现在初始化时和数据变化后将ListView自动定位到最后一个item的位置 你可以使用Sc
  • 基于位置的 AR 应用程序开发最完整指南

    几年前 全世界都为 Pokemon Go 疯狂 虽然这款游戏令人难以置信的受欢迎程度正在缓慢下降 但增强现实已成为科技界的新趋势 并且正在自信地抢占市场份额 2020年 AR市场规模超过141亿美元 预计到2022年底将达到2092亿美元
  • 混合式A星代码解析_2 规划主程序Planner.cpp

    3 规划程序 Planner cpp 在main cpp中 起主要作用的就是 HybridAStar Planner hy hy plan 规划算法都是在HybridAStar Planner这个类内部进行运算的 所以主要分析以下Plann
  • 客户端html跳到cas登出页面,CAS单点登录:单点登出及自定义登出界面(六)

    1 单点登出 1 1 参数说明 配置单点登出 配置允许登出后跳转到指定页面 cas logout followServiceRedirects false 跳转到指定页面需要的参数名为 service cas logout redirect
  • 扫描二维码进入体验版小程序却一直进入线上版本?这个配置要注意!

    1 前期准备 服务器 域名 2 配置扫描普通二维码进入小程序页面 开发小程序过程中 我们会遇到很多不同的场景 其中 扫描普通二维码进入小程序就是其中之一 下面先来看下如何配置扫描普通二维码进入小程序 首先登录开发平台 打开开发管理 进入开发
  • 大端小端,LSB和MSB

    在verilog中碰到了lsb和msb 所以做一下解释 lsb 就是最低位有效 类似于wire 0 31 这样的顺序 msb 就是最高位有效 类似于wire 31 0 这样的顺序 还有计算机中还有大端小端的概念一块解释一下 举例 0X123
  • 2022/9/6小结

    成长 是一个探索自我的过程 看 了不起的我 这本书 不知道是那句话 那个段落 或者那一章触动到了我 曾经我无法发自内心地去读书 去感受书中的情感 或悲伤 或喜悦 曾经我迫切地想通过书籍获得一项技能 获得一种读书人的气质 很幼稚 我不是在读书
  • Linux绑核效率优化

    Linux绑核效率优化 原理概述 cpu一般有多个物理核心 但在运行进程和线程时候 可以将其绑定或者指定到某一个或者多个核心上运行 这样做的好处是 一般在核数比较多的机器上 会有多个CPU共享三级缓存cache的情况 当出现跨cache数据