首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构造多个常量C++的最佳方法

构造多个常量C++的最佳方法
EN

Software Engineering用户
提问于 2020-11-10 16:24:24
回答 1查看 164关注 0票数 1

上下文

我正在开发我自己的国际象棋引擎,如果有什么可以预先初始化/预先计算的话,应该是。这是因为速度是第一位的,每多花一秒时间,你就会把原本可以事先计算出来的计算方法花在计算上,堆叠起来,最终让你失去很多重要的时间,而这些时间本来是不能预先计算的,比如评估。

主要的预初始化变量是各种比特板掩码.

  • 对角线
  • 军衔
  • 文件
  • 不同的正方形图案(中心、边缘、光方块、暗方块)
  • 对可以预先计算的碎片的攻击-骑士,国王,典当

constepxr无处不在。

我有一个单独的头文件来管理所有这些。它们可以在开始时初始化一次,然后在整个程序中使用几次。

问题

我目前所做的是使用嵌套的命名空间。

Mask.h

代码语言:javascript
复制
 // Bitboard is an alias for uint64_t
 // NB_SQ is the number of squares (64)
 
namespace Mask 
{
    void InitMasks();
    void InitAttacks();

    namespace File
    { // few examples
        constexpr Bitboard FileA = 0x0101010101010101;
        constexpr Bitboard FileB = FileA << 1;
        constexpr Bitboard FileC = FileB << 1;
        constexpr Bitboard FileD = FileC << 1;
        constexpr Bitboard FileE = FileD << 1;
        constexpr Bitboard FileF = FileE << 1;
        ...

        constexpr Bitboard notFileAB = ~(FileA | FileB)
        constexpr Bitboard notFileGF = ~(FileG | FileF)
        extern uint64_t AllFiles[NB_SQ] 
    }
    
    namespace Rank{...}

    namespace Diagonal {...}

    namespace Attack
    {
        extern Bitboard PawnAttacks[NB_SQ];
        extern Bitboard KnightAttacks[NB_SQ];
        ...
    }
    
}

所有extern数组都使用InitMasks()InitAttacks()初始化一次

示例

我能知道第七军衔的白卒有多少

代码语言:javascript
复制
WhitePawnsBB & Mask::Rank::Rank7

或者如果我想获得特定正方形的文件掩码

代码语言:javascript
复制
Mask::File::AllFiles[SQ]

如果我需要对任何广场上的骑士进行预先计算的攻击

代码语言:javascript
复制
Mask::Attack::KnightAttacks[SQ];

但是我真的很不满意,知道哪种面具可以属于哪里就会变得非常混乱。而且,这不是名称空间的目的,我是否有更好的方法来构建命名空间呢?

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2020-11-11 06:44:50

使用预先计算的位掩码仍有代价,因为它填充了缓存。内存是SSSSOOOOOOO SSSSSSSLLLLLOOOOOOOOOWWWWWWWWWWWW,因此动态计算这些位图可能会更快。

但假设你已经做了尽职调查。编译时函数怎么样?这允许您对逻辑进行具体说明,并允许编译器决定预编译位掩码或动态计算是否是更好的方法。

代码语言:javascript
复制
constexpr uint64_t horse_attack(uint32_t location)
{
    return /*bit twiddles on the constant location*/;
}

但是,如果确实需要常量,请考虑预先分配的数组。是的,有一个取消引用操作,但它确实避免了在操作码流中包含位掩码(可能多次),并且可以更容易地缓存。

如果检测到缓存的内存对齐,并强制数组在缓存边界上过度对齐,则需要额外的点数。

代码语言:javascript
复制
uint64_t horse_move[64] = {
    //each mask for each successive location.
};

如果不需要手工计算,请考虑编写一个程序来生成和列出这些常量。它不会像你写板面具时那样无聊。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/418836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档