vs2012 , ошибка оптимизатора?
От: Chorkov Россия  
Дата: 14.04.14 16:38
Оценка: 66 (1)
Здравствуйте,
Подозреваю, что нашел ошибку компилятора.
Проявляется в релизе на 2012-я студии (17.00.61030).

#include <iostream>

void foo(size_t size, const double * J, double * omega)
{
    for( size_t i=0; i<size; ++i )
        omega[i] = - J[ i*(size+1) ]; // если без минуса, то все работает нормально.
}

int main(int argc, char *argv[])
{
    const size_t size=6;
    double J[size*size] = {
        11.,12.,13.,14.,15.,16.,
        21.,22.,23.,24.,25.,26.,
        31.,32.,33.,34.,35.,36.,
        41.,42.,43.,44.,45.,46.,
        51.,52.,53.,54.,55.,56.,
        61.,62.,63.,64.,65.,66.,
        };

    double omega[size] ={0};

    foo(size, J, omega);

    for(size_t i=0; i< size; ++i)
        if( omega[i] != -J[i*(size+1)] )
            std::cout<< "Error!!! : i="<<i<<" omega=" << omega[i]  << " -J=" << -J[i*(size+1)] << std::endl;

    return 0;
}



15.04.14 12:10: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: vs2012 , ошибка оптимизатора?
От: ArtDenis Россия  
Дата: 14.04.14 17:50
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Здравствуйте,

C>Подозреваю, что нашел ошибку компилятора.

А что программа выдаёт-то в итоге?
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: vs2012 , ошибка оптимизатора?
От: Аноним  
Дата: 14.04.14 18:00
Оценка: +1 -2 :)
Здравствуйте, Chorkov, Вы писали:

C>Здравствуйте,

C>Подозреваю, что нашел ошибку компилятора.
Сравнивать даблы по значению нельзя.
Re[2]: vs2012 , ошибка оптимизатора?
От: glap  
Дата: 14.04.14 18:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Chorkov, Вы писали:


C>>Здравствуйте,

C>>Подозреваю, что нашел ошибку компилятора.
А>Сравнивать даблы по значению нельзя.

В данном случае можно.
Re: vs2012 , ошибка оптимизатора?
От: Evgeny.Panasyuk Россия  
Дата: 14.04.14 18:28
Оценка: +1
Здравствуйте, Chorkov, Вы писали:

C>Подозреваю, что нашел ошибку компилятора.


Сделай минимальный пример воспроизводящий ошибку, убери лишний шум — желающих помочь будет больше.
На каких уровнях оптимизации /O? проявляется?

C>Проявляется в релизе на 2012-я студии (17.00.61030).


В VS2012 где-то был баг, связанный с floating point — здесь как-то проскакивала подобная тема.
Re[3]: vs2012 , ошибка оптимизатора?
От: Аноним  
Дата: 14.04.14 19:00
Оценка: -2
Здравствуйте, glap, Вы писали:

C>>>Подозреваю, что нашел ошибку компилятора.

А>>Сравнивать даблы по значению нельзя.

G>В данном случае можно.


Нельзя никогда, если два дабла получены в результате вычислений. Умножение на минус единицу ничем в этом плане не отличается.
Re: vs2012 , ошибка оптимизатора?
От: ononim  
Дата: 14.04.14 19:09
Оценка:
стандартный же баян
Как много веселых ребят, и все делают велосипед...
Re: vs2012 , ошибка оптимизатора?
От: Chorkov Россия  
Дата: 14.04.14 19:57
Оценка:
Здравствуйте, Я писал:

  Скрытый текст
#include <iostream>

void foo(size_t size, const double * J, double * omega)
{
    for( size_t i=0; i<size; ++i )
        omega[i] = - J[ i*(size+1) ]; // если без минуса, то все работает нормально.
}

int main(int argc, char *argv[])
{
    const size_t size=6;
    double J[size*size] = {
        11.,12.,13.,14.,15.,16.,
        21.,22.,23.,24.,25.,26.,
        31.,32.,33.,34.,35.,36.,
        41.,42.,43.,44.,45.,46.,
        51.,52.,53.,54.,55.,56.,
        61.,62.,63.,64.,65.,66.,
        };

    double omega[size] ={0};

    foo(size, J, omega);

    for(size_t i=0; i< size; ++i)
        if( omega[i] != -J[i*(size+1)] )
            std::cout<< "Error!!! : i="<<i<<" omega=" << omega[i]  << " -J=" << -J[i*(size+1)] << std::endl;

    return 0;
}


