假设有一排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 =正方形)。有些人还使用数组。如果可能的话,也可以考虑这个背景。
答案 0 :(得分:1)
哪些操作更快?
假设我们有N
个标记,其中N
是一个很大的数字。让我们比较一下测试标志需要做些什么。
每个flag
都是一个字节,因此数组的大小为N
个字节。
byte states[N];
sizeof (states) == N;
value = *(&states + index
value
与零进行比较。每个flag
都是一个位,每8位被分组为字节。所以数组的大小是N / 8
个字节。
byte states[N / 8];
sizeof (states) == N / 8;
arr_idx = index / 8
value = *(&states + arr_idx
bit_idx = index % 8
bit_idx
中的位value
是否为零。正如我们所看到的,位操作将需要更多步骤。但CPU擅长这些额外步骤所需的两个操作的功能,因此从性能的角度来看,它只会稍慢一点。
应该使用哪种情况下的数组呢?
我们更喜欢用于存储大量标志的位。每个字节都有8
个位,因此位的内存占用量总是比字节小8
倍。
我们更喜欢简单,速度和原子操作的字节。大多数CPU都有特殊的“原子”指令来原子地测试/设置/清除字节,但不是字节中的位。
例如,如果在out应用程序中的几个线程之间使用了这个滞后数组,我们可以使用原子CPU指令来操作该数组。对于位,它会更复杂,有锁或比较交换循环。
答案 1 :(得分:0)
寄存器上的按位操作在现代处理器(x86,ARM等)上占用(最多)一个时钟周期它实际上远不止于此,因为这些类型的操作使用了一些最简单的单元。能够在一个周期内执行和退出多个操作系统的CPU(例如Intel CPU),因此汇编程序员认为这些操作是免费的。
另一方面,数组处理需要内存加载和存储,并且可能超过缓存行大小,如果缓存未命中,这将是一个很大的延迟命中。
真的没有比较。按位运算是免费的;阵列操作相对昂贵。