roy*_*est 2 performance x86 assembly cpu-architecture bit
我发现与二进制/双态特性相反,x86 CPU在处理诸如SHR,BT,BTR,ROL等类似的二进制操作指令时非常慢.
例如,我从某个地方读取它,比特移位/旋转超过1个位置被认为是慢的(具有高延迟,性能损失和那些可怕的东西).当操作数在内存中时更糟糕(不是内存双态外设吗?)
shl eax,1 ;ok
shl eax,7 ;slow?
Run Code Online (Sandbox Code Playgroud)
那么是什么让他们变慢?具有讽刺意味的是,像CPU一样的二进制机器在进行这种操作时应该很慢.它给人的印象是二进制CPU正在将位移位困难!
编辑:现在在手册中第二次看SHL条目后,它确实涉及一些沉重的微代码逻辑!
来自英特尔的vol.2手册shl ...
Operation
TemporaryCount = Count & 0x1F;
TemporaryDestination = Destination;
while(TemporaryCount != 0) {
if(Instruction == SAL || Instruction == SHL) {
CF = MSB(Destination);
Destination = Destination << 1;
}
//instruction is SAR or SHR
else {
CF = LSB(Destination);
if(Instruction == SAR) Destination = Destination / 2; //Signed divide, rounding toward negative infinity
//Instruction is SHR
else Destination = Destination / 2; //Unsigned divide
}
TemporaryCount = TemporaryCount - 1;
}
//Determine overflow
if(Count & 0x1F == 1) {
if(Instruction == SAL || Instruction == SHL) OF = MSB(Destination) ^ CF;
else if(Instruction == SAR) OF = 0;
//Instruction == SHR
else OF = MSB(TemporaryDestination);
}
else OF = Undefined;
Run Code Online (Sandbox Code Playgroud)
令人难以置信的是,这样一个简单的布尔代数变成了一个实现的噩梦.
这只是指令的伪代码,具体说明它的作用.该指令实际上并没有像这样实现.实际上,所有现代CPU都有桶形移位器或类似物,允许它们在一个周期内任意移动.例如,参见Agner Fog的表格,其中几乎所有的bit-fiddling指令都显示延迟为1.
一些小小的指令速度较慢,这里有一些例子:
bt,btr,bts,和btc与因为(a)中读-修改-写操作和(b)位串的索引他们做的存储器操作数使用时为慢rcr旋转量大于1慢速,因为该指令几乎从不需要,因此不能优化pdep并且pext在英特尔上稍微慢一些,在AMD上慢得多,可能是因为它们的实现非常复杂,并且实现分离使得它变得更容易.在旧处理器(例如,8086)上,CPU将采用与移位量一样多的周期,每个周期执行一次移位.这种实现方式允许ALU在没有任何额外硬件的情况下进行移位,从而减少了处理器所需的门数.我所知道的现代CPU没有这种性能行为.