DPDK的Cache预取和Cache一致性

news2024/10/6 8:38:06

1.什么是Cache预取

       众所周知,CPU访问Cache中的数据是比访问内存中的数据是要快的,而因为程序都有时间局部性和空间局部性,时间局部性简单来说就是某一条或几条指令在一段时间内会被CPU多次执行;空间局部性简单来说就是某一段数据块中的数据会被CPU多次访问。像这样的会被CPU多次执行和访问的指令和数据,将其放在Cache中,会提高CPU执行程序速度。Cache预取就是在这样的背景下诞生的。

       而Cache预取又分为硬件预取和软件预取。
       关于硬件预取,举一个例子:

// 程序1:
for (int i = 0; i < 1024; i++) {
    for (int j = 0; j < 1024; j++) {
        arr[i][j] = num++;
    }
}
// 程序2:
for (int i = 0; i < 1024; i++) {
    for (int j = 0; j < 1024; j++) {
        arr[j][i] = num++;
    }
}

       程序1是按照数组在内存中的保存方式顺序访问,而程序2则是跳跃式访问。对于程序1,硬件预取单元能够自动预取接下来需要访问的数据到Cache,节省访问内存的时间,从而提高程序1的执行效率;对于程序2,硬件不能够识别数据访问的规律,因而不会预取,从而使程序2总是需要再内存中读取数据,降低了执行效率。

在这里插入图片描述在这里插入图片描述
       因此,硬件预取单元不一定能够提高程序执行的效率,所以一些体系架构的处理器增加了一些指令,作为软件预取指令。DPDK中也有相关预取函数,如:rte_ixgbe_prefetch(sw_ring[rx_id].mbuf); // 预取下一个控制结构体mbuf
rte_packet_prefetch((char*)rxm->buf_addr + rxm->data_off); // 预取报文
       DPDK必须保证所有需要读取的数据都在Cache中,否则一旦出现Cache不命中,性能将会严重下降。为了保证这一点,DPDK采用了多种技术来进行优化,预取只是其中一种。

3.什么是Cache一致性

       当我们定义了一个数据结构或者分配了一段数据缓冲区之后,在内存中就有一个地址和其相对应,然后程序就可以对它进行都写。对于读,首先是从内存加载到Cache,最后送到处理器内部的寄存器;对于写,则是从寄存器送到Cache,最后通过总线写回内存,这两个过程就引出了两个问题:
       问题1:该数据结构或者数据缓冲区的起始地址是Cache Line对齐的吗?如果不是,即使该数据区域大小小于Cache Line,那么也需要占用两个Cache entry;并且,假设第一个Cache Line前半部分属于另外一个数据结构并且另外一个处理器正在处理它,那么当两个核都修改了该Cache Line从而写回各自一级的Cache,准备送回内存时,如何同步数据?毕竟每个核都只修改了该Cache Line的一部分。

       对于这个问题,一个解决办法就是定义该数据结构或者数据缓冲区时就申明对齐,DPDK对很多结构体定义的时候就是如此操作的。例如:

struct rte_ring_debug_status {
    uint64_t enq_success_bulk;
    uint64_t enq_success_objs;
    uint64_t enq_quota_bulk;
    uint64_t enq_quota_objs;
    uint64_t enq_fail_bulk;
    uint64_t enq_fail_objs;
    uint64_t deq_success_bulk;
    uint64_t deq_success_objs;
    uint64_t deq_fail_bulk;
    uint64_t deq_fail_objs;
} __rte_cache_aligned;

       __rte_cache_aligned的定义如下所示:

#define RTE_CACHE_LINE_SIZE 64
#define __rte_cache_aligned __attribute((__aligned(RTE_CACHE_LINE_SIZE)))

       问题2:假设该数据结构或者数据缓冲区的起始地址是Cache Line对齐的,但是有多个核同时对该段内存进行读写,当同时对内存进行写回操作时,如何解决冲突?

       对于这个问题,DPDK解决的方案是:避免多个核访问同一个内存地址或者数据结构。这样,每个核尽量都避免与其他核共享数据,从而减少因为错误的数据共享(cache line false sharing)导致的Cache一致性的开销。
以下是两个DPDK为了避免Cache一致性的例子。
       例子1:数据结构定义。DPDK的应用程序很多情况下都需要多个核同时来处理事务,因而,对于某些数据结构,我们给每个核都单独定义一份,这样每个核都只访问属于自己核的备份。如下:

