double или float, что быстрее?

Я читаю «ускоренный C ++». Я нашел одно предложение, которое гласит: «иногда double выполняется быстрее, чем float в C ++». После прочтения предложения я запутался в float и double работе. Пожалуйста, объясните мне этот момент.

Зависит от того, что делает собственное устройство.

  • Если аппаратное обеспечение реализует double (например, x86), то float эмулируется путем расширения его там, и конверсия будет стоить времени. В этом случае double будет быстрее.

  • Если оборудование реализует только float, то эмуляция с ним будет стоить еще больше времени. В этом случае float будет быстрее.

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

Цитата, о которой вы упоминаете, вероятно, относится к платформе x86, где был указан первый случай. Но в целом это не так.

Вы можете найти полный ответ на эту статью

Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой

Это цитата из предыдущего streamа переполнения стека из float x double относительно пропускной способности памяти

Если для двойника требуется больше памяти, чем для float, для чтения данных потребуется больше времени. Это наивный ответ. На современном IA32 все зависит от того, откуда поступают данные. Если он находится в кеше L1, загрузка незначительна при условии, что данные поступают из одной строки кэша. Если он охватывает более одной строки кэша, есть небольшие накладные расходы. Если это от L2, это занимает много времени, если оно находится в ОЗУ, тогда оно еще длиннее и, наконец, если на диске это огромное время. Таким образом, выбор float или double менее важен, чем способ использования данных. Если вы хотите сделать небольшой расчет по множеству последовательных данных, предпочтительным является небольшой тип данных. Выполнение большого количества вычислений на небольшом наборе данных позволит вам использовать более крупные типы данных с любым значительным эффектом. Если вы получаете доступ к данным очень случайным образом, выбор размера данных неважен – данные загружаются в строки страниц / кеша. Поэтому, даже если вам нужен только байт из ОЗУ, вы можете получить 32 байта (это очень зависит от архитектуры системы). Помимо всего этого, CPU / FPU может быть суперскалярным (он же конвейерным). Таким образом, несмотря на то, что нагрузка может занимать несколько циклов, CPU / FPU может быть занят выполнением чего-то другого (например, умножения), который спрятает время загрузки до определенной степени

Короткий ответ: это зависит .

CPU с x87 будет сжимать поплавки и удваивает одинаково быстро. Векторизованный код будет работать быстрее с поплавками, потому что SSE может хрустить 4 поплавки или 2 удвоения за один проход.

Другое дело – скорость памяти. В зависимости от вашего алгоритма ваш процессор может много работать на холостом ходу, ожидая данных. Коду с интенсивной памятью полезно использовать поплавки, но ограниченный код ALU не будет (если он не будет векторизован).

Я могу думать о двух основных случаях, когда удваивается быстрее, чем плавает:

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

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

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

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

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

  2. Они сохраняют полосу пропускания памяти, поскольку они занимают половину пространства на число.

  3. Существуют также платформы, которые могут обрабатывать больше поплавков, чем двойные параллели.

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

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

Есть только одна причина, по которой 32-битные поплавки могут быть медленнее, чем 64-битные удваивания (или 80-бит 80х87). И это выравнивание. Помимо этого, поплавки занимают меньше памяти, что обычно означает более быстрый доступ, лучшую производительность кеша. Для обработки 32-разрядных инструкций также требуется меньше циклов. И даже если (co) -процессор не имеет 32-битных инструкций, он может выполнять их на 64-битных регистрах с одинаковой скоростью. Вероятно, возможно создать тестовый пример, где удваивается быстрее, чем float, и vv, но мои измерения реальных статистических альгос не показали заметной разницы.

В экспериментах с добавлением 3,3 для 2000000000 раз результаты:

 Summation time in s: 2.82 summed value: 6.71089e+07 // float Summation time in s: 2.78585 summed value: 6.6e+09 // double Summation time in s: 2.76812 summed value: 6.6e+09 // long double 

Таким образом, double быстрее и по умолчанию в C и C ++. Он более переносимый и по умолчанию используется во всех библиотечных функциях C и C ++. Alos double имеет значительно более высокую точность, чем float.

Даже Stroustrup рекомендует использовать двойной поплавок:

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

Возможно, единственный случай, когда вы должны использовать float вместо double, – на 64-битном оборудовании с современным gcc. Поскольку float меньше; double – 8 байтов, а float – 4 байта.

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

  • Как вы печатаете EXACT значение числа с плавающей запятой?
  • Как я могу написать функцию питания самостоятельно?
  • Преобразовать число с плавающей запятой в определенную точность, а затем скопировать в строку
  • Преобразование String для плавания в Apple Swift
  • "F" после числа / float в Objective-C / C
  • Как выполнить поразрядную операцию с числами с плавающей запятой
  • самое большое целое число, которое может быть сохранено в двойном
  • Форматирование удваивается для вывода в C #
  • Как получить знак, мантисса и показатель числа с плавающей запятой
  • Почему (360/24) / 60 = 0 ... в Java
  • Как хранится плавающая запятая? Когда это имеет значение?
  • Давайте будем гением компьютера.