深入浅出dpdk笔记---------内存(二)

        内存方面还有一种优化方案,是预取。但是预取存在较多的局限性,需要把握好度和时机,虽然大多时候软件开发不需要关心底层硬件或者cache的预取机制,但是懂得它的原理对我们进行性能优化有很大的帮助。

1、预取
1.1 预取原理

时间局部性原理:系统即将用到的指令/数据可能就是当前使用的指令/数据

空间局部性原理:系统即将使用到的指令/数据可能就是相邻地址正在使用的

1.2 数据cache预取条件

cache预取需要满足以下条件:

(1)读写的数据是回写的,这是因为如果采用直写,会不停的把数据覆盖,预取是通过当前的数据去预计未来执行的数据,当前的数据不停的覆盖对未来执行的数据没有意义

(2)预取的请求必须在一个4K物理页的内部。这是因为对于程序员来说,虽然指令和数据的虚拟地址都是连续的,但是分配的物理页很有可能是不连续的。而预取是根据物理地址进行判断的,因此跨界预取的指令和数据很有可能是属于其他进程的,或者没有被分配的物理页

(3)处理器的流水线作业中没有fence或者lock这样的指令。这是说明流水线作业中没有其它进程,不存在竞争,如果存在竞争关系的话,当前的数据可能是另一个进程的,预取也就没有意义

(4)当前读取的预取指令没有很多不命中的情况,说明预取是生效的

(5)前端总线不是很忙,因为预取存在时间局部性,如果总线很忙,使得指令不能及时预取,违背时间局部性原理

(6)没有连续的存储(Store)指令。这个和第一条相似

1.3 硬件的预取条件

在Netburst架构的处理器中,硬件遵循以下原则来决定是否开启自动预取。

(1)必须是连续两次cache不命中,并且两次不命中的内存地址的位置偏差不能超过256或者512字节才会激活预取机制。这条有两个重点,连续两次不命中,并且地址偏差还不能太大。通过这两个条件说明处理的数据可能是一个连续的数据,即使当前连续的两个数据没有命中缓存,但根据局部性原理(空间局部性和时间局部性),接下来很可能要访问的数据依然位于这个连续的数据流中。预取机制在此时提前加载这些未来可能访问的数据到高速缓存,可以减少等待内存读取的时间延迟,从而提高处理器执行指令的速度。

(2)一个4K字节的页(Page)内,只定义一条流(Stream,可以是指令,也可以是数据)。因为处理器同时能够追踪的流是有限的。这个目的的作用是在处理单独的数据时,必须是单独的线程,这样预取才有意义。

(3)对4K字节的边界之外不进行预取。也就是说,预取只会在一个物理页(4K字节)内发生。这和一级数据Cache预取遵循相同的原则。

(4)预取的数据存放在二级或者三级Cache中

1.4 软件预取
为了方便软件开发者能够根据自己的需求提供了一些预取函数,预取要慎重,至于按理可以参考收发包流程中的预取流程。
2、cache一致性
cache的一致性是任何流程都绕不过去的一个主题,引用dpdk中的一段话:该数据结构或者数据缓冲区的起始地址是Cache Line对齐的吗?如果不是,即使该数据区域的大小小于Cache Line,那么也需要占用两个Cache entry;并且,假设第一个Cache Line前半部属于另外一个数据结构并且另外一个处理器核正在处理它,那么当两个核都修改了该Cache Line从而写回各自的一级Cache,准备送到内存时,如何同步数据?毕竟每个核都只修改了该Cache Line的一部分。由以上疑问引入了该流程的议题dpdk在提升性能方面如何保证一致性。
欲解决上述问题,首先引入一个概念chache line,什么是cache line? Cache line(缓存行)是计算机系统中高速缓存(Cache)进行数据存储和管理的最小单位。接下来解决上述问题的方案:
2.1 cache line对齐

就是定义该数据结构或者数据缓冲区时就申明对齐

2.2 一致性协议解决一致性问题
2.2.1 基于目录协议

基于目录协议的系统中,需要缓存在Cache的内存块被统一存储在一个目录表中,目录表统一管理所有的数据,协调一致性问题。该目录表类似于一个仲裁者,当处理器需要把一个数据从内存中加载到自己独占的Cache中时,需要向目录表提出申请;当一个内存块被某个处理器改变之后,目录表负责改变其状态,更新其他处理器的Cache中的备份,或者使其他处理器的Cache的备份无效。

2.2.2 MESI协议
MESI协议是Cache line四种状态的首字母的缩写,分别是修改(Modified)态、独占(Exclusive)态、共享(Shared)态和失效(Invalid)态。
(1)修改态
cache line在cache中有多个备份供进程调度,但是备份中只有一份能够处于这种状态,并且将该备份设置一个dirty的状态,拥有修改状态的cache line在某个合适的时间将内容写回内存,但是在写回之前,不能进行读操作,因为此时数据还没有同步,写回之后将修改态变成共享态
(2)独占态
这个状态和修改态相似,cache line在cache中有多个备份,其中只有一个cache line拥有这种状态。当它还有设置dirty的状态时,如果产生一个读请求,就变成了共享态,如果产生一个写请求就变成了修改态。这种状态有点像我有使用进程的权利,进可攻(写请求,设置成修改态),退可守(设置成读请求)
(3)共享态
可以在任何时候都变成其他三种状态。
(4)失效态
该Cache Line要么已经不在Cache中,要么它的内容已经过时。一旦某个Cache Line被标记为失效,那它就被当作从来没被加载到Cache中
2.3 dpdk如何保证cache的一致性

        DPDK的解决方案很简单,首先就是避免多个核访问同一个内存地址或者数据结构。这样,每个核尽量都避免与其他核共享数据,从而减少因为错误的数据共享(cache line false sharing)导致的Cache一致性的开销。说的简单一点,什么操作都是单独使用,比如线程的单独的收发包队列,线程利用亲和性绑核,使得资源在处理时不会存在竞争。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值