struct lcore_conf {
    uint16_t n_rx_queue;
    struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
    uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
    struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];
    lookup_struct_t * ipv4_lookup_struct;
    lookup_struct_t * ipv6_lookup_struct;
} __rte_cache_aligned;    // Cache行对齐
struct lcore_conf lcore[RTE_MAX_LCORE] __rte_cache_aligned;

       以上的数据结构“struct lcore_conf”总是以Cache行对齐,这样就不会出现该数据结构横跨两个Cache行的问题。而定义的数组“lcore[RTE_MAX_LCORE]”中RTE_MAX_LCORE指一个系统中最大核的数量。DPDK中对每个核都进行了编号,这样n就只需要访问lcore[n],核m只需要访问lcore[m],这样就避免了多个核访问同一个结构体。

       例子2:对网络端口的访问。在网络平台中,少不了访问网络设备,比如网卡。多核情况下,有可能多个核访问同一个网卡的接收队列/发送队列,也就是在内存中的一段内存结构。这样,也会引起Cache一致性问题。那么DPDK是如何解决这个问题的呢?

       网卡设备一般都具有多队列的能力,也就是说,一个网卡有多个接收队列和多个访问队列。在DPDK中,如果有多个核可能需要同时访问同一个网卡,那么DPDK就会为每个核都准备一个单独的接受队列/发送队列。这样,就避免了竞争,也避免了Cache一致性问题。
       如下图:
在这里插入图片描述
       上图是四个核同时访问两个网络端口(即两个网卡)的图示。其中,网卡1和网卡2都有两个接收队列核四个发送队列;核0到核3每个都有自己的一个接收队列和一个发送队列。核0从网卡1的接收队列0接收数据,可以发送到网卡1的发送队列0或者网卡2的发送队列0;同理,核3从网卡2的接收队列1接收数据,可以发送到网卡1的发送队列3或者网卡2的发送队列3。

       Cache一致性问题最根本的原因是处理器内部不只一个核,当两个或多个核访问内存中同一个Cache行的内容时,就会因为多个Cache同时缓存了该内容引起同步问题。
       而上面DPDK对于问题2的解决办法很好的解决了这个问题。

       文章参考《深入浅出DPDK》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1849931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Electron快速入门(三):在(二)的基础上修改了一个文件夹做了个备忘录

Lingering Memories 诗绪萦怀 修改index.html <!--index.html--> <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --><meta http…

ES数值类型慢查询优化

现象 某个查询ES接口慢调用告警&#xff0c;如图&#xff0c;接口P999的耗时都在2500ms: 基本耗时都在查询ES阶段&#xff1a; 场景与ES设定 慢调用接口为输入多个条件分页查询&#xff0c;慢调用接口调用的ES索引为 express_order_info&#xff0c;该索引通过DTS(数据同步…

FlinkSQL开发经验分享

最近做了几个实时数据开发需求&#xff0c;也不可避免地在使用Flink的过程中遇到了一些问题&#xff0c;比如数据倾斜导致的反压、interval join、开窗导致的水位线失效等问题&#xff0c;通过思考并解决这些问题&#xff0c;加深了我对Flink原理与机制的理解&#xff0c;因此将…

Ubuntu配置ssh+vnc(完整版)

Ubuntu配置sshvnc&#xff08;完整版&#xff09; 1 配置ssh 1. 安装openssh-server&#xff0c;配置开机自启 # 更新包 sudo apt-get update # 安装openssh-server sudo apt-get install -y openssh-server # 启动服务 sudo service ssh start # 配置开机自启 sudo systemc…

corepack管理包管理器;nvm管理node版本;nrm管理npm源地址

corepack corepack 管理"包管理器"&#xff0c;包括 yarn 和 pnpm。corepack 并不能管理 npm。 corepack 是 nodejs 提供的功能&#xff0c;安装 nodejs 时 corepack 就一起安装了。它还是实验性功能&#xff0c;默认是关闭的&#xff0c;具体介绍看官方文档。 注…

DevOps学习回顾01-技能发展路线-岗位能力-体系认知

事为先&#xff0c;人为重–事在人为 参考来源&#xff1a; 极客时间专栏&#xff1a;DevOps实战笔记&#xff0c;作者&#xff1a;石雪峰 课程链接&#xff1a;https://time.geekbang.org/column/intro/235 时代的典型特征 VUCA VUCA 是指易变性&#xff08;Volatility&…

高性能并行计算华为云实验一:MPI矩阵运算

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建矩阵乘法源码 3.1.1 实验说明 3.1.2 实验步骤 3.2 创建卷积和池化操作源码 3.2.1 实验说明 3.2.2 实验步骤 3.3 创建Makefile文件并完成编译 3.4 建立主机配置文件与运行监测 四、实验结果与分析 4.1 矩阵乘法…

qt 简单实验 一个可以向右侧拖拽缩放的矩形

1.概要 目的是设置一个可以拖拽缩放的矩形&#xff0c;这里仅用右侧的一个边模拟这个过程。就是为了抓住核心&#xff0c;这个便解决了&#xff0c;其他的边也是一样的。而这个更能体现原理。 2.代码 2.1 resizablerectangle.h #ifndef RESIZABLERECTANGLE_H #define RESIZ…

