相关疑难解决方法(0)

使用单个乘法提取位

我看到在使用了一个有趣的技术,答案另一个问题,并想好一点理解.

我们给出了一个无符号的64位整数,我们对以下几位感兴趣:

1.......2.......3.......4.......5.......6.......7.......8.......
Run Code Online (Sandbox Code Playgroud)

具体来说,我们希望将它们移到前八位,如下所示:

12345678........................................................
Run Code Online (Sandbox Code Playgroud)

我们不关心指示的位的值.,并且不必保留它们.

溶液是屏蔽掉不需要的位,并且乘以结果0x2040810204081.事实证明,这就是诀窍.

这种方法有多普遍?这种技术可以用来提取任何比特子集吗?如果不是,如何判断该方法是否适用于特定的位组?

最后,如何找到(a?)正确的乘数来提取给定的位?

c bit-manipulation multiplication

298
推荐指数
5
解决办法
2万
查看次数

从64位数字"隔离"特定的行/列/对角线

好吧,让我们考虑一个64位数字,其位形成一个8x8表.

例如

0 1 1 0 1 0 1 0 0 1 1 0 1 0 1 1 0 1 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 1 1 0 1 0 1 0 0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 0

写作

a b c d e f g h
----------------
0 1 1 0 …
Run Code Online (Sandbox Code Playgroud)

c++ performance 64-bit bit-manipulation bitboard

31
推荐指数
2
解决办法
2356
查看次数

INC指令与ADD 1:重要吗?

来自Ira Baxter回答,为什么INC和DEC指令不会影响进位标志(CF)?

大多数情况下,我远离INCDEC现在,因为他们做的部分条件代码更新,这样就可以在管道中引起滑稽的摊位,和ADD/ SUB没有.因此,无关紧要(大多数地方),我使用ADD/ SUB避免失速.我使用INC/ DEC仅在保持代码较小的情况下,例如,适合高速缓存行,其中一个或两个指令的大小产生足够的差异.这可能是毫无意义的纳米[字面意思!] - 优化,但我在编码习惯上相当老派.

我想问一下为什么它会导致管道中的停顿,而添加不会?毕竟,无论是ADDINC更新标志寄存器.唯一的区别是INC不更新CF.但为什么重要呢?

performance x86 assembly increment micro-optimization

26
推荐指数
2
解决办法
4234
查看次数

如何执行_mm256_movemask_epi8(VPMOVMSKB)的反转?

内在的:

int mask = _mm256_movemask_epi8(__m256i s1)
Run Code Online (Sandbox Code Playgroud)

创建一个掩码,其32位对应于每个字节的最高位s1.在使用位操作(BMI2例如)操作掩码之后,我想执行反转_mm256_movemask_epi8,即创建一个__m256i向量,每个字节的最高有效位包含相应的位uint32_t mask.

做这个的最好方式是什么?

编辑:我需要执行逆操作,因为内在函数_mm256_blendv_epi8只接受__m256i类型掩码而不是uint32_t.因此,在结果__m256i掩码中,我可以忽略除每个字节的MSB之外的位.

c x86 simd avx avx2

21
推荐指数
2
解决办法
4378
查看次数

如何用8个bool值创建一个字节(反之亦然)?

我有8个bool变量,我想将它们"合并"成一个字节.

有一个简单/首选的方法来做到这一点?

相反,如何将一个字节解码为8个独立的布尔值?

我认为这不是一个不合理的问题,但由于我无法通过谷歌找到相关文档,它可能是另一个"非你所有直觉都是错误的"案例.

c++ boolean bit-manipulation bit-packing

20
推荐指数
4
解决办法
2万
查看次数

将屏蔽位移到lsb

当你and使用掩码的某些数据时,你会得到一些与数据/掩码大小相同的结果.我想要做的是取结果中的掩码位(掩码中有1)并将它们向右移动,使它们彼此相邻,我可以对它们执行CTZ(计数尾随零) .

我不知道如何命名这样的程序,所以谷歌让我失望.该操作最好不应该是循环解决方案,这必须尽可能快地操作.

这是一个用MS Paint制作的令人难以置信的图像. 在此输入图像描述

c c++ bitmask

13
推荐指数
1
解决办法
1730
查看次数

为什么GCC不使用部分寄存器?

write(1,"hi",3)在linux上反汇编,gcc -s -nostdlib -nostartfiles -O3结果如下:

ba03000000     mov edx, 3 ; thanks for the correction jester!
bf01000000     mov edi, 1
31c0           xor eax, eax
e9d8ffffff     jmp loc.imp.write
Run Code Online (Sandbox Code Playgroud)

我不是到编译器的开发,但由于移动到这些寄存器的每一个值是恒定的和已知的编译时间,我很好奇,为什么不GCC使用dl,dilal来代替.也许有人会说,此功能不会让任何性能上的差异,但有一个在之间的可执行文件的大小有很大的区别mov $1, %rax => b801000000,并mov $1, %al => b001当我们谈论数千寄存器的程序访问.如果软件的优雅部分不仅体积小,它确实会对性能产生影响.

有人可以解释为什么"海湾合作委员会决定"它无所谓?

x86 assembly gcc x86-64

13
推荐指数
2
解决办法
1655
查看次数

不使用BMI2的便携式有效替代PDEP?

英特尔位操作指令集2(BMI2)中的并行存款指令(PDEP)的文档描述了该指令的以下串行实现(类似C的伪代码):

U64 _pdep_u64(U64 val, U64 mask) {
  U64 res = 0;
  for (U64 bb = 1; mask; bb += bb) {
    if (val & bb)
      res |= mask & -mask;
    mask &= mask - 1;
  }
  return res;
}
Run Code Online (Sandbox Code Playgroud)

另请参阅英特尔的pdepinsn参考手册.

该算法是O(n),其中n是设置位的数量mask,这显然具有O(k)的最坏情况,其中k是总的位数mask.

更有效的最坏情况算法是否可行?

是否有可能制作一个更快的版本,假设val最多有一个位设置,即等于0或等于0到63之间的1<<r某个值r

algorithm x86 assembly bit-manipulation bmi

5
推荐指数
2
解决办法
619
查看次数