Почему использование float вместо двойной не улучшает производительность Android?

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

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

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

Есть ли хорошее объяснение этому? Это связано с тем, как работает Dalvik VM, или что?

Ответ 1

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

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

Существуют также векторные единицы, которые имеют 32-битные FPU, в результате чего операции с 64-разрядными операциями с плавающей запятой занимают больше времени. Некоторые SIMD-устройства (например, те, которые выполняют инструкции SSE) выполняют 32-разрядные и 64-разрядные операции за такое же количество времени, поэтому вы могли бы делать в два раза больше 32-битных операционных систем одновременно, но один 32-битный оператор выиграл 't идти быстрее, чем один 64-битный оператор.

Ответ 2

Многие, возможно, большинство устройств Android не имеют копроцессора с плавающей запятой.

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

Это не очень хорошо работает на устройствах Android, у которых отсутствует процессор с плавающей запятой.

Переместите его в C/С++ с помощью NDK, затем ограничьте свои цели до ARM7, у которого есть сопроцессор с плавающей запятой.

Или измените свою математику на работу в режиме фиксированной точки. Например, Google Maps не имеет десятичных степеней для широты и долготы, а скорее для микродегретов (10-6 раз), в частности, чтобы он мог выполнять свои вычисления с использованием математики с фиксированной точкой.

Ответ 3

Кажется, вы используете Nexus One, у которого есть ядро ​​Scorpion.

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

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