我正试图在两种算法之间做出决定。一个将8个字节(两个对齐的4字节字)写入2条缓存行,另一条写入3条完整的缓存行。
如果CPU只将更改的8字节写回内存,那么第一种算法使用的内存带宽要少得多:8字节对192字节。如果CPU写入整个缓存行,那么128字节和192字节之间的差异就不那么明显了。
那么Intel Xeon CPU是如何写回内存的呢?你会感到惊讶的是,在谷歌中找到一个应该广为人知的答案是多么困难。
据我所知,写入进入存储缓冲区,然后进入缓存。只有当脏缓存行被从缓存中移除时,它们才会被写入内存,但是Intel是跟踪缓存行的哪些部分是脏的,还是只是转储整个东西?我很怀疑它们是否跟踪缓存行粒度以下的内容。在缓存行被逐出之前,如果有任何东西进入内存,我也会感到非常惊讶。
发布于 2015-07-25 21:36:11
即使对DRAM本身来说,局部性也很重要,甚至对缓存也是如此。对于脏的缓存行,一个64B连续字节的突发写入比4B到16个不同地址的16次写入快得多。或者换一种说法,写回整个缓存行比在缓存行中只写几个更改的字节要慢得多。
由Ulrich编写的每个程序员都应该知道关于内存的事情解释了在编程时如何避免内存瓶颈的许多内容。他包括一些DRAM地址的细节。DRAM控制器必须选择一行,然后选择列。访问另一个虚拟内存页也会导致TLB失败。
DRAM确实有一个突发传输命令,用于传输一个连续的数据块.(显然是为CPU编写回缓存行而设计的)。现代计算机中的内存系统是针对编写整个缓存行的使用模式进行优化的,因为这种情况几乎总是发生的。
缓存线是CPU跟踪脏或不脏的单位。用比现在或不高速缓存线更小的线条来跟踪污秽是可能的,但这需要额外的晶体管,而且不值得。缓存的多个级别被设置为在周围传输整个缓存行,因此当需要读取整个缓存行时,它们可以尽可能快。
有所谓的非时态读写(movnti/movntdqa)绕过缓存.这些数据将用于数据,直到数据被从缓存中删除(因此是非时态数据),才会再次被访问。对于那些可以从缓存中获益的数据来说,它们是个坏主意,但是可以让您将4个字节写入内存,而不是整个缓存行。根据该内存范围的MTRR,写入可能会或不受写入组合的限制。(这与内存映射的i/o区域相关,其中两个相邻的4B写入与一个8B写入不相同。)
该算法只涉及两条缓存线,当然在这一点上具有优势,除非需要更多的计算,尤其是分支,才能确定要写哪个内存。如果你想要帮助做决定的话,可以问一个不同的问题。(请参阅https://stackoverflow.com/tags/x86/info的链接,尤其是Agner的指南,以获得帮助您自己做出决定的信息。)
有关在不同CPU上使用多个线程访问相同内存的危险的警告,请参见Cornstalks的回答。这可能会导致更大的减速,而不仅仅是单线程程序的额外写入。
发布于 2015-07-25 21:15:13
为了使CPU只将脏字节写回内存,它需要为缓存中的每个字节存储一个脏位。这是不可行的,而且不是在现代CPU上完成的(据我所知)。CPU对于缓存行只有一个脏位。写入缓存行中的任何字节会导致整行标记为脏。
当需要刷新脏缓存行时,需要编写整个行,因为CPU不知道哪个字节改变了。
这可以在缓存失效策略中看到,在这种策略中,写入一个核心中的一个缓存行可以使另一个核心中的高速缓存线失效(因为两个高速缓存线映射到同一个地址),即使第一个核心使用缓存线的一半,而第二个核心使用高速缓存线的上半部分。也就是说,如果core 1写入字节N,而core 2使用字节N+1,那么core 2仍然必须刷新其缓存行,尽管您和我都知道这是不必要的。
https://stackoverflow.com/questions/31631073
复制相似问题