Подтвердить что ты не робот

Почему двойные предпочтения по сравнению с поплавком?

В большинстве случаев, которые я вижу вокруг, double является фаворитом против float, даже если высокая точность не нужна.

Поскольку при использовании двух типов (CPU/GPU/memory/bus/cache/...) существуют штрафы за производительность, в чем причина этого двойного использования

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

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

4b9b3361

Ответ 1

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

Короткий ответ: разработчики С++ используют удвоения над float:

  • Во избежание преждевременной оптимизации, когда они плохо понимают компромиссы производительности ( "они имеют более высокую точность, почему бы и нет?" - это мыслительный процесс)
  • Привычка
  • Культура
  • Для соответствия подписей функций библиотеки
  • Для сопоставления литералов с плавающей запятой с простой записью (вы можете написать 0.0 вместо 0.0f)

Истинное значение double может быть таким же быстрым, как float для одного вычисления, потому что большинство FPU имеют более широкое внутреннее представление, чем 32-битное число с плавающей запятой или 64-битное представление.

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

Вот почему некоторые разработчики, стремящиеся оптимизировать свой код, должны изучить возможность использования 32-битных поплавков над 64-битными удвоениями:

  • Они вписываются в половину памяти. Это похоже на то, что все ваши тайники будут вдвое больше. (большая победа!!!)
  • Если вы действительно заботитесь о производительности, вы будете использовать инструкции SSE. Инструкции SSE, которые работают с значениями с плавающей запятой, имеют разные инструкции для 32-битных и 64-разрядных представлений с плавающей запятой. 32-разрядные версии могут соответствовать 4 значениям в 128-битных операндах регистра, но 64-разрядные версии могут соответствовать только двум значениям. В этом случае вы можете удвоить свои FLOPS, используя float over double, потому что каждая команда работает с вдвое большим количеством данных.

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

Ответ 2

Среди прочих:

  • Экономия вряд ли когда-либо стоит (число-хруст не типично).
  • Ошибки округления накапливаются, поэтому лучше начинать с большей точности, чем нужно с самого начала (эксперты могут знать, что это достаточно точно в любом случае, и есть расчеты, которые можно выполнить точно).
  • Общие плавающие операции с использованием fpu внутри часто часто работают с двойной или более высокой точностью.
  • C и С++ могут неявно конвертировать из float в double, другой способ требует явного приведения.
  • Функции Variadic и no-prototype всегда становятся двойными, а не float. (второй - только в древнем C и активно обескуражен)
  • Обычно вы можете выполнять операцию с более чем необходимой точностью, но редко с меньшим количеством, поэтому библиотеки обычно предпочитают более высокую точность.

Но в конце концов, YMMV: Измерьте, испытайте и решите для себя и вашей конкретной ситуации.

BTW: Еще больше для фанатиков производительности: используйте тип полуточности IEEE. Маленькая аппаратная или компиляторная поддержка для нее существует, но она снова сокращает требования к пропускной способности в два раза.

Ответ 3

double является, в некотором роде, "естественным" типом с плавающей точкой на языке C, что также влияет на С++. Предположим, что:

  • неприкрашенная обычная константа с плавающей запятой, такая как 13.9, имеет тип double. Чтобы сделать его плавающим, мы должны добавить дополнительный суффикс f или f.
  • продвижение аргументов по умолчанию в C преобразует float аргументы функции * в double: это происходит, когда для аргумента нет объявления, например, когда функция объявлена ​​как вариационная (например, printf) или не существует объявления (старый стиль C, не разрешенный в С++).
  • Спецификатор преобразования %f printf принимает аргумент double, а не float. Нет специального способа печати float -s; a float аргумент default - продвигается до double и поэтому соответствует %f.

На современном оборудовании float и double обычно отображаются соответственно 32-битным и 64-битным типам IEEE 754. Аппаратное обеспечение работает с 64-битными значениями "изначально": регистры с плавающей запятой имеют ширину 64 бит, а операции построены вокруг более точного типа (или внутренне могут быть даже точнее, чем это). Поскольку double сопоставляется с этим типом, это "естественный" тип с плавающей запятой.

Точность float плоха для любой серьезной численной работы, и проблема с уменьшением диапазона также может быть проблемой. Битовый тип IEEE 32 имеет только 23 бита мантиссы (8 бит потребляются полем экспоненты и одним битом для знака). Тип float полезен для сохранения хранилища в больших массивах значений с плавающей запятой при условии, что потеря точности и дальности не является проблемой в данном приложении. Например, 32-битные значения с плавающей запятой иногда используются в аудио для представления образцов.

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


* Обратите внимание, однако, что нет общего автоматического продвижения с float выражений до double; единственная рекламная кампания такого рода - это цельное продвижение: char, short и битовые поля, идущие к int.

Ответ 4

В основном это зависит от аппаратного обеспечения, но считают, что наиболее распространенный процессор (основанный на x86/x87) имеет внутренний FPU, который работает с точностью до 80 бит с плавающей запятой (что превышает как поплавки, так и удваивает).

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

Учесть, что поплавки имеют точность, которая приблизительно равна 6 десятичным разрядам. По сложности N-кубической сложности (например, инверсии или преобразования матрицы) вы теряете два или три в mul и div, оставаясь только с 3 значащими цифрами. На экране с разрешением 1920 пикселей они просто недостаточно (вам нужно по крайней мере 5, чтобы правильно соответствовать пикселу).

Это примерно вдвое предпочтительнее.

Ответ 5

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

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

Ответ 6

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

Я думаю, что если точность float достаточно хороша для конкретной задачи, нет смысла использовать double.