Перенос программ из одной архитектуры в другую

Сразу предупреждаю, что это сложная задача.

Есть тест. Тест был результатом анализа большой проблемы с ошибкой, с которой мы столкнулись на работе. строительство __ attribute__((noinline)) запрещает компилятору делать функцию подстановки (для оптимизации чего-то там не взорвалось). Это самый простой способ оптимизации, гарантированно не убивающий интересную ситуацию.

#include <stdio.h>

double d = 5436277361664796672.000000;
long long ll = 5436277361664796253LL;

int __attribute__((noinline))
func1 (void)
{
double d1 = (double)ll;

if (d > d1)
return 1;
else
return 0;
}

int __attribute__((noinline))
func2 (void)
{
if (d > (double)ll)
return 1;
else
return 0;
}

int
main (void)
{
printf ("%d %d\n", func1(), func2());
return 0;
}

Я провел этот тест на intel а также sparc, Gcc используется в режиме с оптимизацией и без оптимизации. Получены следующие результаты:

sparc: "gcc" printed "0 0"sparc: "gcc -O2" printed "0 0"intel: "gcc" printed "0 1"intel: "gcc -O2" printed "1 1"

В чем причина различия? В любом случае в ситуации анализа было бы полезно иметь возможность повторить все это самостоятельно, но, конечно, почти никто не имеет возможности запустить этот код на sparc, Вместо sparc можно попробовать запустить под Windows используя microsoft or borland C compiler, Я не знаю, что им дадут результаты, но в любом случае что-то не соответствует ни с чем (потому что мы видим три разных результата)

Редактировать 1
_атрибут_ ((noinline)) — расширение компилятора gcc (забыл написать об этом). Поэтому VisualStudio не может скомпилировать его.

3

Решение

Я отмечаю, что объявление двойной константы имеет 19 значащих цифр, что является более точным, чем то, что может быть представлено двойным IEEE (который допускает 15-17 значащих цифр). Таким образом, d не может содержать 5436277361664796672.000000 точно.

Две строки определения констант различаются на 16-й цифре, поэтому вы находитесь в той области, где неточности в двойном выражении имеют ту же величину, что и разница между этими двумя числами. Следовательно, нельзя сравнивать сравнение.

Я не знаю, определяет ли стандарт C ++, что происходит, когда сверхточная строка преобразуется в double, но я не удивлюсь, если точный результат будет либо неопределенным, либо зависящим от реализации.

1

Другие решения

Кажется, решена проблема. В целом все написано правильно. Но на самом деле работает правильно sparc версия. Потому что стандарт для преобразования int64-> float64 должна быть потеря точности. И в коде при конвертации (для intel) int64-> float80 потеря происходит. Т.е. код на основе Intel работает с большей точностью, но это противоречит стандарту.

Возможно, это какое-то соглашение для платформы Intel, которое по умолчанию разрешено работать таким образом. Конечно, есть некоторые варианты, в которых код выполняется в строгом соответствии со стандартом (но становится медленнее)

0

По вопросам рекламы [email protected]