memory type
Memory Type
什么是Memory Type
每个内存区域都有自己的memory type,代表此内存区域的一些特性,例如数据是否会使用cache、访存操作是否可以reorder等等
Linux下可以通过以下命令查看
1 |
|
目前IA32中的memory type如下表所示
Memory Type and Mnemonic | read cacheable | write cacheable | read allocate | write allocate | Allows Speculative Reads | Memory Ordering Model |
---|---|---|---|---|---|---|
Strong Uncacheable(UC) | No | No | No | No | No | Strong Ordering |
Uncacheable (UC-) | No | No | No | No | No | Strong Ordering. Can only be selected through the PAT. Can be overridden by WC in MTRRs. |
Write Combining (WC) | No | No | No | No | Yes | Weak Ordering. Available by programming MTRRs or by selecting it through the PAT. |
Write-through (WT) | Yes | Yes | Yes | No | Yes | Speculative Processor Ordering |
Write Back(WB) | Yes | Yes | Yes | Yes | Yes | Speculative Processor Ordering |
Write protected(WP) | Yes | No | Yes | No | Yes | Speculative Processor Ordering. Available by programming MTRRs. |
Strong Uncacheable(UC) : 对于UC的内存读写操作都不会写到cache里,不会被reordering。
对于memory-mapped I/O device,UC很适用。SMP 系统上,各个 CPU 可以通过支持 cache 一致性协议的总线 snoop 到其他 CPU 对 cache 的读写,而通过 PCIe 连接的 CPU 和 GPU 则不能互相 snoop,如图一所示,因此从 CPU 的角度,显存算是 I/O memory,对其访问需要是 uncachable 的(注1)。reordering也会导致I/O device读到dirty data,比如说I/O device把这些内存作为一些控制用的寄存器使用。
对于普通用途的内存,UC会导致性能的急剧下降。
注1: 一种例外是,有些I/O device支持bus coherency protocol,可以和CPU保持cache一致性,这样的话是可以使用cacheable的内存的,但是这种总线协议也是有代价的。
Uncacheable (UC-): 和UC类型一样,除了UC- memory type可以通过设置MTRRs被改写为WC memory type.
Write Combining (WC): 文档,WC内存不会被cache,bus coherency protcol不会保证WC内存的读写。在WC类型的内存上的写操作会被延迟,数据会在cpu的WC buffer上被组合,这样可以减少总线上的访存操作。对同一地址的连续写,以最后一次写入的为准。
显存作为 frame buffer 有个特点,就是它容许对不同地址写操作的 combine 和 reorder(写入不同像素点的数据往往是不相关的),这和普通的 MMIO 是不同的,因此就有了 WC 这种相对特殊的类型
注2: Speculative read是指读之前并不验证内存的有效性,先冒险的读进来,如果发现不是有效数据再取消读取操作,并更新内存后再读取. 比如说数据还是被buffer在WC buffer中
Write back(WB):read 和 write 都 cache,在read 或者write miss时,都会同步写入数据到cache中
Write Through(WT):read 时 cache,write hit 时同步写入 cache line 和 main memory,而 write miss 时不分配 cache line(即没有 write allocate),直接写入 memory
Write protected(WP): 读操作和WT/WB没有什么区别,读会被cache. 写不一样,写的时候会在bus上传播这个操作,并且导致其他处理器上的cache lines被更新。主要用于多处理器的情况。WP的内存,在写的时候就会更新其他处理器上的cache,而WB/WT类型的内存需要等到其他处理读的时候才会去更形无效的cache
上述几种内存属性中,WB理论上性能最好,因为既不会使用cache,又可以reordering
可以得知,cache和out-of-order并不是两个独立的特性,memory type将他们交织在了一起
prefetch
1 |
|
从地址P处预取尺寸为cache line大小的数据缓存,参数i指示预取方式(_MM_HINT_T0, _MM_HINT_T1, _MM_HINT_T2, _MM_HINT_NTA,分别表示不同的预取方式)
- T0 预取数据到所有级别的缓存,包括L0
- T1 预取数据到除L0外所有级别的缓存
- T2 预取数据到除L0和L1外所有级别的缓存
- NTA 预取数据到非临时缓冲结构中,可以最小化对缓存的污染
NTA:non-temporal aligned,程序告诉处理器应该尽可能地避免以这个数据污染cache,因为数据只在一段很短的期间内会被使用
non-temporal的含义
- 将数据放入cache,但假设只使用一次。通常的实现方法是加载数据,但偏置 “最近最少使用 “位,这样新加载的行将被视为 “最近最少使用”,而不是默认的 “最近使用”。 PREFETCHNTA 指令似乎就是这样做的。 PREFETCHNTA 还会将数据拉入 L1 数据缓存(因此在被逐出时,不必被放入到 L2 或者更高层次的缓存中),但不会将数据放入到 L2 或 L3。
- 不将数据放在cache中,而是将其放在单独的cacheline大小的缓冲区,即WC Buffer中,以允许多次连续(部分cacheline)加载。 这就是 MOVNTDQA 和 VMOVNTDQA 指令的作用。 它们用于WC内存类型。
因此
- 在system memory中时,memory type一般不是WC,NT的作用是将数据尽可能快地从cache中逐出
- 在属性为WC的内存中,NT的作用是使用cpu的internal wirte buffer,不将数据放入到cache中。