我正在用C语言从头开始制作一个基于位板的国际象棋引擎。移动生成过程对时间特别敏感。目前,我的代码如下:
void generate_moves(Position *p, Colour side, Move *list) {
if(side == WHITE) {
Bitboard b1 = p->piece_bitboards[BLACK_KNIGHT];
Bitboard top_rank_mask = MASK_RANK[RANK8];
...
} else {
Bitboard b1 = p->piece_bitboards[WHITE_KNIGHT];
Bitboard top_rank_mask = MASK_RANK[RANK1];
...
}
}以及其他数百行代码,它们要么是黑白的镜像,要么是相同的。然而,在我看来,这似乎很容易出错,而且很混乱。
因此,在每个fork中用一个三元操作符替换大的if-else以增加可读性:
void generate_moves(Position *p, Colour side, Move *list) {
Bitboard b1 = p->piece_bitboards[side == WHITE ? WHITE_KNIGHT :
BLACK_KNIGHT];
Bitboard top_rank_mask = MASK_RANK[side == WHITE ? RANK8 : RANK1];
...
}有相似的性能吗?所有三元运算符都依赖于变量side,它只能采用常量值白色或黑色。
发布于 2019-05-25 19:16:53
任何中等质量的编译器都会将这两个代码序列视为相同的代码序列,除非禁用优化。
第二个序列名义上有两个或多个测试,但是编译器应该识别重复的表达式以及它不能从一条语句更改到另一条语句的事实,因为其中的操作数不受前一条语句(Bitboard b1 = p->piece_bitboards[side == WHITE ? WHITE_KNIGHT : BLACK_KNIGHT];)中任何内容的影响。(假设WHITE是一个常量。)即使是中等质量的编译器也需要这样的优化。
至于选择(在if序列中选择两个块中的一个还是在另一种情况下选择三进制操作数)是在编译时进行的,除非编译器知道side的值,否则不会发生这种情况。由于side是一个函数参数,编译器不能仅从函数的源代码中知道它的值。如果编译器可以看到函数被调用的位置,并且为side传递的参数是常量表达式,或者编译器可以推导出它的值,那么它就可以知道它的值。例如,如果调用代码包含两个序列,其中一个序列为WHITE调用generate_moves,另一个序列为BLACK调用generate_moves,则编译器可能会为generate_moves生成内联代码,其中的选择在每种情况下都已优化。
这样做的情况不太清楚,并且更多地受到编译器和其他代码的属性的影响,而您还没有展示这些属性。
像这样的代码性能很可能受到其他因素的影响,而不是您所确定的条件选择。
https://stackoverflow.com/questions/56304205
复制相似问题