在四字上执行位级别排列

时间:2013-02-20 01:02:09

标签: c algorithm bit-manipulation

我正在寻找以64位整数排列位的最快方法。

给定一个名为“array”的表,对应于一个排列数组,意味着它的大小为64,并且填充了0到63之间的唯一数字(即没有重复),对应于64位整数中的位位置,I可以这样排列位

bit = GetBitAtPos(integer_, array[i]);
SetBitAtPos(integer_, array[i], GetBitAtPos(integer_, i));
SetBitAtPos(integer_, i, bit);

(by looping i from 0 to 63)

GetBitAtPos being
GetBitAtPos(integer_, pos) { return (integer >>) pos & 1 }

Setbitatpos也基于相同的原则(即使用C运算符), 形式为SetBitAtPos(整数,位置,bool_bit_value)

如果可能,我正在寻找更快的方法来执行此任务。我愿意接受任何解决方案,包括必要时的内联汇编。我很难找到比这更好的方法,所以我想我会问。

我想执行这样的任务来隐藏64位生成的整数中的数据(其中第一位4可以显示信息)。它比一个XOR模板imo(除非我错过了一些东西)要好一些,主要是因为有人试图找到相关性。 它还允许进行逆操作,不会丢失宝贵的位......

但是我觉得这个操作有点贵......

由于

3 个答案:

答案 0 :(得分:1)

由于排列是不变的,你应该能够提出一种比逐个移动位更好的方法(如果你可以发布你的秘密排列,我就可以去了)。最简单的改进是在输入和输出中同时移动具有相同距离(可以是模块化距离,因为您可以使用旋转)的位。如果这样的群体很少,这是一种非常好的方法。

如果这样做不如你所希望的那么好,看看你是否可以使用bit_permute_step来移动全部或大部分位。有关更多想法,请参阅该网站的其余部分。

如果你可以使用PDEP和PEXT,你可以移动位中的位,其中位之间的距离可以任意改变(但它们的顺序不能)。它是afaik,虽然它们的速度有多快(但它们尚未可用)。

最好的方法可能是其他答案中提到的这些和其他技巧的组合。

有太多的可能性来探索它们,真的,所以你可能不会找到最好的方式进行排列,但是使用这些想法(以及发布的其他想法)你无疑可以找到比你现在使用的更好的东西。


PDEP和PEXT已经有一段时间了,因此它们的性能已知,在3个周期的延迟和1个/周期的吞吐量下,它们比大多数其他有用的置换原语(除了普通的原语之外)更快。

答案 1 :(得分:0)

将您的位拆分为此方法有效的子集:

Extracting bits with a single multiplication

然后使用按位OR组合结果。

答案 2 :(得分:0)

对于64位数字,我认为(由于存在大量可能性)(找到最佳算法)的问题可能无法解决。最具可扩展性和最容易自动化的一个是查找表:

result = LUT0[ value & 0xff] +  
         LUT1[(value >> 8) & 0xff] +  
         LUT2[(value >> 16) & 0xff] + ...  
     +   LUT7[(value >> 56) & 0xff];  
  • 每个LUT条目必须是64位宽,它只是将子组中的每8位扩展到64个可能的区间的整个范围。此配置使用16k内存。

可伸缩性来自于可以使用任意数量的查找表(实际范围从3到32?)的事实。此方法容易受到缓存未命中的影响,并且无法并行化(至少对于大型表大小)。

如果存在某些对称性,可以使用一些聪明的技巧 - 例如在英特尔交换两位:

 test eax, (1<<BIT0 | 1<<BIT1)
 jpe skip:
 xor  eax, (1<<BIT0 | 1<<BIT1)
 skip:

这个OTOH极易受到分支错误预测的影响。