[TOC] > `Cache Line`作为`Cache`的基本组织单位,其大小包括32,64,128.其中较新的`X86`和`ARM`架构的`cpu`的大小为64,对于Cache的读和写过程会导致有两个问题: - Cache Line不对齐,由于不对齐,它占用了两个Cache entry,多个核使用他分布的不同的块,产生了冲突. - Cache Line对齐,但是由于多核问题,同时对同段内存进行读和写,产生冲突. Cache的一致性问题在意多处理器独占Cache而不是多个处理器的问题. ## Cache对齐 DPDK对很多的结构体使用了64字节对齐,例如: ```c struct a_b{ uint32_t a; uint64_t b; uint64_t c; }__rte_cache_aligned; ``` 其中DPDK在内部给__rte_cache_aligned做了定义,如下所示: ```c #define RTE_CACHE_LINE_SIZE 64 #define __rte_cache_aligned __attribute__((__aligned__(RTE_CACHE_LINE_SIZE))) ``` ## Cache一致性协议 - 基于目录的协议 - 总线窥探协议 ## MESI协议 > 处理器上有一套完整的协议,来保证Cache一致性。比较经典的Cache一致性协议当属MESI协议,奔腾处理器有使用它,很多其他的处理器都是使用它的变种。 单核Cache中每个Cache line有2个标志:dirty和valid标志,它们很好的描述了Cache和Memory(内存)之间的数据关系(数据是否有效,数据是否被修改),而在多核处理器中,多个核会共享一些数据,MESI协议就包含了描述共享的状态。 在MESI协议中,每个Cache line有4个状态,可用2个bit表示,它们分别是: |状态 | 描述 | |------|-----| |M(Modified) |这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。| |E(Exclusive) |这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。| |S(Shared) |这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。| |I(Invalid) | 这行数据无效。| - M(Modified)和E(Exclusive)状态的Cache line,数据是独有的,不同点在于M状态的数据是dirty的(和内存的不一致),E状态的数据是clean的(和内存的一致)。 - S(Shared)状态的Cache line,数据和其他Core的Cache共享。只有clean的数据才能被多个Cache共享。 - I(Invalid)表示这个Cache line无效。 ## DPDK如何保证Cache一致性 DPDK解决方案: 尽量避免多核访问同一数据结构 尽量避免多核访问同一内存地址 DPDK保证一致性的例子如下: - 保证为每个核单独定义一份结构体 ```C 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 ``` - 对网络端口的访问 网卡上有可能有多对`接收/发送的队列`,其中那`发送/接收队列`相当于内存中的结构,多核访问就会引起Cache一致性问题.解决方案如下: ```C DPDK为每个核都提供了一对单独的`发送/接收的队列` ``` ![](https://leanote.com/api/file/getImage?fileId=59685edfab64416bcf000d3d)