我正在使用基于位板的国际象棋引擎,其中一项行动是在无符号的64位整数中设置/清除位。因为我不熟悉哪些代码会运行得更快'在某些处理器上,这是我无法解决的问题。
设置和清除位是一个非常简单的操作,但我应该使用(用于设置):
uint64_t bitboard |= 1ULL << index;
或:
uint64_t bitboard |= BITMASK[index];
其中BITMASK[]
是一些预先计算的整数数组,其中只有一位(index
)被设置。
乍一看,位移似乎是明显更快的选择,因为位移总是比内存查找更快。
但是在国际象棋引擎的上下文中,可能会大量执行此操作,将查找表存储在处理器的高速缓存中是有意义的,这可能会使查找速度更快表。或者是吗?
此外,它甚至有所作为吗?
或许可能是一个愚蠢的考虑因素,但要知道它并不会有什么坏处。
答案 0 :(得分:3)
与表查找相比,shift方法应该更快,因为它避免了额外的内存引用。但出于教育目的,基准测试会很有趣。
答案 1 :(得分:2)
我很快就掀起了这个(非常粗暴,赦免)的功能:
#include <iostream>
#include <random> // std::mt19937()
typedef unsigned long long uint64;
uint64 SET_BITMASK[64];
void init_bitmask()
{
for(int i = 0; i < 64; i++) SET_BITMASK[i] = 1ULL << i;
}
int main()
{
std::mt19937 gen_rand(42);
uint64 bb = 0ULL;
double avg1, avg2;
init_bitmask();
for(unsigned int i = 0; i < 10; i++)
{
std::clock_t begin = std::clock();
for(unsigned int j = 0; j < 99999999; j++)
{
bb |= 1ULL << (gen_rand() % 64);
}
std::clock_t end = std::clock();
std::cout << "For bitshifts, it took: " << (double) (end - begin) / CLOCKS_PER_SEC << "s." << std::endl;
avg1 += (double) (end - begin) / CLOCKS_PER_SEC;
bb = 0ULL;
begin = std::clock();
for(unsigned int j = 0; j < 99999999; j++)
{
bb |= SET_BITMASK[gen_rand() % 64];
}
end = std::clock();
std::cout << "For lookups, it took: " << (double) (end - begin) / CLOCKS_PER_SEC << "s." << std::endl << std::endl;
avg2 += (double) (end - begin) / CLOCKS_PER_SEC;
}
std::cout << std::endl << std::endl << std::endl;
std::cout << "For bitshifts, the average is: " << avg1 / 10 << "s." << std::endl;
std::cout << "For lookups, the average is: " << avg2 / 10 << "s." << std::endl;
std::cout << "Lookups are faster by " << (((avg1 / 10) - (avg2 / 10)) / (avg2 / 10))*100 << "%." << std::endl;
}
对于每次迭代,平均十个超过一亿个位集对于位移是1.61603s
,对于一致的查找是1.57592s
(即使对于不同的种子值)。
查找表格看起来惊人地大致2.5%
(在此特定用例中)。
注意: 我使用随机数来防止任何不一致,如下所示。
如果我使用i % 64
进行移位/索引,则比特移位速度提高约6%
。
如果我使用常数来移动/索引,输出变化大约8%,介于-4%和4%之间,这让我觉得一些有趣的猜测业务正在发挥作用。要么是,要么平均为0%;)
我无法得出结论,因为这肯定不是一个真实的场景,因为即使在国际象棋引擎中,这些设置的位案例也不会快速连续地相互跟随。我只能说,差异可能微不足道。我还可以补充一点,查找表是不一致的,因为您是否已经缓存了表格。我个人会在我的引擎中使用bithifts。