Float или Double? - PullRequest
       23

Float или Double?

29 голосов
/ 04 июня 2011

Что быстрее, вдвое или с плавающей запятой при предварительном формировании арифметики (+ - * /%), и стоит ли просто использовать float по соображениям памяти? Точность не является большой проблемой.

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

РЕДАКТИРОВАТЬ 1: Единственная причина, по которой это происходит под андроидом, заключается в том, что именно здесь я считаю, что память имеет значение; Я бы даже не попросил об этом для разработки десктопов.

Ответы [ 8 ]

25 голосов
/ 04 июня 2011

В настоящее время скорость обработки обоих типов должна быть примерно одинаковой в процессорах.

«Используйте ту точность, которая требуется для получения приемлемых результатов».

Связанные вопросы были заданы несколько раз здесь, на SO, вот один .

Редактировать:

С точки зрения скорости, нет разницы между float и double на более современном оборудовании.

Пожалуйста, ознакомьтесь с этой статьей с developer.android.com.

15 голосов
/ 25 ноября 2012

Double, а не Float, было рекомендовано сообщением ADT v21 lint из-за оптимизации JIT (Just In Time) в Dalvik начиная с Froyo (API 8 и более поздние версии).

Я использовал FloatMath.sin, и он предложил вместо этого Math.sin со следующим в контекстном меню «объяснить проблему». Это читается мне как общее сообщение о двойном и плавающем, а не только о триггере.

"В старых версиях Android, используя android.util.FloatMath был рекомендован для причины производительности при работе на поплавках. Тем не менее, на современном оборудовании удваиваются так же быстро как плавать (хотя они занимают больше памяти), а в последние версии Android, FloatMath на самом деле медленнее, чем использование java.lang.Math из-за способа JIT оптимизирует java.lang.Math. Поэтому вы должны использовать Math вместо FloatMath, если вы только нацеливаетесь Фройо и выше. "

Надеюсь, это поможет.

6 голосов
/ 19 сентября 2013

http://developer.android.com/training/articles/perf-tips.html#AvoidFloat

Избегайте использования чисел с плавающей точкой

Как правило, с плавающей точкой примерно в 2 раза медленнее, чем целое число на Устройства на платформе Android.

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

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

6 голосов
/ 04 июня 2011

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

4 голосов
/ 04 июня 2011

число с плавающей точкой - 32 бита или 4 байта

значение типа double - 64 бита или 8 байтов

, так что да, число с плавающей точкой в ​​два раза меньше согласно книге сертификации Sun Java.

3 голосов
/ 13 февраля 2013

С точки зрения скорости, нет разницы между float и double на более современном оборудовании.

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

  • Проверка кода с плавающей точкой занимает 4,7 секунды
  • Тот же код с "двойной" занимает 6,6 секунды

Этот вопрос задавался пару раз ...

Да. Потому что ответ отличается для разных типов оборудования. На настольных компьютерах double имеет ту же скорость, что и float. На устройствах без FPU (интересно для взломов WLAN-роутеров) float в 2-5 раз быстрее, чем double; и на устройствах с 32-разрядным FPU (часто используется в промышленных и автомобильных приложениях) даже до 100 раз.

Пожалуйста, ознакомьтесь с этой статьей ...

В последнем разделе статьи говорится, что вы должны выполнять измерения времени на устройстве, которое собираетесь использовать, чтобы быть на 100% уверенным.

1 голос
/ 03 ноября 2016

Приведенная в документации Android указывает, что целые числа предпочтительнее для быстрых операций. На первый взгляд это кажется немного странным, но скорость алгоритма, использующего ints vs float vs doubles, зависит от нескольких слоев:

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

  2. Собственное аппаратное обеспечение (почему первый уровень не идеален): большинство процессоров в настоящее время имеют аппаратные блоки с плавающей запятой (те поддерживают числа с плавающей запятой и двойные числа). Если такой аппаратный модуль присутствует, числа с плавающей запятой / двойные числа могут быть быстрее, чем целые числа, если только не существует аппаратной поддержки целых чисел. Проблема усугубляется тем, что большинство процессоров имеют некоторую форму поддержки SIMD (Single Instruction Multiple Data), которая позволяет векторизовать операции, если типы данных достаточно малы (например, добавить 4 числа с плавающей точкой в ​​одну инструкцию, поместив два в каждый регистр вместо использовать один целый регистр для каждого из 4 двойников). Это может позволить обрабатывать типы данных, которые используют меньше битов, гораздо быстрее, чем удваивать, за счет точности.

Оптимизация для скорости требует детального знания обоих этих уровней и того, как они взаимодействуют. Даже оптимизация использования памяти может оказаться непростой задачей, поскольку виртуальная машина может представлять ваши данные более широко по другим причинам: число с плавающей запятой может занимать 8 байт в коде виртуальной машины, хотя это менее вероятно. Все это делает оптимизацию почти полной противоположностью переносимости. Итак, здесь снова, лучше использовать рекомендованный «быстрый» тип данных виртуальной машины, поскольку это должно привести к наилучшей производительности, усредненной по поддерживаемым устройствам.

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

0 голосов
/ 13 декабря 2012

Я тоже задумался над этим и написал небольшой тест:

#include <iostream>
#include <chrono>

template<typename numType>
void test(void)  {
    std::cout<< "Size of variable: " << sizeof(numType) << std::endl;
    numType array[20000];

    auto t1 = std::chrono::high_resolution_clock::now();
    // fill array
    for( numType& number : array ) {
        number = 1.0014535;
    }

    auto t2 = std::chrono::high_resolution_clock::now();

    // multiply each number with itself 10.000 times
    for( numType& number : array ) {
        for( int i=0; i < 10000 ; i++ )  {
            number *= number;
        }
    }

    auto t3 = std::chrono::high_resolution_clock::now();

    auto filltime = t2 - t1;
    auto calctime = t3 - t2;

    std::cout<< "Fill time: " << filltime.count() << std::endl;
    std::cout<< "Calc time: " << calctime.count() << std::endl;
}

int main(int argc, char* argv[]) {
    test<float>();
    test<double>();
}

Я запустил и скомпилировал его под Ubuntu 12.04 x64, используя GCC на процессоре Intel i7 3930k

Это были результаты:

Size of variable: 4
Fill time: 69
Calc time: 694303

Size of variable: 8
Fill time: 76
Calc time: 693363

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


Из любопытства я также запустил и скомпилировал его под Windows 7 x64, используя Visual Studio 2012 в режиме выпуска на процессоре Intel i7 920

(Единица времени отличается, поэтому не сравнивайте приведенные выше результаты с этими: она действительна только для внутреннего сравнения)

Size of variable: 4
Fill time: 0
Calc time: 3200183

Size of variable: 8
Fill time: 0
Calc time: 3890223

Результаты были воспроизводимы.

Похоже, что распределение окон происходит мгновенно, возможно, потому что linux на самом деле не дает вам память, пока вы не используете ее, в то время как Windows просто передает все это вам сразу, требуя меньше системных вызовов. Или возможно назначение оптимизировано далеко.

Умножение удваивается здесь на 21,5% медленнее, чем для чисел с плавающей точкой. Эта разница с предыдущим тестом, вероятно, связана с другим процессором (по крайней мере, это мое лучшее предположение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...