Может ли компилятор C автоматически оптимизировать float для double для меня?

#c #optimization #floating-point #double

#c #оптимизация #значение с плавающей запятой #double

Вопрос:

Мне было интересно, что, возможно, double быстрее на некоторых машинах, чем float.

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

Могу ли я использовать float везде и быть уверенным, что оптимизирующий компилятор VC 2008 преобразует его в double, если сочтет это более подходящим? Я не понимаю, как это может нарушить код.

Заранее спасибо!

Комментарии:

1. Нет. Точность — это дизайнерское решение, принятое дизайнером. «считает это более подходящим»? Как это будет работать? Можете ли вы дать правило для этого? Правило, которое не разрушило бы чьи-то расчеты?

2. 32-разрядный float по крайней мере, такой же быстрый, как [64/128-разрядный] double на 32-разрядных машинах.

3. Нет, это не оптимизирует его для вас. Однако вы всегда можете сделать это регистром

4. @S.Лотт Можете ли вы дать правило для этого? Правило, которое не испортило бы чьи-либо вычисления? Я подумал, что все значения ‘float’ в коде можно заменить на ‘double’ без какого-либо большого влияния на вычисления. Известно, что оптимизация с плавающей запятой уже в любом случае «прерывает» ненадежные вычисления.

5. Если вы хотите, чтобы это было double , объявите это так. Когда компиляторы оптимизируют, они делают вам одолжение — им не нужно этого делать.

Ответ №1:

Нет, компилятор не будет изменять фундаментальный тип, такой как float, на double для оптимизации.

Если вы считаете, что это вероятно, используйте typedef для вашей плавающей точки в общем заголовке, например typedef float FASTFLOAT; и используйте FASTFLOAT (или как вы это называете) во всем вашем коде. Затем вы можете изменить одно центральное значение typedef и изменять тип во всем вашем коде.

Мой собственный опыт показывает, что float и double в настоящее время в основном сопоставимы по производительности на платформах x86 / x64 для математических операций, и я склонен предпочитать double . Если вы обрабатываете много данных (и сталкиваетесь с проблемами пропускной способности памяти, вместо того, чтобы быть привязанным к вычислениям), вы можете получить некоторое преимущество в производительности от того факта, что значения float вдвое меньше, чем double .

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

Комментарии:

1. Это может не изменить тип переменной. Но он все равно мог бы выполнить арифметику для удвоений, если дополнительная скорость была полезна, и преобразовать обратно в float для хранения в переменной.

2. Достаточно верно. Также, насколько я помню, операции с float выполняются над 40-разрядными значениями в аппаратном обеспечении, которые затем усекаются до 32-разрядных для хранения. (Кто-нибудь может найти ссылку на это?)

Ответ №2:

Во-первых, компилятор не изменяет типы float, если это не необходимо, и никогда в объявлениях хранилища.

float будет не медленнее, чем double , но если вы действительно хотите быструю обработку, вам нужно либо использовать компилятор, который может генерировать код SSE2 или SSE3, либо вам нужно написать свои процедуры интенсивной обработки, используя эти инструкции. IIRC, есть инструменты, которые могут помочь вам при необходимости микроуправлять конвейером процессора. В последний раз, когда я возился с этим (много лет назад), у Intel была библиотека под названием IPP, которая также могла бы помочь путем векторизации вашей математики.

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

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

Комментарии:

1. Хотя это не совсем проблема с float и double, на x86 регистры FPU имеют ширину 80 бит, в то время как значения float и double равны 32 и 64 битам соответственно. Строгое прочтение стандарта C требует частых сокращений до ширины запрошенного вами типа хранилища; это требует времени. У GCC есть -ffast-math флаг, чтобы отключить эти усечения и выполнить некоторые промежуточные вычисления с точностью выше допустимой; однако я не знаю о MSVC.

Ответ №3:

Когда коду необходимо сохранить переменную в памяти, скорее всего, на большинстве архитектур потребуется 32 бита для a float и 64 бита для a double . Выполнение преобразования размера памяти предотвратило бы полную оптимизацию такого.

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