Плавание медленнее, чем в два раза? Работает ли 64-битная программа быстрее, чем 32-битная? - PullRequest
13 голосов
/ 21 апреля 2011

Используется ли тип float медленнее, чем тип double?

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

А как насчет стандартных математических функций (sqrt, pow, log, sin, cos и т. Д.)? Вычисление их с одинарной точностью должно быть значительно быстрее, поскольку для этого требуется меньше операций с плавающей запятой. Например, с одинарной точностью sqrt может использоваться более простая математическая формула, чем с двойной точностью sqrt. Кроме того, я слышал, что стандартные математические функции работают быстрее в 64-битном режиме (при компиляции и запуске в 64-битной ОС). Каков окончательный ответ на этот вопрос?

Ответы [ 6 ]

11 голосов
/ 21 апреля 2011

Классическая архитектура x86 использует модуль с плавающей точкой (FPU) для выполнения вычислений с плавающей точкой. FPU выполняет все вычисления в своих внутренних регистрах, каждый из которых имеет точность 80 бит. Каждый раз, когда вы пытаетесь работать с float или double, переменная сначала загружается из памяти во внутренний регистр FPU. Это означает, что нет абсолютно никакой разницы в скорости реальных вычислений, так как в любом случае вычисления выполняются с полной 80-битной точностью. Единственное, что может отличаться, это скорость загрузки значения из памяти и сохранения результата обратно в память. Естественно, на 32-битной платформе загрузка или сохранение double может занять больше времени по сравнению с float. На 64-битной платформе не должно быть никакой разницы.

Современные архитектуры x86 поддерживают расширенные наборы команд (SSE / SSE2) с новыми инструкциями, которые могут выполнять те же вычисления с плавающей запятой без использования «старых» инструкций FPU. Однако, опять же, я не ожидал бы увидеть разницу в скорости вычислений для float и double. И поскольку эти современные платформы являются 64-битными, скорость загрузки / сохранения данных также должна быть одинаковой.

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

Редактировать: (по адресу @MSalters comment) То, что я сказал выше, относится к фундаментальным арифметическим операциям. Когда дело доходит до библиотечных функций, ответ будет зависеть от нескольких деталей реализации. Если набор инструкций платформы с плавающей запятой содержит инструкцию, которая реализует функциональные возможности данной библиотечной функции, то то, что я сказал выше, будет обычно применяться и к этой функции (которая обычно включает такие функции, как sin, cos, sqrt). Для других функций, чьи функциональные возможности не поддерживаются сразу в наборе инструкций FP, ситуация может оказаться существенно другой. Вполне возможно, что float версии таких функций могут быть реализованы более эффективно, чем их double версии.

6 голосов
/ 21 апреля 2011

На ваш первый вопрос уже был дан ответ здесь, на SO .

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

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

2 голосов
/ 21 апреля 2011

Из некоторых исследований и эмпирических измерений, которые я провел в Java:

  • базовые арифметические операции с двойными числами и числами с плавающей запятой, по существу, выполняются одинаково на оборудовании Intel, за исключением деления;с другой стороны, на Cortex-A8, который используется в iPhone 4 и iPad, даже «базовая» арифметика для двойников занимает примерно вдвое больше времени, чем для чисел с плавающей запятой (добавление в регистр FP на поплавке занимает около 4 нс по сравнению с регистромудвоение (около 9 нс);
  • Я сделал несколько таймингов методов для java.util.Math (тригонометрические функции и т. д.), которые могут представлять интерес - в принципе, некоторые изони могут быть быстрее на поплавках, так как для вычисления точности поплавка потребуется меньше терминов;с другой стороны, многие из них оказываются «не такими плохими, как вы думаете»;

Также верно, что могут быть особые обстоятельства, в которых, например, проблемы с пропускной способностью памяти перевешивают «необработанные»"Расчет времени.

1 голос
/ 21 апреля 2011

Хотя в большинстве систем double будет иметь такую ​​же скорость, что и float для отдельных значений, вы правы в том, что вычислительные функции, такие как sqrt, sin и т. Д. С одинарной точностью, должны работать намного быстрее чем вычислять их с двойной точностью. В C99 вы можете использовать функции sqrtf, sinf и т. Д., Даже если ваши переменные равны double, и получить преимущество.

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

1 голос
/ 21 апреля 2011

«Собственное» внутреннее представление с плавающей запятой в x86 FPU имеет ширину 80 бит. Это отличается от float (32 бита) и double (64 бита). Каждый раз, когда значение входит в или из FPU, выполняется преобразование. Существует только одна инструкция FPU, которая выполняет операцию sin , и она работает на внутреннем 80-битном представлении.

Является ли это преобразование более быстрым для float или для double, зависит от многих факторов и должно измеряться для данного приложения.

0 голосов
/ 21 апреля 2011

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

...