gpt4 book ai didi

c++ - 无模板优化

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:14:25 24 4
gpt4 key购买 nike

我正在编写一个国际象棋引擎,我有一个如下所示的函数:

U64 find_moves(Piece type, Team side, uint8_t square, U64 occupied) {
switch (type) {
case PAWN: {
U64 result = 0;
result |= occupied & bb_normal_moves::pawn_caps[side][square];
if (!(occupied & bb_normal_moves::pawn_moves_x1[side][square])) {
result |= bb_normal_moves::pawn_moves_x1[side][square];
if (!(occupied & bb_normal_moves::pawn_moves_x2[side][square])) {
result |= bb_normal_moves::pawn_moves_x2[side][square];
}
}
return result;
}
case KNIGHT:
return bb_normal_moves::knight_moves[square];
case BISHOP:
return bb_magics::bishop_moves(square, occupied);
case ROOK:
return bb_magics::rook_moves(square, occupied);
case QUEEN:
return bb_magics::bishop_moves(square, occupied) | bb_magics::rook_moves(square, occupied);
case KING:
return bb_normal_moves::king_moves[square];
}

return 0; // Can't happen
}

它本质上是根据 type 参数委托(delegate)给另一个函数调用。在程序的许多地方,这个函数在循环遍历不同的 Piece 值后被调用,它恰好是一个 enum

不幸的是,这意味着在该循环中每次都会调用此函数,因此此函数分支会浪费大量 CPU 时间。

我想做的是更改此函数以允许编译器优化调用:

template <Piece type> U64 find_moves(Team side, uint8_t square, U64 occupied)

但是我的循环不会编译,因为函数调用的目标无法在编译时解析。

有没有一种方法可以优化此功能而无需手动展开我的所有循环?

编辑:这是调用 find_moves 的循环之一的示例:

for (uint8_t piece = 1; piece < 6; piece++) {
move.info.piece = piece;
U64 bb_piece = board.bb_pieces[team][piece];

while (bb_piece) {
uint8_t from = pop_bit(team, bb_piece);
move.info.from = from;

U64 bb_targets = find_moves((Piece) piece, team, from, board.bb_all) & mask;

while (bb_targets) {
uint8_t to = pop_bit(x_team, bb_targets);
move.info.to = to;

buf[buf_size++] = move;
}
}
}

最佳答案

鉴于您的 Piece 的值enum 是从 1 到 6,你可以使用模板,std::make_index_sequence , std::index_sequence展开。

抱歉,我只能准备一个最小的例子(没有 move ,没有 board ,等等)。

如果你称某物为

foo(std::make_index_sequence<6U>{});

foo()你可以用单值调用另一个函数(你标记了 C++17 所以你可以使用模板折叠)

template <std::size_t ... Ps>
void foo (std::index_sequence<Ps...> const &)
{ (bar<Ps>(), ...); }

我的想法是在bar()你可以把正文的内容放在for (uint8_t piece = 1; piece < 6; piece++)你的例子的循环;我只调用了一个微不足道的(没有其他参数)find_moves()功能。

template <std::size_t Ps>
void bar ()
{ find_moves<pieces(1+Ps)>(); }

现在你可以开发六个find_moves()使用完全特化的模板函数(我只写 std::cout 消息;您可以使用其他参数将 case 的内容放在您的 switch 中。

template <pieces P>
void find_moves ();

template <>
void find_moves<Pawn> ()
{ std::cout << "Case Pawn" << std::endl; }

template <>
void find_moves<Knight> ()
{ std::cout << "Case Knight" << std::endl; }

template <>
void find_moves<Bishop> ()
{ std::cout << "Case Bishop" << std::endl; }

template <>
void find_moves<Rook> ()
{ std::cout << "Case Rook" << std::endl; }

template <>
void find_moves<Queen> ()
{ std::cout << "Case Queen" << std::endl; }

template <>
void find_moves<King> ()
{ std::cout << "Case King" << std::endl; }

下面是一个完整的编译示例

#include <iostream>
#include <utility>
#include <type_traits>

enum pieces { Pawn = 1, Knight, Bishop, Rook, Queen, King };

template <pieces P>
void find_moves ();

template <>
void find_moves<Pawn> ()
{ std::cout << "Case Pawn" << std::endl; }

template <>
void find_moves<Knight> ()
{ std::cout << "Case Knight" << std::endl; }

template <>
void find_moves<Bishop> ()
{ std::cout << "Case Bishop" << std::endl; }

template <>
void find_moves<Rook> ()
{ std::cout << "Case Rook" << std::endl; }

template <>
void find_moves<Queen> ()
{ std::cout << "Case Queen" << std::endl; }

template <>
void find_moves<King> ()
{ std::cout << "Case King" << std::endl; }

template <std::size_t Ps>
void bar ()
{ find_moves<pieces(1+Ps)>(); }

template <std::size_t ... Ps>
void foo (std::index_sequence<Ps...> const &)
{ (bar<Ps>(), ...); }

int main ()
{
foo(std::make_index_sequence<6U>{});
}

关于c++ - 无模板优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50726812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com