LINUX.ORG.RU
ФорумTalks

Wine и Windows по-разному округляют

 ,


0

1

Cтолкнулся тут... Программа наподобие Proteo Wizard. Закрытой библиотекой импортируются данные. Интерполируются под регулярную сетку. Значения сетки — от 10 до 100. Если запускать программу в Виндоуз или если в Вайне, в полученных массивах часть узлов сетки отличаются на 1e-14, то есть на последний значащий бит. Похоже, проблема возникает при преобразовани 10-байтных extended в 8-байтные double.

Обидно.

★★★

Ответ на: комментарий от Deleted

А при чём тут wine может быть хотя бы теоретически?

Я вот думаю не в виртуалочке vs железо ли автор сравнивал? А вообще ржакой окажется если x86 vs x86_64. Ибо я сильно сомневаюсь, что арифметика чиселок с плавающей точкой где-то на софтверном уровне здесь реализована.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

А при чём тут wine может быть хотя бы теоретически?

Теоретически, вариантов тут может быть масса. Может существует некая функция WinAPI для работы с числами с плавающей точкой, которая в вайне реализована как-то иначе. Если поведение одной программы на одном наборе входных данных в венде и в вайне отличается, то проблема в вайне.

Хотя я соглашусь: без хоть каких-нибудь подробностей тут можно только гадать.

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

Так то она даже в glibc программно местами реализована. Короче, всякое может быть.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Кстати, я даже не уверен, что для всех операций с плавающей точкой гарантируется одинаковый результат на разных системах. Я не про простейшие вещи, типа сложения/вычитания, а про более «высокоуровневые» - тригонометрия, преобрезование в/из строку, etc. Так что даже не все отличия между либами вайна и винды будут считаться багами.

Deleted
()
Ответ на: комментарий от Deleted

https://bugs.winehq.org/

Уже искал «roundoff» и не нашёл. Сейчас поискал «rounding», нашёл ссылку вот на эту дискуссию: https://sourceware.org/bugzilla/show_bug.cgi?id=4943

Дело в msvcrt.dll? И майкрософтовская поможет повторить поведение в Windows?

olegd ★★★
() автор топика
Ответ на: комментарий от pon4ik

А при чём тут wine может быть хотя бы теоретически?

Я вот думаю не в виртуалочке vs железо ли автор сравнивал?

Сравнивал 2 витруальные машины VMware.

Но уже нашёл ссылку, что у C одни правила округления, у IEEE другие, у MSVC третьи. https://sourceware.org/bugzilla/show_bug.cgi?id=4943

А программа, похоже, на смеси MSVC и Дельфи :)

olegd ★★★
() автор топика
Последнее исправление: olegd (всего исправлений: 1)
Ответ на: комментарий от olegd

Дело может быть в чём угодно. Может вообще баг в самой программе.

Deleted
()

возможно настройки округления разные по дефолту

Harald ★★★★★
()
Ответ на: комментарий от Deleted

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

И правильно, результат вычислений с плавающей точкой разнится от платформы к платформе.

aiive
()

Если вы ожидаете что два одинаковых вычисления на float дадут совпадающий до бита результат, вы глубоко ошибаетесь, никто вам этого не гарантирует. Если вы на это зачем-то завязались - сравниваете float с помощью ==, например, и вас как-то колышат эти e-14, то у меня для вас плохие новости.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

Тут смысл не в плавающей запятой, а в том, что вычислительная программа в wine и нативной винде выдает разный результат.

praseodim ★★★★★
()
Ответ на: комментарий от unanimous

Да забудь ты про вычмат, программа выдает разный результат при одинаковых входных данных, вот в чем неприятность. Ну и для вычислений в некоторых случаях таки 64-битного типа мало, так что тоже может что-то значить.

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

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

slovazap ★★★★★
()
Ответ на: комментарий от praseodim

программа выдает разный результат при одинаковых входных данных

Это совершенно нормально для итеративных алгоритмов, вроде матричных диагонализаций

unanimous ★★★★★
()
Ответ на: комментарий от slovazap

Плавающая запятая != рандомная запятая. То что в программе два таких числа нельзя напрямую сравнивать - это одно, а то, что вообще результаты разные я не совсем понимаю почему это нормально.

praseodim ★★★★★
()
Ответ на: комментарий от unanimous

Это совершенно нормально для итеративных алгоритмов, вроде матричных диагонализаций

Вот это новость, для разных реализаций алгоритма - понятно, но для одной и той же программы - нет, это значит, что нет полной совместимости и какие-то библиотеки по-разному реализованы. По-хорошему надо разбираться в чем конкретно причина.

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

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

В моём случае это не страшно, но бросается в глаза. Данные сортируются по возрастанию этого столбца и пакуются LZO. Из-за иного порядка почти на процент меняется размер сжатого, и это сильно бросается в глаза.

olegd ★★★
() автор топика
Ответ на: комментарий от slovazap

Когда одна и та же программа выдаёт разный результат на двух разных машинах, это вызывает опасения и отказ принятия работы :)

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

Дело в msvcrt.dll? И майкрософтовская поможет повторить поведение в Windows?

Не помогло, msvcrt.dll только меняет поведение printf().

olegd ★★★
() автор топика
Ответ на: комментарий от praseodim

Можешь мне не рассказывать про вычисления, я работаю в этой области уже 15 лет. Для операций с плавающей точкой нормально иметь разный результат при запуске в разных программных окружениях. Все, что должен гарантировать алгоритм — это ошибки ниже порога, а порог почти всегда выше разрядной точности чисел с плавающей точкой.