Собственно это и есть минимальный пример воспроизводящий ошибку.
Перекладываем диагональные элементы матрицы с умножением на -1.
Вывод программы:
Error!!! : i=1 omega=-12 -J=-22
Error!!! : i=3 omega=-34 -J=-44
Error!!! : i=5 omega=-56 -J=-66

Проявляется при оптимизации -O2. (-O1 — ошибки нет, но у меня производительность критична.)
При убирании '-' в цикле в foo — ошибка пропадает.
При удалении добавлении любого дополнительного кода внутрь цикла в foo, тое пропадает.
Поэтому и грешу на оптимизатор.

Про сравнение чисел с плавающей точкой я знаю. Оператор == появился при сублимировании кода.
Re[4]: vs2012 , ошибка оптимизатора?
От: Evgeny.Panasyuk Россия  
Дата: 14.04.14 20:13
Оценка:
Здравствуйте, Аноним, Вы писали:

C>>>>Подозреваю, что нашел ошибку компилятора.

А>>>Сравнивать даблы по значению нельзя.
G>>В данном случае можно.
А>Нельзя никогда, если два дабла получены в результате вычислений.

Это всего лишь rule of dumb, подходящий для 99% случаев.
В общем случае их можно сравнивать. Особенно когда работа с такими числами регламентирована стандартами, например IEEE 754 (fpu большинства современного железа реализуют этот стандарт).
Например, как минимум одинаковые вычисления (в точности до последовательности всех операций), должны давать одинаковый бинарный результат (при одинаковых флагах fpu).

А>Умножение на минус единицу ничем в этом плане не отличается.


Единица в IEEE 754 binary64 представляется точно, знак это всего лишь отдельный бит — поэтому никаких проблем с проверкой быть не должно. (это в общем, в код ТС я пока не вникал)
Re[2]: vs2012 , ошибка оптимизатора?
От: ononim  
Дата: 14.04.14 20:33
Оценка:
C>Вывод программы:
C>
C>Error!!! : i=1 omega=-12 -J=-22
C>Error!!! : i=3 omega=-34 -J=-44
C>Error!!! : i=5 omega=-56 -J=-66
C>

а ну тогда да.. эпсилон не причем
Как много веселых ребят, и все делают велосипед...
Re[2]: vs2012 , ошибка оптимизатора?
От: Evgeny.Panasyuk Россия  
Дата: 14.04.14 21:46
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Проявляется при оптимизации -O2. (-O1 — ошибки нет, но у меня производительность критична.)

C>При убирании '-' в цикле в foo — ошибка пропадает.
C>При удалении добавлении любого дополнительного кода внутрь цикла в foo, тое пропадает.
C>Поэтому и грешу на оптимизатор.

Да, видимо так и есть. Немного сократил:
// Bug in VS2012 11.0.50727.1 x64 Release /O2
// Output is: i=1 Y=-1001 X=1005

#include <iostream>
#include <iterator>
#include <numeric>
using namespace std;

size_t index(size_t i, size_t size)
{
    return i*(size+1);
}

__declspec(noinline) // affects bug
void foo(size_t size, const double * const X, double * const Y)
{
    for(size_t i=0; i!=size; ++i) // replacing size_t with unsigned affects bug
        Y[i] = -X[index(i, size)]; // negation affects bug
}

int main()
{
    const size_t size=4;
    double X[size*size], Y[size];
    iota(begin(X), end(X), 1000.);
    foo(size, X, Y);
    const size_t i = 1;
    cout << "i=" << i << " Y=" << Y[i] << " X=" << X[index(i, size)] << endl;
}
Re[5]: vs2012 , ошибка оптимизатора?
От: Аноним  
Дата: 14.04.14 22:29
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Аноним, Вы писали:


C>>>>>Подозреваю, что нашел ошибку компилятора.

А>>>>Сравнивать даблы по значению нельзя.
G>>>В данном случае можно.
А>>Нельзя никогда, если два дабла получены в результате вычислений.

EP>Это всего лишь rule of dumb, подходящий для 99% случаев.