Linux驱动调试——使用DEVICE_ATTR实现cat、echo指令调试驱动

在平常做一些驱动调试的时候&#xff0c;每次都写应用去调试相对较麻烦&#xff0c;有一个非常便捷的操作方法就是使用device_attr&#xff0c;只需要执行shell指令例如echo和cat就可以看到效果&#xff0c;不需要再单独写一个测试demo。 看网上很多博客在这一块的使用上写的都…

RK3568平台(音频篇)RT5651解码芯片Codec驱动分析

一.Audio Codec的必要性 在理想状况下&#xff0c;对于录音过程&#xff0c;只需要将麦克风获取到的analog信号通过ADC转换为digital信号并存储即可&#xff0c;对于播放音过程&#xff0c;只需要将digital信号通过DAC转换为analog并输出到speaker播放即可。 但在实际的过程中…

C++ 编程技巧分享

侯捷 C 学习路径&#xff1a;面向对象的高级编程 -> STL库 -> C11新特性 -> cmake 1.1. C 与 C的区别 在C语言中&#xff0c;主要存在两大类内容&#xff0c;数据和处理数据的函数&#xff0c;二者彼此分离&#xff0c;是多对多的关系。不同的函数可以调用同一个数据…

Docker开机自动重启及自动启动容器

Docker开机自动重启及自动启动容器 Windows开机自动重启设置容器自动启动 Windows开机自动重启 勾选 Start Docker Desktop when you sign in to your computer 设置容器自动启动 1.docker update 命令 Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]Update co…

32.基于分隔符解决黏包和半包

LineBasedFrameDecoder 基于换行/n (linux)或回车换行/r/n(windows)进行分割。 使用LIneBasedFrameDecoder构造方法,需要设定一个最大长度。 如果超过了最大长度,还是没有找到换行符,就这位这个数据段太长了,抛出ToolLongFrameException DelimiterBasedFrameDecoder …

IF膨胀时代,“水刊”当赢?2023热门“水刊”影响因子详解!

【欧亚科睿学术】 1 “四大水刊”详情 图片来源&#xff1a;欧亚科睿学术整理 “四大水刊”的影响因子均有所下跌&#xff0c;其中&#xff0c;曾经被列入中科院预警名单的期刊MEDICINE&#xff0c;其影响因子已是连续三年持续下降。从JCR分区来看&#xff0c;四本期刊分区均…

新手(初学者)学R语言第一课,从学正确导入数据开始

初看题目好像我在教你怎么导入数据&#xff0c;不不不&#xff0c;我是在教你正确的导入数据&#xff0c;不是说数据导入R就叫正确导入数据了。本章为新手教程&#xff0c;老手可以跳过。 这个内容早就想写了&#xff0c;今天有点空和大家聊一下。为什么R语言对于新手而言不太友…

threeJS 基础 03---动画

1.动画效果渲染循环 注&#xff1a; 使用循环渲染时&#xff0c;不用手动渲染到画布且再次调用监听更新事件&#xff0c;两者只用使用其中之一即可 周期循环&#xff0c;默认理想状态下每秒循环60次 requestAnimationFrame 渲染帧率&#xff08;详情见threeJs的文档&#xff…

区块链会议投稿资讯CCF A--WINE 2024 截止7.15 附录用率 附录用的区块链文章

Conference&#xff1a;The Conference on Web and Internet Economics (WINE) CCF level&#xff1a;CCF A Categories&#xff1a;Cross-cutting/comprehensive/emerging Year&#xff1a;2024 Conference time&#xff1a; December 2-5, 2024 录用率&#xff1a; sele…

Pyqt5 + Qt Creator实现QML开发环境配置

先安装Qt Creator, 该软件主要是为了编辑QML文件 在pycharm中配置外部插件&#xff0c;实现Qt Creator的调用 配置完成后&#xff0c;右击qml文件选择Qt Creator就可以直接进行编辑了

高效22KW双向DCDC储能、充电电源模块项目设计开发

22kW 双向CLL谐振变换器的目标是输出电压范围宽、高效率和高功率密度的双向应用&#xff0c;如电动汽车车载充电器和储能系统。研究了一种新的灵活的 CLLC 双向谐振变换器增益控制方案&#xff0c;以便在充放电模式下实现高效率和宽电压增益范围。得益于 Wolfspeed C3MTM 1200V…

Python+Selenium自动化入门

本章内容需有一定Python基础&#xff0c;如何不懂的&#xff0c;请先学习Python。 什么&#xff1f;&#xff1f;没有好的学习资料&#xff0c;给你准备好了&#xff01;&#xff01; Web自动化环境搭建 1、软件准备 python64位安装包chrome64位浏览器&驱动浏览器驱动下…