[使用AVX512,有一个固有的_mm256_lzcnt_epi32
,它返回一个矢量,对于8个32位元素中的每一个,它都包含输入矢量元素中前导零位的数量。
是否有一种仅使用AVX和AVX2指令来实现此目标的有效方法?
当前,我正在使用一个提取每个元素并应用_lzcnt_u32
函数的循环。
double
的指数位并消除偏差。我认为整数log2与lzcnt相同,但是在2的幂处可能存在1比1的偏移。
[Standford Graphics比特黑客页面列出了您可以使用的其他无分支比特黑客,它们可能仍然比8倍标量lzcnt
好。
[如果您知道自己的数字始终很小(例如小于2 ^ 23),则可以使用float
执行此操作,并避免拆分和混合。
int v; // 32-bit integer to find the log base 2 of
int r; // result of log_2(v) goes here
union { unsigned int u[2]; double d; } t; // temp
t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000;
t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v;
t.d -= 4503599627370496.0;
r = (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] >> 20) - 0x3FF;
```
The code above loads a 64-bit (IEEE-754 floating-point) double with a 32-bit integer (with no paddding bits) by storing the integer in the mantissa while the exponent is set to 252. From this newly minted double, 252 (expressed as a double) is subtracted, which sets the resulting exponent to the log base 2 of the input value, v. All that is left is shifting the exponent bits into position (20 bits right) and subtracting the bias, 0x3FF (which is 1023 decimal).
[[要使用AVX2进行此操作,将set1_epi32(0x43300000)
和_mm256_castps_pd
混合并移位和混合奇/偶半数以获得__m256d
。减去后,_mm256_castpd_si256
并移位/混合低/将两半放到适当的位置,然后遮盖以得到指数。使用AVX2对FP位模式进行整数运算非常有效,在FP数学指令的输出上进行整数移位时,旁路延迟只有1个周期的额外延迟。
((待办事项:使用C ++内在函数编写,编辑欢迎内容,否则其他人可以将其作为答案。)
我不确定您是否可以使用
int
->double
conversion
进行任何操作,然后读取指数字段。负数没有前导零,而正数给出的指数取决于幅度。
[如果您确实希望这样做,您将一次走一个128位通道,改组以馈送xmm-> ymm包装的int32_t
->包装的double
转换。