- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设您要将rax
和rdx
中的值加载到xmm
寄存器中。
一种方法是:
movq xmm0, rax
pinsrq xmm0, rdx, 1
最佳答案
在最近的Intel或AMD上,您不会在延迟或uop计数方面做得更好(我主要查看Agner Fog的Ryzen / Skylake表)。对于相同的端口,movq+movq+punpcklqdq
也是3 oups。
在Intel / AMD上,将GP寄存器存储到一个临时位置并用16字节的读取值重新加载它们可能是值得考虑的吞吐量,前提是ALU端口上的整数瓶颈->向量(最近Intel的端口5)周围的代码瓶颈。
在Intel上,端口5的pinsrq x,r,imm
是2 uop,端口5的movq xmm,r64
也是1 uop。movhps xmm, [mem]
可以微熔接负载,但仍需要5 ALU uop端口。因此,movq xmm0,rax
/ mov [rsp-8], rdx
/ movhps xmm0, [rsp-8]
是3个融合域uops,其中2个需要最近Intel上的端口5。存储转发延迟使此延迟比插入延迟高得多。
将两个GP寄存器与store / store / movdqa
存储在一起(从读取较大负载的两个较窄存储中读取长存储转发档)也为3 ups,但这是避免任何端口5 uop的唯一合理顺序。大约15个周期的延迟如此之多,以至于乱序执行很容易将其隐藏起来。
对于YMM和/或更窄的元素,商店+重新加载是更值得考虑的,因为您可以在更多商店中摊销摊位/可以节省更多洗牌。但这仍然不应该成为32位元素的首选策略。
对于较窄的元素,如果有将2个较窄的整数打包到64位整数寄存器中的单-uop方式,那就很好了,因此可以进行更广泛的XMM寄存器传输。但是没有:Packing two DWORDs into a QWORD to save store bandwidth shld
在Intel SnB系列中是1 uop,但是需要寄存器顶部的输入之一。与PowerPC或ARM相比,x86的位域插入/提取指令非常弱,每次合并需要多个指令(存储/重装除外,每个时钟1的存储吞吐量很容易成为瓶颈)。
AVX512F可以broadcast to a vector from an integer reg,并且合并掩码允许单uup插入。
根据http://instlatx64.atw.hu/的电子表格(从IACA获取uop数据),只需花费1个port5 uop,即可将任意宽度的整数寄存器广播到Skylake-AVX512上的x / y / zmm向量。
Agner似乎没有在KNL上测试整数源寄存器,但是类似的VPBROADCASTMB2Q v,k
(掩码寄存器源)为1 uop。
已经设置了掩码寄存器:总共仅2微码:
; k1 = 0b0010
vmovq xmm0, rax ; 1 uop p5 ; AVX1
vpbroadcastq xmm0{k1}, rdx ; 1 uop p5 merge-masking
0001
而不是
0010
,请使用
vmovq xmm0{k1}, rax
将其混合到未掩码的广播中。
vmovq xmm0, rax 2c latency
vpbroadcastq xmm0{k1}, rdx ; k1 = 0b0010 3c latency
vpbroadcastq ymm0{k2}, rdi ; k2 = 0b0100 3c latency
vpbroadcastq ymm0{k3}, rsi ; k3 = 0b1000 3c latency
vinserti64x4
来组合256位的一半。这也意味着只需要3 k寄存器而不是7个寄存器即可。它需要1个额外的shuffle uop,但是除非有一些软件流水线操作,否则OoO exec在对向量执行任何操作之前,可能难以隐藏7个合并= 21c的延迟。)
; high 256 bits: maybe better to start again with vmovq instead of continuing
vpbroadcastq zmm0{k4}, rcx ; k4 =0b10000 3c latency
... filling up the ZMM reg
vpbroadcastq
延迟仍为3c。
http://instlatx64.atw.hu/
vpbroadcastq xmm,xmm
列为1c延迟,因此可以肯定的是,合并依赖链中的每一步我们都获得3c延迟。不幸的是,合并屏蔽的微指令需要目标寄存器早于其他输入就准备就绪。因此该操作的合并部分无法单独转发。
k1 = 2 = 0b0010
开始,我们可以用
KSHIFT初始化其余部分:
mov eax, 0b0010 = 2
kmovw k1, eax
KSHIFTLW k2, k1, 1
KSHIFTLW k3, k1, 2
# KSHIFTLW k4, k1, 3
# ...
KXNOR k0, k0,k0
开始生成-1并向左移,但这是2个port5 uops,而
mov eax,2
/
kmovw k1, eax
为p0156 + p5。
kmov k1, imm
,并且从内存中加载需要花费多倍,因此,一次性使用合并掩码就没有3-uop选项。但是如果您可以保留一些掩码规则,那么在循环中,似乎要好得多。)
VPBROADCASTQ xmm1, rdx ; 1 uop p5 ; AVX512VL (ZMM1 for just AVX512F)
vmovq xmm0, rax ; 1 uop p5 ; AVX1
vpblendd xmm0, xmm0, xmm1, 0b1100 ; 1 uop p015 ; AVX2
; SKX: 3 uops: 2p5 + p015
; KNL: 3 uops: ? + ? + FP0/1
vmovsd xmm1, xmm1, xmm0
也可以将这两个部分混合在一起,但只能在最近的Intel的端口5上运行,而整数立即混合则可以在任何矢量ALU端口上运行。
vpbroadcastq
替换。
_mm_set_epi64x
,请绝对使用
-mtune=haswell
或最近的版本,以避免对默认的
mtune=generic
进行繁琐的调整。或者,如果二进制文件仅在本地计算机上运行,则使用
-march=native
。)
关于assembly - 从GP规则加载xmm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50779309/
Intel x86 汇编中执行以下操作最有效的方法是什么(a、b 是 32 位 float ): 从 xmm1: [-, -, a, b] 到 xmm1: [a, a, b, b] 我找不到任何有用的
Intel x86 汇编中执行以下操作最有效的方法是什么(a、b 是 32 位 float ): 从 xmm1: [-, -, a, b] 到 xmm1: [a, a, b, b] 我找不到任何有用的
从 SIMD 寄存器加载和存储生成用途寄存器的最佳方式是什么?到目前为止,我一直使用堆栈作为临时的。例如, mov [rsp + 0x00], r8 mov [rsp + 0x08], r9 mov
我正在尝试实现一些内联汇编器(在 C/C++ 代码中)以利用 SSE。我想将值(从 XMM 寄存器或内存)复制并复制到另一个 XMM 寄存器。例如,假设我在内存中有一些值 {1, 2, 3, 4}。我
在多核 CPU 中,每个核是否都可以访问自己的 XMM 寄存器组?例如,如果一个芯片被列为具有 16 个 XMM 寄存器 (XMM0-XMM15),那么每个内核 16 个寄存器还是 16 个共享? 我
我发现很难在 Visual Studio 的寄存器窗口中解释 xmm 寄存器的值。窗口显示以下内容: XMM0 = 00000000000000004018000000000000 XMM1 = 00
pushf //couldnt store this in other registers movd xmm0,eax//storing in xmm registers
我正在使用 AES-NI在内核代码中。 AES 新指令使用 XMM 寄存器,我想确保从用户模式到内核模式的转换以及返回到用户模式的转换将保留 XMM 寄存器的状态。 MSDN link读到: In 6
有没有办法将压缩双字整数从 XMM 寄存器推送到堆栈?然后在需要时将其弹出? 理想情况下,我正在为通用寄存器寻找 PUSH 或 POP 之类的东西,我已经检查过英特尔手册,但我要么错过了命令,要么没有
是将值移动到 xmm 寄存器的唯一方法,首先将值移动到整数寄存器中,不知道它们叫什么,然后进入 xmm 寄存器,例如 mov [eax], (float)1000 ; store to mem
如何仅访问 128 位 xmm 寄存器的特定部分(字节)?我必须在整个空间上循环(按字节),逐字节比较并在明确定义的条件下复制它*。 因此,我必须将这个 16 字节寄存器的每个字节与 \0 进行比较,
我在xmm1寄存器加载了一些内容,假设它可以被视为 xmm1 = | bgra | bgra | bgra | bgra | (each one a dw) 现在,我想将每个双字逻辑右移 1 个字节,
我正在尝试使用 XMM 寄存器使用 SSE2 指令将 4 个数字添加到其他 4 个汇编语言中的数字。我确实成功了,但是我遇到了一些我不明白的事情。如果我以这种方式添加: movdqu xmm0, ow
我想知道,有没有办法增加 xmm 寄存器中的值,或者只能将一个值移到一个寄存器中? 我的意思是,你可以这样做: inc eax 或者像这样: inc [ebp+7F00F000] 有没有办法对 xmm
我需要能够采用 4 个压缩整数,并使用“或”运算将它们(一个在另一个之上)折叠成一个组合整数。 最有效的方法是什么?请注意,打包整数中的 1 永远不会有公共(public)位置,因此我认为无符号“ad
我正在尝试使用 XMM 寄存器使用 SSE2 指令将 4 个数字添加到其他 4 个汇编语言中的数字。我确实成功了,但是我遇到了一些我不明白的事情。如果我以这种方式添加: movdqu xmm0, ow
使用 nasm 在 x86 汇编中编程... 使用 MOVQ 指令,我将 m64 设置为 xmm MOVQ xmm1, qword [mymem64] 现在我想将它与零进行比较,以便我可以使用 Jcc
给定一个 128 位 xmm包含两个四字(即两个 64 位整数)的寄存器: ╭──────────────────┬──────────────────╮ xmm0 │ ffeeddccbb
我正在开发一个涉及 SSE 内在函数和 XMM 寄存器的项目,并且我想使用提供的所有 16 个寄存器。我试图明确告诉编译器执行此操作,但它似乎不起作用。例如,我可能会写这样一行: register _
我正在尝试使用 GCC 风格的内联汇编将 xmm 寄存器推送到 x86_64 C 代码中的堆栈上。我查看了this的答案问题并正在使用此代码 int main(void) { asm vola
我是一名优秀的程序员,十分优秀!