最初,我试图重现Agner Fog的微体系结构指南部分“YMM和ZMM矢量指令的预热期”中描述的效果,其中指出:
处理器在不使用时关闭向量执行单元的上部,以节省电源。在大约56000个时钟周期或14μs的初始预热期间,具有256位向量的指令的吞吐量大约是正常的4.5倍。
我得到了减速,尽管它看起来更接近~2x而不是4.5x。但我发现在我的CPU(英特尔i7-9750H咖啡湖)上,减速不仅影响256位操作,还影响128位向量操作和标量浮点操作(甚至是XMM触摸指令之后的N个仅限GPR的指令)。
基准项目代码:
# Compile and run:
# clang++ ymm-throttle.S && ./a.out
.intel_syntax noprefix
.data
L_F0:
.asciz "ref cycles = %u\n"
.p2align 5
L_C0:
.long 1
.long 2
.long 3
.long 4
.long 1
.long 2
.long 3
.long 4
.text
.set initial_scalar_warmup, 5*1000*1000
.set iteration_count, 30*1000
.set wait_count, 50*1000
.global _main
_main:
# ---------- Initial warm-up
# It seems that we enter _main (at least in MacOS 11.2.2) in a "ymm warmed-up" state.
#
# Initial warm-up loop below is long enough for the processor to switch back to
# "ymm cold" state. It also may reduce dynamic-frequency scaling related measurements
# deviations (hopefully CPU is in full boost by the time we finish initial warmup loop).
vzeroupper
push rbp
mov ecx, initial_scalar_warmup
.p2align 4
_initial_loop:
add eax, 1
add edi, 1
add edx, 1
dec ecx
jnz _initial_loop
# --------- Measure XMM
# TOUCH YMM.
# Test to see effect of touching unrelated YMM register
# on XMM performance.
# If "vpxor ymm9" below is commented out, then the xmm_loop below
# runs a lot faster (~2x faster).
vpxor ymm9, ymm9, ymm9
mov ecx, iteration_count
rdtsc
mov esi, eax
vpxor xmm0, xmm0, xmm0
vpxor xmm1, xmm1, xmm1
vpxor xmm2, xmm2, xmm2
vmovdqa xmm3, [rip + L_C0]
.p2align 5
_xmm_loop:
# Here we only do XMM (128-bit) VEX-encoded op. But it is triggering execution throttling.
vpaddd xmm0, xmm3, xmm3
add edi, 1
add eax, 1
dec ecx
jnz _xmm_loop
lfence
rdtsc
sub eax, esi
mov esi, eax # ESI = ref cycles count
# ------------- Print results
lea rdi, [rip + L_F0]
xor eax, eax
call _printf
vzeroupper
xor eax, eax
pop rbp
ret
问题:我的基准是否正确?下面对发生的事情的描述似乎合理吗?
CPU处于AVX-冷状态(约675µs内没有执行256位/512位指令)遇到带有YMM(ZMM)目标寄存器的单个指令。CPU立即切换到某种“过渡到AVX-暖”状态。这大概需要Agner指南中提到的约100-200个周期。并且这个“过渡”周期持续约56'000个周期。
在过渡期间,GPR代码可以正常执行,但任何具有向量目标寄存器的指令(包括128位XMM或标量浮点指令,甚至包括vmovq xmm0、rax)都会对整个执行管道应用限制。这会影响紧跟在该指令之后的仅GPR代码N个周期(不确定有多少个周期;可能有十几个周期的指令)。
节流可能会限制分配给执行单元的µop的数量(无论这些µop是什么;只要至少有一个µop具有向量目标寄存器)?
对我来说,这里的新功能是,我认为在过渡期内,节流将仅适用于256位(和512位)指令,但似乎任何具有向量寄存器目标的指令都会受到影响(以及仅在指令之后立即测量20-60的GPR;在我的系统上无法更精确地测量)。
相关报道:特拉维斯·唐斯博客上一篇文章的“仅电压转换”部分可能描述了同样的效果。虽然作者测量了过渡期间YMM向量的性能,但得出的结论是,当过渡期间遇到向量寄存器接触指令时,被拆分的不是向量的上部,而是应用于整个管道的节流。(编辑:这篇博文没有测量过渡期内的XMM寄存器,这正是本文所测量的)。
即使对于窄SIMD指令,您也会看到节流,这是我称之为隐式加宽的行为的副作用。
基本上,在现代英特尔上,如果在ymm0到ymm15范围内的任何寄存器上的128-255高位脏了,任何SIMD指令都会在内部扩展到256位,因为高位需要归零,这需要寄存器文件中的全部256位寄存器通电,可能还需要256位ALU路径。因此,该指令用于AVX频率,就好像它是256位宽的一样。
类似地,如果任何zmm寄存器上的位256到511在zmm0到zmm15的范围内变脏,则操作会隐式加宽到512位。
对于轻指令与重指令,加宽指令的类型与全宽指令的类型相同。也就是说,将128位FMA扩展到512位的FMA充当“重AVX-512”,即使仅发生128位FMA。
这适用于所有使用xmm/ymm寄存器的指令,甚至标量FP操作。
请注意,这不仅仅适用于此限制期:这意味着如果您的上限不干净,则窄SIMD指令(或标量FP)将导致转换到更保守的DVFS状态,就像全宽指令一样。
我在一个项目中工作,在这个项目中,我通过XML流向web服务发帖。在这种情况下,提供程序请求使用密码块链接(CBC)模式下的高级加密标准(AES)和128位初始化向量对路由xml进行加密。我是用VB.NET编码的,从我可以看出我已经满足了他们所有的加密要求,但当我提交帖子时,我总是得到一个“无效的路由输入加密”的错误响应。我没有做很多与加密,所以我希望有人与一些加密经验可以帮助我在这里。它失败是因
问题内容: 在当前的作业中,我需要处理位向量,但是我不确定如何在Python中执行此操作。它们应该能够从4位到20位。我以前从未使用过位向量,但是我猜想一个人会创建一个使用无与伦比的字节数组,这些数组是使用通常的AND / OR / XOR操作进行操作的。 这里的 重要限制 是:除了标准Python提供的库之外,我不能依赖 任何 其他库。 我想我知道如何使用8位无符号字节数组在C中做到这一点:例如
问题内容: 只是在ThreeJS中对r67-r69进行了更新,最终遇到了将其位置指向一个(相同)向量的问题。 在执行此操作之前,请执行以下操作: 这使得当我移动其中一个网格时,它也可以移动另一个网格。 在r69中,位置矢量保持不变(也称为0、0、0),这意味着每当我对另一个网格进行模式化时,我都必须手动设置每个网格的X,Y和Z坐标。 我在这里想找点零钱吗?或者我应该怎么做才能解决这个问题? 问题答
问题内容: 有没有一种很好的方法来区分python中的行向量和列向量?到目前为止,我正在使用numpy和scipy,到目前为止,我看到的是,如果我要给一个向量,说 他们无法说天气,我的意思是行或列向量。此外: 在“现实世界”中哪一个根本是不正确的。我意识到上述模块中向量上的大多数功能都不需要区分。例如,或者我想为自己的方便而与众不同。 问题答案: 您可以通过向数组添加另一个维度来明确区分。 现在将
矢量或者说向量,可以通过2~4个分量表示一个向量,比如通过vec3(1,0,0)表示三维空间中一个沿着x轴正方向的三维方向向量,如果你有高中数学的基础,应该对向量有一定的了解,对于三维坐标的相关几何运算也有一定的概念。 关键字 数据类型 vec2 二维向量,具有xy两个分量,分量是浮点数 vec3 三维向量 ,具有xyz三个分量,分量是浮点数 vec4 四维向量 ,具有xyzw四个分量,分量是浮点
在最近的一次采访中,我建议使用向量 编码过程结束后,他们说在向量上使用pair是个好主意,并要求我详细说明我之前所说的“更重”是什么意思。不幸的是,我无法详细说明。是的,我知道我们只能在一对中输入两个值,但在一个向量中可以输入更多的值,并且当向量的大小==容量等时,该向量会自动调整大小。但是我应该如何回答他们的问题?为什么具体使用<代码>向量