К>>На 17.00.50727.1 не воспроизвелась. К>Опа! Воспроизвелось. К>Что-то я не понимаю. Только что не воспроизводилось... всего-то, компьютер перезагрузил. К>Итак, VS2010 — не воспроизводится, 2012 — воспроизводится, причём для разных платформ по-разному К>amd64 и x86_amd64 — ошибки в i=1, 3; x86 — i=1, 3, 5.
Уважаемые коллеги, давайте сделаем единообразные тесты на доступных компиляторах (VS10, 11, 12), для отправки bug reprort.
main.cpp:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>2. Это VS2012(причём не обновлённый), а уже есть VS2013, которого у меня нет под рукой. Нужно в первую очередь проверить на VS2013.
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>2. Это VS2012(причём не обновлённый), а уже есть VS2013, которого у меня нет под рукой. Нужно в первую очередь проверить на VS2013.
AD>На VS2013 не проявляется.
Проявляется
+> cl vs.cpp /O2
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
vs.cpp
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\xlocale(337) : warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc
Microsoft (R) Incremental Linker Version 12.00.21005.1
Copyright (C) Microsoft Corporation. All rights reserved.
Здравствуйте, Кодт, Вы писали:
К>Пожалуйста, укажи командную строку полностью.
x64:
D:\WB\tests\test_msvc_o2>cl -O2 main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
main.cpp
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocale(336) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:main.exe
main.obj
D:\WB\tests\test_msvc_o2>main.exe
Error!!! : i=1 omega=-12 -J=-22
Error!!! : i=3 omega=-34 -J=-44
x86 — тоже самое
D:\WB\tests\test_msvc_o2>cl -O2 main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
main.cpp
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocale(336) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:main.exe
main.obj
D:\WB\tests\test_msvc_o2>main.exe
Error!!! : i=1 omega=-12 -J=-22
Error!!! : i=3 omega=-34 -J=-44
Error!!! : i=5 omega=-56 -J=-66
Здравствуйте, Chorkov, Вы писали:
C>Подозреваю, что нашел ошибку компилятора.
Сделай минимальный пример воспроизводящий ошибку, убери лишний шум — желающих помочь будет больше.
На каких уровнях оптимизации /O? проявляется?
C>Проявляется в релизе на 2012-я студии (17.00.61030).
В VS2012 где-то был баг, связанный с floating point — здесь как-то проскакивала подобная тема.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Chorkov, Вы писали:
C>>Здравствуйте, C>>Подозреваю, что нашел ошибку компилятора. А>Сравнивать даблы по значению нельзя.
Проявляется при оптимизации -O2. (-O1 — ошибки нет, но у меня производительность критична.)
При убирании '-' в цикле в foo — ошибка пропадает.
При удалении добавлении любого дополнительного кода внутрь цикла в foo, тое пропадает.
Поэтому и грешу на оптимизатор.
Про сравнение чисел с плавающей точкой я знаю. Оператор == появился при сублимировании кода.
Здравствуйте, Аноним, Вы писали:
C>>>>Подозреваю, что нашел ошибку компилятора. А>>>Сравнивать даблы по значению нельзя. G>>В данном случае можно. А>Нельзя никогда, если два дабла получены в результате вычислений.
Это всего лишь rule of dumb, подходящий для 99% случаев.
В общем случае их можно сравнивать. Особенно когда работа с такими числами регламентирована стандартами, например IEEE 754 (fpu большинства современного железа реализуют этот стандарт).
Например, как минимум одинаковые вычисления (в точности до последовательности всех операций), должны давать одинаковый бинарный результат (при одинаковых флагах fpu).
А>Умножение на минус единицу ничем в этом плане не отличается.
Единица в IEEE 754 binary64 представляется точно, знак это всего лишь отдельный бит — поэтому никаких проблем с проверкой быть не должно. (это в общем, в код ТС я пока не вникал)
Здравствуйте, Chorkov, Вы писали:
C>Проявляется при оптимизации -O2. (-O1 — ошибки нет, но у меня производительность критична.) C>При убирании '-' в цикле в foo — ошибка пропадает. C>При удалении добавлении любого дополнительного кода внутрь цикла в foo, тое пропадает. C>Поэтому и грешу на оптимизатор.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, Аноним, Вы писали:
C>>>>>Подозреваю, что нашел ошибку компилятора. А>>>>Сравнивать даблы по значению нельзя. G>>>В данном случае можно. А>>Нельзя никогда, если два дабла получены в результате вычислений.
EP>Это всего лишь rule of dumb, подходящий для 99% случаев.
Это то, о чем нужно думать, прежде, чем кричать о найденой ошибке в компиляторе.
EP>В общем случае их можно сравнивать. Особенно когда работа с такими числами регламентирована стандартами, например IEEE 754 (fpu большинства современного железа реализуют этот стандарт). EP>Например, как минимум одинаковые вычисления (в точности до последовательности всех операций), должны давать одинаковый бинарный результат (при одинаковых флагах fpu).
А кто вообще гарантирует, что вычисления будут одинаковыми с точностью до инструкций? Что оптимизатор одинаково их заоптимизирует в друх разных местах, например?
EP>Единица в IEEE 754 binary64 представляется точно, знак это всего лишь отдельный бит — поэтому никаких проблем с проверкой быть не должно. (это в общем, в код ТС я пока не вникал)
никто никому ничего не должен. Что именно решит компилятор — его дело. Он может реализовать умножение так, как ему удобнее, а не так, как вы думаете.
Здравствуйте, Аноним, Вы писали:
C>>>>>>Подозреваю, что нашел ошибку компилятора. А>>>>>Сравнивать даблы по значению нельзя. G>>>>В данном случае можно. А>>>Нельзя никогда, если два дабла получены в результате вычислений. EP>>Это всего лишь rule of dumb, подходящий для 99% случаев. А>Это то, о чем нужно думать, прежде, чем кричать о найденой ошибке в компиляторе.
Так а кто кричит? Коллега даже знак вопроса в сабже поставил
EP>>В общем случае их можно сравнивать. Особенно когда работа с такими числами регламентирована стандартами, например IEEE 754 (fpu большинства современного железа реализуют этот стандарт). EP>>Например, как минимум одинаковые вычисления (в точности до последовательности всех операций), должны давать одинаковый бинарный результат (при одинаковых флагах fpu). А>А кто вообще гарантирует, что вычисления будут одинаковыми с точностью до инструкций? Что оптимизатор одинаково их заоптимизирует в друх разных местах, например?
С точностью до инструкции нет гарантий, а вот до получения тех же значений — вполне. Именно для этого и существуют такие настройки компиляторов как floating-point behavior, с /fp:precise по умолчанию. Например, fp сложение не ассоциативно — оптимизатор не может просто взять и "переставить скобки" в (a+b)+c — так как это влияет на результат.
Или, например, настройка fp rounding.
Другой пример — см. какие свойства есть в std::numeric_limits, то есть в ISO C++.
EP>>Единица в IEEE 754 binary64 представляется точно, знак это всего лишь отдельный бит — поэтому никаких проблем с проверкой быть не должно. (это в общем, в код ТС я пока не вникал) А>никто никому ничего не должен. Что именно решит компилятор — его дело. Он может реализовать умножение так, как ему удобнее, а не так, как вы думаете.
Компилятор конечно может сделать что угодно, хоть чайник вскипятить.
Но я говорю про те компиляторы, которые лично проверял — GCC, MSVC и частично Clang, причём разных версий, на разных архитектурах. Регулярно гоняю достаточно длинные цепочки fp вычислений на unit-test'ах — результаты идентичны вплоть до бинарного представления.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Да, видимо так и есть. Немного сократил:
Ты можешь завести баг на сайте мс и отправить им этот пример, интересно что ответят.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
EP>>Да, видимо так и есть. Немного сократил: V>Ты можешь завести баг на сайте мс и отправить им этот пример, интересно что ответят.
Я-то могу (недавно заводил по поводу ICE), но тут есть два момента:
1. Мне кажется здесь уже проскакивал подобный баг (именно в VS2012), хорошо бы найти ту тему и сравнить.
2. Это VS2012(причём не обновлённый), а уже есть VS2013, которого у меня нет под рукой. Нужно в первую очередь проверить на VS2013.
Здравствуйте, Chorkov, Вы писали:
Ассемблер покажи.
Поскольку ошибка идет через два дабла, есть мнение, что для негоциации используется неправильная маска в xmm регистре, при этом скорее всего умный оптимизатор подгружает туда сразу два дабла, отсюда первый отрабатывает нормально, а второй портится маской.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, denisko, Вы писали:
D>>Коллеги, покажите же асм этого дела, интересно как он начудил.
Спасиб, конечно, но foo то мне зачем? Ошибка почти наверняка здесь
const double x = X[index(i, size)], y = -Y[i];
if(x != y)
Здравствуйте, denisko, Вы писали:
D>>>Коллеги, покажите же асм этого дела, интересно как он начудил. D>Спасиб, конечно, но foo то мне зачем? Ошибка почти наверняка здесь D>
D>const double x = X[index(i, size)], y = -Y[i];
D> if(x != y)
D>
Баг не в проверке, а в том что Y заполняется не теми значениями внутри foo.
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, Аноним, Вы писали:
AD>>>На VS2013 не проявляется. А>>Проявляется
AD>Хм. Точно. А из студии если компилить, то не хочет.
Похоже всё дело в опции /GL (global optimization). Если её включить, то баг не проявляется.