ОП несколько изменился со времени моего первоначального ответа.Позвольте мне попытаться вернуться здесь.
В случае 1, из-за короткого замыкания or
, я ожидаю, что компилятор сгенерирует четыре секции кода сравнения-затем-ветви.Очевидно, что ответвления могут быть довольно дорогими, особенно если они не идут по предсказанному пути.
В случае 2 компилятор может решить выполнить все четыре сравнения, преобразовать их в результаты bool 0/1 и затем побитировать or
все четыре штуки вместе, затем делаем одну (дополнительную) ветку.Это торгует, возможно, большим количеством сравнений для, возможно, меньшего количества ветвей.Похоже, что уменьшение числа ветвей действительно улучшает производительность.
В случае 3 все работает почти так же, как 2, за исключением того, что в самом конце еще одна ветвь может быть устранена путем явного указания компилятору: «Я знаюрезультат будет равен нулю или единице, поэтому просто умножьте значение слева на это значение ».Умножение очевидно происходит быстрее, чем соответствующая ветка на вашем оборудовании.Это отличается от второго примера, где компилятор не знает диапазон возможных выходных данных от побитового or
, поэтому он должен предположить, что это может быть любое целое число, и вместо этого должен выполнить сравнение и переход.
Оригинальный ответ для истории: Первый случай функционально отличается от второго и третьего, если random
имеет побочные эффекты (что было бы у обычного PRNG), поэтому вполне понятно, что компилятор может оптимизироватьих по-разному.В частности, первый случай будет вызывать random
столько раз, сколько необходимо для прохождения проверки, в то время как в двух других случаях random
всегда будет вызываться четыре раза.Это (при условии, что random
действительно является состоянием) приведет к тому, что будущие случайные числа будут другими.
Разница между вторым и третьим состоит в том, что компилятор, вероятно, по какой-то причине не может выяснить, что результатпобитовый или всегда будет 0 или 1. Когда вы даете подсказку сделать умножение вместо ветвления, вероятно, умножение получается быстрее из-за конвейерной обработки.