Проводятся ли троичные операции во время компиляции? - PullRequest
1 голос
/ 25 мая 2019

Я делаю шахматный движок на основе битборта с нуля на 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];
        ...
    }
}

и несколько других сотен строк кода, которые либо зеркально отображены для черно-белых изображений, либо совпадают.Тем не менее, это кажется мне подверженным ошибкам и запутанным.

Так будет ли замена большого 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];
    ...
}

будет иметь аналогичную производительность?Все троичные операторы зависят от переменной, которая может принимать только постоянные значения WHITE или BLACK.

1 Ответ

3 голосов
/ 25 мая 2019

Любой компилятор среднего качества будет обрабатывать две кодовые последовательности одинаково, если оптимизация не отключена.

Вторая последовательность номинально имеет два или более тестов, но компилятор должен распознавать дублированное выражение и тот факт, что он не может перейти от одного оператора к следующему, потому что на операнды в нем ничего не влияет в предыдущем выражении ( s) (Bitboard b1 = p->piece_bitboards[side == WHITE ? WHITE_KNIGHT : BLACK_KNIGHT];). (Предположительно, WHITE является константой.) Такая оптимизация ожидается от компиляторов даже среднего качества.

Что касается того, будет ли выбор (одного из двух блоков в последовательности if или троичных операндов в другом случае) выполнен во время компиляции, это не может произойти, если компилятор не знает значение side. Поскольку side является параметром функции, компилятор не может знать его значение только из исходного кода функции. Он может знать свое значение, если компилятор может видеть, где вызывается функция, и аргумент, переданный для side, является константным выражением или может быть иным образом выведен компилятором. Например, если вызывающий код содержит две последовательности, одна из которых вызывает generate_moves для WHITE, а другая - generate_moves для BLACK, возможно, компилятор сгенерирует встроенный код для generate_moves в который выбор был оптимизирован в каждом случае.

Обстоятельства, при которых это будет сделано, менее понятны и в большей степени зависят от свойств компилятора и другого кода, который вы не показали.

На производительность в коде, подобном этому, скорее всего, будут влиять другие факторы, чем выбор условий, который вы определили.

...