什么更快?按位运算或数组运算。为什么呢?

时间:2018-02-23 11:59:07

标签: arrays performance bit-manipulation programming-languages

假设有一排10个灯泡。它们的状态可以是ON(1)或OFF(0)。

这可以用数组表示。

states = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]

或者是10位数字。

states = 1011010010

更新状态(在列表中设置值):

对于数组,它将是

states[0] = 1

对于位,它将使用位掩码

states = states | 10000000

类似的操作将用于清除比特等。

哪些操作更快?哪些情况应该使用数组,同样也应该用于比特?

我已经看到像国际象棋/棋盘引擎这样的某些引擎使用位串来存储板状态(1 =正方形,0 =正方形)。有些人还使用数组。如果可能的话,也可以考虑这个背景。

2 个答案:

答案 0 :(得分:1)

  

哪些操作更快?

假设我们有N个标记,其中N是一个很大的数字。让我们比较一下测试标志需要做些什么。

标志操作数组:

每个flag都是一个字节,因此数组的大小为N个字节。

byte states[N];
sizeof (states) == N;
  1. 访问阵列,即value = *(&states + index
  2. value与零进行比较。
  3. 位操作:

    每个flag都是一个位,每8位被分组为字节。所以数组的大小是N / 8个字节。

    byte states[N / 8];
    sizeof (states) == N / 8;
    
    1. 计算数组索引,即arr_idx = index / 8
    2. 访问数组元素,即value = *(&states + arr_idx
    3. 计算位索引,即bit_idx = index % 8
    4. 测试bit_idx中的位value是否为零。
    5. 正如我们所看到的,位操作将需要更多步骤。但CPU擅长这些额外步骤所需的两个操作的功能,因此从性能的角度来看,它只会稍慢一点。

        

      应该使用哪种情况下的数组呢?

      我们更喜欢用于存储大量标志的位。每个字节都有8个位,因此位的内存占用量总是比字节小8倍。

      我们更喜欢简单,速度和原子操作的字节。大多数CPU都有特殊的“原子”指令来原子地测试/设置/清除字节,但不是字节中的位。

      例如,如果在out应用程序中的几个线程之间使用了这个滞后数组,我们可以使用原子CPU指令来操作该数组。对于位,它会更复杂,有锁或比较交换循环。

答案 1 :(得分:0)

寄存器上的按位操作在现代处理器(x86,ARM等)上占用(最多)一个时钟周期它实际上远不止于此,因为这些类型的操作使用了一些最简单的单元。能够在一个周期内执行和退出多个操作系统的CPU(例如Intel CPU),因此汇编程序员认为这些操作是免费的。

另一方面,数组处理需要内存加载和存储,并且可能超过缓存行大小,如果缓存未命中,这将是一个很大的延迟命中。

真的没有比较。按位运算是免费的;阵列操作相对昂贵。