Pull to refresh

Comments 31

Однажды сделал тест собрав один и тот же код VC6 и VC10 и запустив на Celeron.

Собранный VC6 код быстрее крутился с float, собранный с VC10 - с double. Причем цифры были очень похожи, но с точностью до наоборот. Разгадки тогда так и не нашёл. В ассемблер было лень лезть смотреть.

UFO just landed and posted this here
UFO just landed and posted this here

На моем DSP (для случая float конечно)

main:

000004d4: 71080000 JUMP main;;

Это если с -О2. А если без оптимизации, то тоже бесконечный цикл, но уже со всеми операторами :)

UFO just landed and posted this here

из-за большой разницы в экспонентах при выполнении операции -1 превращается в ноль. Компилятор на базе Clang.

UFO just landed and posted this here

но вот если его немножко надуть

float x; // = 1e8;

x = get_N(); // возвращает из ассемблера 1e8

то все равно подвиснет. Хотя умный компилятор увидел бы, что здесь всего-лишь задержка и если от него просят максимум скорости, то её (задержку) можно было бы и убрать :)

Если поменять float на int, то результат такой

CALL _get_N
J8 = 0; return;;

т.е. к float больше уважения :)

Ага clang он такой. Вы поставьте double x = 1e16; вот тогда оптимизации жгут.

Поставил для float :) При -О2 получил

Fatal[L0]: INTERNAL ERROR. PLEASE CONTACT TECHNICAL SUPPORT.

Очень похоже на подсказку, что так делать не стоит :)

Статья не ради одного этого примера же написана. Она для общего понимания принципов работы чисел с плавающей точкой.

Дело в том, о при удалении от нуля увеличиваются интервалы между соседними числами с плавающей точкой. И в зависимости от модели округления (round to zero, round to nearest, ...), может так случиться, что при вычитании единицы, получившееся число станет непредставимо во float и округлится обратно к исходному значению.

это понятно. Но тут есть момент что кроме правил работы с ПТ, в жизненном процессе еще участвует и компилятор. И порой он очень старается помочь считать точнее и быстрее.

очень хорошее замечание про режим округления. Для случая round to zero зацикливания не будет.

Извините, а вы точно знаете смысл флага O0? Кажется странным сообщать компилятору "ничего не оптимизируй" и потом говорить "К сожалению не все компиляторы умеют оптимизировать такой код".

UFO just landed and posted this here

Нет, volatile это "within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. "

нет, на O0 всегда будет настоящий цикл. проверьте на godbolt.org

Плавающая точка очень коварна. Она зависит даже от опций (оптимизаций) компилятора — он может как использовать классический FPU (для x86), так и SSE. А там и разное время выполнения, даже если тип в программе вообще не менять.
Двойная точность — вежливость королей программистов. Еще со студенчества…

Как ML инженер не могу согласиться. Достаточная точность – лучшее решение. Иногда и half precision хватает.

Но всегда нужно понимать как работает плавающая точка.

Согласен с вами. Кому то и интов хватает...

Так точно. Напишу ещё какие-нибудь про модели округления, денормалы и прочие весёлые вещи.

А это точно проблема С/С++? Другие языки однозначно выполняют этот цикл на любой платформе?

Я вам не скажу за всю Одессу.

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

Ну и даже С++ выполняет этот цикл по-разному в зависимости от опций компиляции, и не только уже упомянутых -O0, -O1 и т.д.

Если вы выбрали C++ в качестве языка программирования, то учить его придётся всю жизнь. Смиритесь. Или выбирайте другой язык.

На самом деле нет, если использовать Qt, то можно без малейших неудобств до сих пор сидеть на С++11. Не вижу ни одной причины зачем постоянно учить новые стандарты, если и так всё работает. Только когнитивную нагрузку на ровном месте увеличивать.

Как минимум всякие мелочи, типа auto в лябдах, более ослабленные требования к constexpr функциям, новые атрибуты, типа maybe_unused и так далее. Никто не заставляет брать всё.

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

Во время командной разработки достаточно быстро знания выравниваются

Sign up to leave a comment.

Articles