X86 什么';这是LDQU si256和loadu si256之间的区别

X86 什么';这是LDQU si256和loadu si256之间的区别,x86,simd,intrinsics,avx,micro-optimization,X86,Simd,Intrinsics,Avx,Micro Optimization,根据我在网上找到的一个例子,我一直在使用\u mm256\u lddqu\u si256。后来我发现了\u mm256\u loadu\u si256。《英特尔Intrinsics指南》仅指出,lddqu版本在跨越缓存线边界时性能可能会更好。loadu的优点是什么?一般来说,这些函数是如何不同的?< P> 没有理由使用 MM256YLDQQUIX256< /代码> ,将其视为的同义词:MM256ILUBUIXSI256code>lddqu仅因历史原因而存在,因为x86正在朝着更好的未对齐向量加载

根据我在网上找到的一个例子,我一直在使用
\u mm256\u lddqu\u si256
。后来我发现了
\u mm256\u loadu\u si256
。《英特尔Intrinsics指南》仅指出,
lddqu
版本在跨越缓存线边界时性能可能会更好。
loadu
的优点是什么?一般来说,这些函数是如何不同的?

< P> <强>没有理由使用<代码> MM256YLDQQUIX256< /代码> <强>,将其视为<代码>的同义词:MM256ILUBUIXSI256code>lddqu仅因历史原因而存在,因为x86正在朝着更好的未对齐向量加载支持发展,并且支持AVX版本的CPU运行它们的方式相同。没有AVX512版本

并发出该指令,因此如果希望代码以相同的方式运行,但具有不同的校验和或机器代码字节,则可以使用该指令


没有x86微体系结构运行的
vlddqu
vmovdqu
有任何不同。即,两个操作码可能在所有AVX CPU上解码为同一个内部uop。它们可能总是会的,除非出现一些非常低功耗或专门的微体系结构,而没有有效的未对齐向量负载(这是自Nehalem以来的事情)。编译器在自动矢量化时从不使用
vlddqu

lddqu
与奔腾4上的
movdqu
不同。请参阅。

lddqu
允许(并且在P4上允许)两个对齐的16B加载,并获取该数据的窗口
movdqu
架构上仅从预期的16字节加载这对存储转发有影响:如果您正在加载刚与未对齐存储一起存储的数据,请使用
movdqu
,因为存储转发仅适用于完全包含在以前存储中的加载。但除此之外,您通常希望使用
lddqu
。(这就是为什么他们不只是让
movdqu
始终使用“好方法”,而是为程序员引入了一条新的指令来担心。但幸运的是,他们改变了设计,所以我们不必再担心使用哪条未对齐的加载指令。)

它还对不可缓存(UC)或不可缓存推测写组合(UCSW,又名WC)内存类型(其后面可能有MMIO寄存器)的可观察行为的正确性有影响


两条asm指令中没有代码大小差异:

  # SSE packed-single instructions are shorter than SSE2 integer / packed-double
  4000e3:       0f 10 07                movups xmm0, [rdi]   

  4000e6:       f2 0f f0 07             lddqu  xmm0, [rdi]
  4000ea:       f3 0f 6f 07             movdqu xmm0, [rdi]

  4000ee:       c5 fb f0 07             vlddqu xmm0, [rdi]
  4000f2:       c5 fa 6f 07             vmovdqu xmm0, [rdi]
  # AVX-256 is the same as AVX-128, but with one more bit set in the VEX prefix

在Core2和更高版本上,没有理由使用
lddqu
,但与
movdqu
相比,也没有缺点。Intel放弃了Core2的特殊
lddqu
功能,因此这两个选项都很糟糕

特别是在Core2上,在具有两个对齐加载和SSSE3
palignr
的软件中避免缓存线分裂有时是对
movdqu
的胜利,尤其是在第二代Core2(Penryn)上,
palignr
在Merom/Conroe上只是一个随机uop,而不是2个。(Penryn将洗牌执行单元扩展到128b)

请参阅Dark Shikaris 2009年一篇x264开发人员日志:了解更多关于旧时代未对齐的加载策略的信息

Core2之后的一代是Nehalem,其中
movdqu
是一条uop指令,在加载端口中具有专用硬件支持。告诉编译器指针何时对齐仍然很有用(特别是对于自动矢量化,尤其是在没有AVX的情况下),但对他们来说,到处使用
movdqu
并不是性能灾难,特别是如果数据实际上在运行时对齐


我根本不知道英特尔为什么要生产一款AVX版的
lddqu
。我想对于解码器来说,在所有模式下(使用传统SSE前缀,或使用AVX128/AVX256),只将该操作码作为
movdqu
/
vmovdqu
的别名,而不是将该操作码解码为其他带有VEX前缀的操作码更简单

所有当前支持AVX的CPU都具有高效的硬件未对齐加载/存储支持,可以尽可能以最佳方式处理它。e、 g.当数据在运行时对齐时,与
vmovdqa
相比,性能差异完全为零

尼哈勒姆的情况并非如此
movdqu
lddqu
用于解码到多个uop,以处理潜在的未对齐地址,而不是将硬件支持放在加载端口中,在加载端口中单个uop可以激活它,而不是在未对齐的地址上出错

但是,256b版本可以加载多达64个字节(取决于实现):

如果源操作数跨越缓存线边界,则此指令可能会提高相对于(V)MOVDQU的性能。在需要修改(V)LDDQU加载的数据并将其存储到同一位置的情况下,使用(V)MOVDQU或(V)MOVDQA代替(V)LDDQU。要将双四字移入或移出已知在16字节边界上对齐的内存位置,请使用(V)MOVDQA指令

IDK其中有多少是故意写的,有多少是在更新AVX条目时预先添加的
(V)
。我不认为英特尔的优化手册建议在任何地方使用
vlddqu
,但我没有检查


没有AVX512版本的
vlddqu
,因此我认为这意味着英特尔已经决定,替代策略未对齐的加载指令不再有用,甚至不值得保留它们的选项。

哎呀,我忘了我已经写了关于非AVX
lddqu
的大部分历史资料。(包括相同的链接,因为我记得搜索相同的内容。)