Гарантированная точность только на числах фиксированной точности (fixed-point), потому что фактически это целочисленная масштабированная арифметика

unanimous ★★★★★
()
Ответ на: комментарий от slovazap

тут смысл именно в плавающей запятой, и то что программа выдаёт разный результат абсолютно нормально и ожидаемо.

Вычисления с плавающей запятой детерминистичны, так что если последовательность операций одинаковая, результат должен быть одинаковый.

i-rinat ★★★★★
()
Ответ на: комментарий от unanimous

Ну да. Это вопрос презентации.

olegd ★★★
() автор топика
Ответ на: комментарий от unanimous

Я тоже работал, правда давно и едва год, но все-таки. Помню как раз переносили программы с alpha dec на третьепень и появилась разница в результатах, тоже там e-14 или даже e-15 и более, точно уже не помню. Но помню, что было разбирательство по поводу причин, в первую очередь на тему не накосячили ли в чем, а то бывают ошибки, которые наглядно вылазят только при каких-то радикальных изменениях.

praseodim ★★★★★
()
Ответ на: комментарий от olegd

Не помогло, msvcrt.dll только меняет поведение printf().

В программе используется SSE2 или fpu87? Если fpu87, то возможно, что из-за того что внутри сопроцессор считает не в 64-битном double, а в 80-битном типе. И еще там есть нюансы, в частности писюковый сопроцессор вообще не полностью совместим с IEEE 754 и вот эти моменты с округлениями и некоторыми другими вещами могут быть разными в wine и нативной винде, вроде там даже от состояния процессора может зависеть. Сейчас не вспомню в чем точно фокус, но что-то там было, надо в доках на процессор копаться.

praseodim ★★★★★
()
Последнее исправление: praseodim (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Вычисления с плавающей запятой детерминистичны

https://github.com/h5py/h5py/issues/1051 Недетерминистичны под Windows, возможно баг в libHdf5, с которой работаю и я.

Интересно, WINE усугубил проблему, или как раз под WINE детерминистично? :)

olegd ★★★
() автор топика
Ответ на: комментарий от praseodim

Если fpu87, то возможно, что из-за того что внутри сопроцессор считает не в 64-битном double, а в 80-битном типе.

Да, fpu87, и да, 80-битные.

И еще там есть нюансы, в частности писюковый сопроцессор вообще не полностью совместим с IEEE 754 и вот эти момент с округлениями и некоторыми другими вещами могут быть разными в wine и нативной винде, вроде там даже от состояния процессора может зависеть.

Да, зависит. Но по идее, это состояние можно задавать.

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

Да, fpu87, и да, 80-битные.

В wine могли для таких случаев слишком «правильно» написать реализацию. Тогда в wine результат не просто отличается, а грубее.

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

То что в программе два таких числа нельзя напрямую сравнивать - это одно, а то, что вообще результаты разные я не совсем понимаю почему это нормально.

Вы не видите тут противоречия? Что значит «вообще»? Там та же погрешность в младших разрядах из-за которой нельзя сравнивать напрямую.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Вы не видите тут противоречия? Что значит «вообще»? Там та же погрешность в младших разрядах из-за которой нельзя сравнивать напрямую.

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

Регистры процессора - это же не аналоговые датчики с шумом в младших разрядах, чтобы не обращать внимание на разницу от случая к случаю. Я даже более того скажу, в процессоре строго говоря нет плавающей запятой - это такая наша интепрпретация значений регистров.

Например, значения машинного эпсилон не должны быть разными для разных процессоров одной архитектуры. И даже на одном компе не должны бы зависеть от языка (в пределах использования одинаковых типов) и компилятора

praseodim ★★★★★
()
Последнее исправление: praseodim (всего исправлений: 2)
Ответ на: комментарий от praseodim

Во-первых, есть fenv, который может быть очень разным в зависимости от разных условий. Во-вторых, самого алгоритма о детерминированности которого вы говорите, не существует - даже один бинарный код самого приложения может обращаться в разных условиях к libm разных версий, что просто гарантирует несовпадающий результат. Это даже не затрагивая того что в реальном мире одного бинарного кода не существует, и поведение меняется в зависимости от платформы, компилятора, флагов и изменений в приложении, даже не затрагивающих алгоритм напрямую.

slovazap ★★★★★
()

Проблема может быть даже в реализациях FPU на аппаратном уровне, либо в реализации плавающей точки в различных библиотеках. Например, WINE может использовать для плавающей точки системную библиотеку с одной реализацией, а шиндовс - с другой.

Quasar ★★★★★
()
Последнее исправление: Quasar (всего исправлений: 1)
Ответ на: комментарий от Quasar

Проблема может быть даже в реализациях FPU на аппаратном уровне,

Нет, это 2 виртуальные машины на одном физическом хосте. Процессор один и тот же.

либо в реализации плавающей точки в различных библиотеках. Например, WINE может использовать для плавающей точки системную библиотеку с одной реализацией, а шиндовс - с другой.

Об этом и речь в стартовом посте. Причём не программную эмуляцию плавающей запятой, а просто вызовы сопроцессора. Оказалось, что там тоже есть конфигурация, которую можно сломать.

olegd ★★★
() автор топика
Ответ на: комментарий от slovazap

Во-первых, есть fenv, который может быть очень разным в зависимости от разных условий.

О! А как-то управлять им из командной строки можно? Запустить враппер или демона, который бы гарантировал, что при работе заданного процесса всегда будет одна и та же конфигурация. Даже если процесс сам меняет эти параметры.

olegd ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.