Конференция "Основная" » Оптимизация и Double
 
  • dmk © (14.01.17 16:01) [0]
    Странное дело. Есть такой код:

    var
     t: double;

    t := (1 / 1000);


    С включенной опцией компилятора Optimization получается число QNAN.
    Без оптимизации все нормально.

    Кто нибудь сталкивался? И как можно это дело обойти?
    Delphi XE6.
  • rrrrr © (14.01.17 18:02) [1]
    1.0/1000.0
  • dmk © (14.01.17 20:28) [2]
    1 и 1000 целочисленные.
  • NoUser © (15.01.17 00:29) [3]
    как узнал, что там QNAN ? (32/64?)
  • dmk © (15.01.17 01:54) [4]
    Через FloatToStrF выводит строку NAN и в Watch List добавил переменную.
  • dmk © (15.01.17 01:54) [5]
    64
  • Германн © (15.01.17 03:12) [6]

    > dmk ©   (14.01.17 20:28) [2]
    >
    > 1 и 1000 целочисленные.

    Это ты так считаешь. На самом деле что 1, что 1000 это константы неопределенного типа. Как их использует компилятор - знает только он.
  • NoUser © (15.01.17 03:14) [7]
    Ставь точку останова и показывай асм/регистры
  • dmk © (15.01.17 12:58) [8]
    Да с регистрами все в порядке. Сразу после расчета 0.001 получается. Сделал переменные глобальными — стало все в порядке, а так компилятор рушил локальные переменные, хотя и не должен.

    Получается так:
    1. f := 1/1000;
    2. Какие-то другие расчеты
    3. Вызов внешней процедуры
    4. Тут происходит слет внутренних переменных.
    5. Использование переменных невозможно из-за слетевшего значения

    А не должно быть так вроде :(
  • NoUser © (15.01.17 17:35) [9]
    > 3. Вызов внешней процедуры
    с этого момента поподробнее ))
  • dmk © (15.01.17 19:56) [10]
    Тут дело в оптимизации в общем. Когда она включена, то переменные по возможности хранятся в XMM-регистрах, а когда выключена в памяти. Отсюда и слет при внешнем вызове. У меня XMM-регистры используются.
  • dmk © (15.01.17 19:56) [11]
    Видимо недоработка компилятора.
  • NoUser © (15.01.17 23:11) [12]
    > У меня XMM-регистры используются.
    ну-у, может и не только у тебя они используются?

    Видимо тебе нужно узнать, как договорится об их совместном использовании.
    (https://msdn.microsoft.com/ru-ru/library/zthk2dkh.aspx)
  • dmk © (16.01.17 01:27) [13]
    Да не, с передачей параметров у меня порядок. Какого черта компилятор переменные помещает в регистры?
  • NoUser © (16.01.17 01:41) [14]
    а как иначе процессору работать с переменными ?

    ++
    (https://msdn.microsoft.com/ru-ru/library/9z1stfyw.aspx)
  • dmk © (16.01.17 13:50) [15]
    >а как иначе процессору работать с переменными ?

    Процессор тут не при чем. Это компилятор распихивает переменные. В случае оптимизации в регистры. Без - в память. Отсюда и глюк.
  • NoUser © (16.01.17 15:32) [16]

    >  В случае оптимизации в регистры.

    и глюк в том, что ты тоже используешь эти регистры (из асм кода) не сохранив/восстановив их значение?
  • dmk © (16.01.17 20:34) [17]
    Ну да. Именно так. Подстава от компилятора :)
  • dmk © (16.01.17 20:36) [18]
    У меня просто оптимизация никогда не включалась. По умолчанию она выключена.
  • Германн © (17.01.17 01:09) [19]
    Так кто кого подставил?
  • dmk © (17.01.17 01:29) [20]
    >Так кто кого подставил?
    Компилятор меня. В хелпе про это нет ни слова.
  • Rouse_ © (17.01.17 18:48) [21]
    Вообще странно, я проверил на ХЕ4 и на последнм Берлине, не воспроизвелось (ХЕ6 нет)
  • dmk © (17.01.17 21:11) [22]
    Для меня это тоже странно.

    Там такой код:
     //Единица на случай нулевой разницы
     if (gEndTime = gStartTime) then gEndTime := (gEndTime + 1);
     //Время использованное на отрисовку кадра в миллисекундах
     gUsedTime := (gEndTime - gStartTime);
     //Время использованное на отрисовку кадра в секундах
     gFrameTime := (gUsedTime / 1000);
     //Всего кадров отрисовано с момента сброса
     gTotalFrames := (gTotalFrames + 1);
     //Всего времени с момента сброса
     gTotalTime := (gTotalTime + gFrameTime);
     //Кадров в секунду с момента сброса
     gFPS := (gTotalFrames / gTotalTime);


    Потом вызывается

    //Рамка региона отсечения
    sBmp.RectAA(Rgn.X, Rgn.Y, Rgn.W, Rgn.H, crWhite, 255, 128);


    Внутри RectAA есть вызов

    //Рисуем линию
    FBlendScLine(lpDA, lpLen, dColor, dAlpha, dOpacity);


    В линии (часть кода):
     //Формируем маски очистки из одной
     movdqu xmm6, PClearMask //Читаем общую маску очистки
     movdqu xmm8, xmm6 //дублируем
     movdqu xmm9, xmm6 //дублируем
     psrldq xmm8, 1 //xmm8 - Маска очистки 15-го байта
     psrldq xmm9, 15 //xmm9 - маска инверсии
     psrldq xmm6, 8 //в xmm6 маска очистки 7..0 байтов


    В общем использую xmm на полную. После выход а из нее переменная приобретает вид QNAN вместо 0,001 как было до нее.

    Где я накосячил?
    Если сделать переменную глобальную - все в полном порядке.
    Если выключить оптимизацию - все хорошо.
    Поэтому вывод один - компилятор пихает локульную переменную в регистры.
    И да стека у меня нет. Ничего не сохраняю. Там все 16 xmm-регистров используются.
  • dmk © (17.01.17 21:14) [23]
    МОгу полный код FBlendScLine на почту скинуть. Кормить не хочу халявщиков :)
  • Давно не заходил (17.01.17 22:01) [24]
    In line with the x64 Application Binary Interface (ABI), the contents of the following registers must be preserved and restored within inline assembly functions: R12, R13, R14, R15, RDI, RSI, RBX, RBP, RSP, XMM4, XMM5, XMM6, XMM7, XMM8, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, and XMM15.

    http://docwiki.embarcadero.com/RADStudio/XE6/en/Using_Inline_Assembly_Code
  • dmk © (17.01.17 23:23) [25]
    Ну да, меня предупреждали :(
  • dmk © (17.01.17 23:23) [26]
    Спасибо!
 
Конференция "Основная" » Оптимизация и Double
Есть новые Нет новых   [118456   +62][b:0][p:0.001]