[英]Setting/clearing bits: bitshift or bitmask lookup?
我正在研究一个基于位板的国际象棋引擎,其中一个大概执行的操作是在无符号的64位整数中设置/清除位。 由于我不熟悉哪些代码在某些处理器上“运行得更快”,所以我无法完全理解这一点。
设置和清除位是一个非常简单的操作,但我应该使用(用于设置):
uint64_t bitboard |= 1ULL << index;
要么:
uint64_t bitboard |= BITMASK[index];
其中BITMASK[]
是一些预先计算的整数数组,其中只有一位(在index
)被设置。
乍一看,位移似乎是明显更快的选择,因为位移总是比内存查找更快。
但是在国际象棋引擎的上下文中,可能会大量执行此操作,将查找表存储在处理器的缓存中是有意义的,这可能会使查找表的使用速度更快。 或者是吗?
而且,它甚至有所作为吗?
也许是一个愚蠢的考虑因素,但要知道它并没有坏处。
与表查找相比,shift方法应该更快,因为它避免了额外的内存引用。 但出于教育目的,基准测试会很有趣。
我很快就掀起了这个(非常原始,赦免)的功能:
#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
为bitshifts和1.57592s
进行查找一致(甚至是不同的种子值)。
令人惊讶的查找表似乎始终快了大约2.5%
(在这个特定的用例中)。
注意:我使用随机数来防止任何不一致,如下所示。
如果我使用i % 64
来移位/索引,则位移的速度提高约6%
。
如果我使用常数来移位/索引,输出变化大约8%,介于-4%和4%之间,这让我觉得一些有趣的猜测业务正在发挥作用。 要么是,要么平均为0%;)
我无法得出结论,因为这肯定不是一个真实的场景,因为即使在国际象棋引擎中,这些设置的比特案例也不会快速连续地相互跟随。 我只能说,差异可能微不足道。 我还可以补充一点,查找表是不一致的,因为您是否已经缓存了表格。 我个人会在我的引擎中使用bithifts。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.