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

Поплавок или Двойной?

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

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

ИЗМЕНИТЬ 1: Единственная причина, по которой это относится к андроиду, - это то, что я считаю памятью важной; Я бы даже не просил об этом для разработки настольных систем.

4b9b3361

Ответ 1

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

Ответ 2

Скорость обработки на обоих типах в наши дни должна быть примерно одинаковой.

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

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

Изменить:

В терминах скорости нет разницы между float и double на более современном оборудовании.

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

Ответ 3

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

Я использовал FloatMath.sin, и вместо этого предложил Math.sin со следующим в контекстном меню "Объяснить проблему". Он читает мне как общее сообщение, касающееся double vs float, а не только связанное с ним.

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

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

Ответ 4

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

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

Как правило, с плавающей запятой примерно 2x медленнее, чем integer on Устройства на базе Android.

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

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

Ответ 5

float - 32 бита или 4 байта

double - это 64 бита или 8 байтов

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

Ответ 6

В терминах скорости нет разницы между float и double на более современном оборудовании.

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

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

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

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

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

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

Ответ 7

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

#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 фактически не дает вам памяти, пока вы ее не используете, а окна просто передают вам все сразу, что требует меньше системных вызовов. Или, возможно, назначение оптимизировано.

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

Ответ 8

Указанная цитата в android указывает, что целые числа предпочтительны для быстрых операций. Это кажется немного странным на первый взгляд, но скорость алгоритма с использованием ints vs floats vs doubles зависит от нескольких слоев:

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

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

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

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