Есть ли (Linux) g ++, эквивалентный / fp: точные и / fp: fast флаги, используемые в Visual Studio? - PullRequest
11 голосов
/ 13 июля 2010

Справочная информация:

Много лет назад я унаследовал кодовую базу, которая использовала флаг Visual Studio (VC ++) '/ fp: fast' для создания более быстрого кода в конкретном вычислении.тяжелая библиотека.К сожалению, «/ fp: fast» дал результаты, которые немного отличались от той же библиотеки в другом компиляторе (Borland C ++).Поскольку нам нужно было получать точно такие же результаты, я переключился на «/ fp: точный», который работал нормально, и с тех пор все стало превосходно.Тем не менее, сейчас я собираю ту же библиотеку с g ++ для uBuntu Linux 10.04, и я вижу похожее поведение, и мне интересно, может ли она иметь аналогичную основную причину.Численные результаты моей сборки g ++ немного отличаются от численных результатов моей сборки VC ++.Это подводит меня к моему вопросу:

Вопрос:

Имеет ли g ++ параметры, эквивалентные или сходные с параметрами fp: fast и fp: точные в VC ++??(и что это? Я хочу активировать эквивалент 'fp: точный'.)

Более подробная информация:

Я компилирую, используя 'make', которая вызываетг ++.Насколько я могу судить (файлы make немного загадочны и не были написаны мной), единственные параметры, добавленные к вызову g ++, - это «нормальные» параметры (включая папки и файлы для компиляции) и -fPIC (Я не уверен, что делает этот переключатель, я не вижу его на странице man).

Единственные релевантные параметры в man g ++, по-видимому, относятся к включению параметров оптимизации.(например, -funsafe-math-optimizations).Однако я не думаю, что что-то включаю, я просто хочу отключить соответствующую оптимизацию.

Я пробовал сборки Release и Debug, VC ++ дает те же результаты для выпуска и отладки, иg ++ дает те же результаты для выпуска и отладки, но я не могу получить версию g ++, которая дает те же результаты, что и версия VC ++.

Ответы [ 5 ]

18 голосов
/ 13 июля 2010

Из руководства GCC :

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

Эта опция предотвращает нежелательную избыточную точность на машинах, таких как 68000, где плавающие регистры (из 68881) сохраняют большую точность, чем предполагалось для удвоения. Аналогично для архитектуры x86. Для большинства программ избыточная точность приносит только пользу, но некоторые программы полагаются на точное определение плавающей запятой IEEE. Используйте -ffloat-store для таких программ, изменив их, чтобы сохранить все соответствующие промежуточные вычисления в переменных.

Чтобы немного расширить, большинство этих расхождений происходит из-за использования 80-разрядных регистров с плавающей запятой x86 для вычислений (в отличие от 64-разрядных, используемых для хранения значений double). Если промежуточные результаты хранятся в регистрах без обратной записи в память, вы фактически получаете 16 бит дополнительной точности в своих вычислениях, делая их более точными, но, возможно, отличающимися от результатов, полученных при записи / чтении промежуточных значений в память (или от вычислений по архитектуры, которые имеют только 64-битные регистры FP).

Эти флаги (как в GCC, так и в MSVC) обычно приводят к усечению каждого промежуточного результата до 64-битных, что делает вычисления нечувствительными к капризам генерации и оптимизации кода и различиям платформы. Такая согласованность обычно сопровождается небольшими затратами времени выполнения в дополнение к стоимости с точки зрения точности / точности.

10 голосов
/ 13 июля 2010

Чрезмерная точность регистров является проблемой только для регистров FPU, которых компиляторы (с правильными разрешающими переключателями) все равно стараются избегать. Когда вычисления с плавающей запятой выполняются в регистрах SSE, точность регистров равна памяти.

По моему опыту, большая часть влияния / fp: fast (и потенциальное несоответствие) исходит от компилятора, позволяющего выполнять алгебраические преобразования. Это может быть так же просто, как изменить порядок слагаемых:

( a + b ) + c --> a + ( b + c)

может быть - распределение умножений, таких как * (b + c), по желанию, и может получить некоторые довольно сложные преобразования - все это предназначено для повторного использования предыдущих вычислений. Конечно, в бесконечной точности такие преобразования являются доброкачественными, но в конечной точности они действительно меняют результат. В качестве игрушечного примера, попробуйте пример порядка слагаемых с a = b = 2 ^ (- 23), c = 1. Эрик Флигал из MS (1006 *) описывает его более подробно .

В этом отношении переключатель gcc, ближайший к / fp: точный -fno-unsafe-math-optimizations. Я думаю, что он включен по умолчанию - возможно, вы можете попытаться установить его явно и посмотреть, если это имеет значение. Точно так же вы можете попробовать явно отключить все оптимизации -ffast-math: -fno-finite-math-only, -fmath-errno, -ftrapping-math, -frounding-math и -fsignaling-nans (последние 2 опции: не по умолчанию!)

5 голосов
/ 13 июля 2010

Я не думаю, что есть точный эквивалент.Вы можете попробовать -mfpmath=sse вместо значения по умолчанию -mfpmath=387, чтобы посмотреть, поможет ли это.

1 голос
/ 13 июля 2010

Это определенно не связано с флагами оптимизации, предполагая, что под «отладкой» подразумевается «с отключенными оптимизациями». Если g ++ дает те же результаты в отладке, что и в выпуске, это означает, что это не связано с оптимизацией. Отладочные сборки всегда должны хранить каждый промежуточный результат в памяти, тем самым гарантируя те же результаты, что и / fp: precision для MSVC.

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

0 голосов
/ 13 июля 2010

-mpc32 или -mpc64?

Но вам может понадобиться перекомпилировать C и математические библиотеки с переключателем, чтобы увидеть разницу ... Это может относиться и к другим вариантам, предложенным.

...