Взгляните на GodBolt
На мусоре компилятора gcc distr(gen);
!!!
.L27:
dec esi
je .L25
Это для цикла, который ничего не делает!
На clang компилятор не был достаточно умен:
.LBB0_1: # =>This Inner Loop Header: Depth=1
mov edi, offset gen
call double std::generate_canonical<double, 53ul, std::mersenne_twister_engine<unsigned long, 32ul, 624ul, 397ul, 31ul, 2567483615ul, 11ul, 4294967295ul, 7ul, 2636928640ul, 15ul, 4022730752ul, 18ul, 1812433253ul> >(std::mersenne_twister_engine<unsigned long, 32ul, 624ul, 397ul, 31ul, 2567483615ul, 11ul, 4294967295ul, 7ul, 2636928640ul, 15ul, 4022730752ul, 18ul, 1812433253ul>&)
dec ebx
jne .LBB0_1
И generate_canonical
фактически был вызван.
В основном вы должны использовать результат distr(gen);
, чтобы сделать с ним что-то, что будетповлиять на исход кода, в противном случае компилятор может удалить этот код.
Самый простой способ исправить i t - это собрать результаты
distr(gen);
и распечатать их.
Теперь, когда вы посмотрите на сборку, вы увидите, что clang
вызывает функцию std::generate_canonical<double, 53ul, std::mersenne_twister_engine< .... >>
и gcc
только что поместили соответствующий код в строку.
Скорее всего, это различие вызвано различной организациейстандартная библиотека. Clang использовал версию, встроенную в стандартную библиотеку, и в шаблоне gcc из заголовочного файла был использован для генерации кода в только что созданной сборке. Когда компилятор достигает внешнего кода из библиотеки, он не может сказать, что именно он делает, поэтому он не может оптимизировать этот код (поскольку некоторые побочные эффекты могут быть скрыты в библиотеке).