当数据位于 2 个不同的块中时,x86 存储
x86 store when data is in 2 different blocks
假设linux-32:对齐规则说,例如,double(8 字节)必须对齐到 4 字节。这意味着,如果我们假设 64 字节缓存块(现代处理器的典型值),我们可以在第 60 个位置有一个双精度对齐,这意味着这个双精度将在 2 个不同的缓存块中。
double 的两个部分甚至可能位于 2 个不同的 4KB 页面中的 2 个不同的缓存块中。
在对这个问题进行简要介绍后,我有几个疑问:
1- 对于追求最佳性能的汇编程序,建议通过放置对齐指令来防止这些事情发生,对吗?或者,出于我不知道的任何原因,仅在 1 个块中进行对齐并不意味着任何性能变化?
2- 在上述情况下,存储指令将如何解码? (假设现代英特尔微体系结构)。我的意思是,我知道正常的存储 x86 指令在一对微融合的 str-addr 和 str-data 中被解码,但在这种情况下,涉及 2 个不同的缓存块(甚至可能是 2 个不同的 4KB 页),这将在 2 个微融合的 str-addr 和 str-data 对中解码(一个用于 double 的前 4 个字节,另一个用于最后 4 个字节)?或者它将被解码为单个微融合对,但必须同时执行 str-addr 和 str-data 两倍的工作,直到最终能够退出执行端口?
是的,当然您应该尽可能对齐 double
,就像编译器一样,除非 ABI 结构布局规则强制它们不对齐。 (ABI 是在 i386 流行时设计的,所以 double 总是需要 2 个负载。)
当前版本的 i386 System V ABI 需要 16 字节堆栈对齐,因此可以对齐本地双精度数(必须溢出而不是保留在 regs 中),并且 malloc
必须return 适合任何类型的内存,而 alignof(max_align_t) = 16
在 32 位上 Linux (8 在 32 位上 Windows)所以 32 位 malloc 总是会给你至少 16 (或 8)字节对齐的内存。当然,在静态存储中,您可以使用 align
(NASM) 或 .p2align
(GAS) 指令控制对齐方式。
有关缓存行拆分和页面拆分的性能缺点,请参阅
回复:解码:地址在解码时未知,因此显然行拆分页面拆分的任何影响稍后解决。对于存储,在存储缓冲区条目必须提交到 L1d 缓存之前可能没有任何影响。 Are two store buffer entries needed for split line/page stores on recent Intel? - 可能不,在执行存储地址 uop 后分配第二个条目是不可信的。
对于加载,通过执行单元重新运行加载以获得另一半(或任何不均匀分割),使用内部行分割缓冲区来组合数据。 (不是从 RS 重新调度,只是在加载端口内部处理。但是 RS 会主动重放 uops 等待 加载结果。)
Re-运行 未对齐存储的存储数据 uop 似乎也不太可能。我认为我们没有看到 uops_dispatched_port.port_4
性能事件的额外计数。
假设linux-32:对齐规则说,例如,double(8 字节)必须对齐到 4 字节。这意味着,如果我们假设 64 字节缓存块(现代处理器的典型值),我们可以在第 60 个位置有一个双精度对齐,这意味着这个双精度将在 2 个不同的缓存块中。 double 的两个部分甚至可能位于 2 个不同的 4KB 页面中的 2 个不同的缓存块中。
在对这个问题进行简要介绍后,我有几个疑问:
1- 对于追求最佳性能的汇编程序,建议通过放置对齐指令来防止这些事情发生,对吗?或者,出于我不知道的任何原因,仅在 1 个块中进行对齐并不意味着任何性能变化?
2- 在上述情况下,存储指令将如何解码? (假设现代英特尔微体系结构)。我的意思是,我知道正常的存储 x86 指令在一对微融合的 str-addr 和 str-data 中被解码,但在这种情况下,涉及 2 个不同的缓存块(甚至可能是 2 个不同的 4KB 页),这将在 2 个微融合的 str-addr 和 str-data 对中解码(一个用于 double 的前 4 个字节,另一个用于最后 4 个字节)?或者它将被解码为单个微融合对,但必须同时执行 str-addr 和 str-data 两倍的工作,直到最终能够退出执行端口?
是的,当然您应该尽可能对齐 double
,就像编译器一样,除非 ABI 结构布局规则强制它们不对齐。 (ABI 是在 i386 流行时设计的,所以 double 总是需要 2 个负载。)
当前版本的 i386 System V ABI 需要 16 字节堆栈对齐,因此可以对齐本地双精度数(必须溢出而不是保留在 regs 中),并且 malloc
必须return 适合任何类型的内存,而 alignof(max_align_t) = 16
在 32 位上 Linux (8 在 32 位上 Windows)所以 32 位 malloc 总是会给你至少 16 (或 8)字节对齐的内存。当然,在静态存储中,您可以使用 align
(NASM) 或 .p2align
(GAS) 指令控制对齐方式。
有关缓存行拆分和页面拆分的性能缺点,请参阅
回复:解码:地址在解码时未知,因此显然行拆分页面拆分的任何影响稍后解决。对于存储,在存储缓冲区条目必须提交到 L1d 缓存之前可能没有任何影响。 Are two store buffer entries needed for split line/page stores on recent Intel? - 可能不,在执行存储地址 uop 后分配第二个条目是不可信的。
对于加载,通过执行单元重新运行加载以获得另一半(或任何不均匀分割),使用内部行分割缓冲区来组合数据。 (不是从 RS 重新调度,只是在加载端口内部处理。但是 RS 会主动重放 uops 等待 加载结果。)
Re-运行 未对齐存储的存储数据 uop 似乎也不太可能。我认为我们没有看到 uops_dispatched_port.port_4
性能事件的额外计数。