Это то, о чем нужно думать, прежде, чем кричать о найденой ошибке в компиляторе.

EP>В общем случае их можно сравнивать. Особенно когда работа с такими числами регламентирована стандартами, например IEEE 754 (fpu большинства современного железа реализуют этот стандарт).

EP>Например, как минимум одинаковые вычисления (в точности до последовательности всех операций), должны давать одинаковый бинарный результат (при одинаковых флагах fpu).
А кто вообще гарантирует, что вычисления будут одинаковыми с точностью до инструкций? Что оптимизатор одинаково их заоптимизирует в друх разных местах, например?

EP>Единица в IEEE 754 binary64 представляется точно, знак это всего лишь отдельный бит — поэтому никаких проблем с проверкой быть не должно. (это в общем, в код ТС я пока не вникал)

никто никому ничего не должен. Что именно решит компилятор — его дело. Он может реализовать умножение так, как ему удобнее, а не так, как вы думаете.
Re[6]: vs2012 , ошибка оптимизатора?
От: Evgeny.Panasyuk Россия  
Дата: 14.04.14 23:00
Оценка:
Здравствуйте, Аноним, Вы писали:

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'ах — результаты идентичны вплоть до бинарного представления.
Re[3]: vs2012 , ошибка оптимизатора?
От: Vain Россия google.ru
Дата: 15.04.14 01:24
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Да, видимо так и есть. Немного сократил:

Ты можешь завести баг на сайте мс и отправить им этот пример, интересно что ответят.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[4]: vs2012 , ошибка оптимизатора?
От: Evgeny.Panasyuk Россия  
Дата: 15.04.14 01:35
Оценка:
Здравствуйте, Vain, Вы писали:

EP>>Да, видимо так и есть. Немного сократил:

V>Ты можешь завести баг на сайте мс и отправить им этот пример, интересно что ответят.

Я-то могу (недавно заводил по поводу ICE), но тут есть два момента:
1. Мне кажется здесь уже проскакивал подобный баг (именно в VS2012), хорошо бы найти ту тему и сравнить.
2. Это VS2012(причём не обновлённый), а уже есть VS2013, которого у меня нет под рукой. Нужно в первую очередь проверить на VS2013.
Re[5]: vs2012 , ошибка оптимизатора?
От: ArtDenis Россия  
Дата: 15.04.14 02:37
Оценка: 14 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>2. Это VS2012(причём не обновлённый), а уже есть VS2013, которого у меня нет под рукой. Нужно в первую очередь проверить на VS2013.


На VS2013 не проявляется.
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[6]: vs2012 , ошибка оптимизатора?
От: Аноним  
Дата: 15.04.14 02:44
Оценка: 14 (1)
Здравствуйте, 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.

/out:vs.exe
vs.obj

+> vs
i=1 Y=-1001 X=1005
Re: vs2012 , ошибка оптимизатора?
От: Кодт Россия  
Дата: 15.04.14 08:25
Оценка: 14 (1)
Здравствуйте, Chorkov, Вы писали:

C>Подозреваю, что нашел ошибку компилятора.

C>Проявляется в релизе на 2012-я студии (17.00.61030).

На 17.00.50727.1 не воспроизвелась.
Перепробовал платформы x86, x86_amd64, amd64 и опции /O2, /Oy

На VS2010, кстати, тоже не воспроизвелась.

Пожалуйста, укажи командную строку полностью.
Перекуём баги на фичи!
Re[2]: vs2012 , ошибка оптимизатора?
От: Chorkov Россия  
Дата: 15.04.14 08:36
Оценка: 14 (1)
Здравствуйте, Кодт, Вы писали:

К>Пожалуйста, укажи командную строку полностью.


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
Re[2]: vs2012 , ошибка оптимизатора?
От: Кодт Россия  
Дата: 15.04.14 09:28
Оценка: 14 (1)
Здравствуйте, Кодт, Вы писали:

К>На 17.00.50727.1 не воспроизвелась.


Опа! Воспроизвелось.
Что-то я не понимаю. Только что не воспроизводилось... всего-то, компьютер перезагрузил.

Итак, VS2010 — не воспроизводится, 2012 — воспроизводится, причём для разных платформ по-разному
amd64 и x86_amd64 — ошибки в i=1, 3; x86 — i=1, 3, 5.
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.