Cortex A9 NEON против путаницы в использовании VFP - PullRequest
19 голосов
/ 01 сентября 2011

Я пытаюсь создать библиотеку для ARM-процессора Cortex A9 (OMAP4, если быть более точным), и я немного сбит с толку относительно того, когда \ когда использовать NEON против VFP в контексте с плавающей запятой операции и SIMD. Следует отметить, что я знаю разницу между двумя аппаратными сопроцессорными модулями (как также указано здесь на SO ), у меня просто есть некоторое недопонимание относительно их правильного использования.

В связи с этим я использую следующие флаги компиляции:

GCC
-O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
-O3 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp
ARMCC
--cpu=Cortex-A9 --apcs=/softfp
--cpu=Cortex-A9 --fpu=VFPv3 --apcs=/softfp

Я прочитал документацию по ARM, много вики (, как эта ), сообщения на форумах и в блогах, и все, похоже, согласны с тем, что использование NEON лучше, чем использование VFP. или, по крайней мере, смешивание NEON (например, использование встроенных функций для реализации некоторых алгоритмов в SIMD) и VFP не очень хорошая идея; Я еще не уверен на 100%, применимо ли это в контексте всего приложения \ библиотеки или только к определенным местам (функциям) в коде.

Так что я использую неон в качестве FPU для своего приложения, так как я также хочу использовать встроенные функции. В результате у меня возникли небольшие проблемы, и моя путаница в том, как наилучшим образом использовать эти функции (NEON против VFP) на Cortex A9, еще больше углубляется, а не проясняется. У меня есть код, который выполняет тестирование для моего приложения и использует некоторые пользовательские классы таймера в котором расчеты основаны на двойной точности с плавающей запятой. Использование NEON в качестве FPU дает совершенно неподходящие результаты (попытка распечатать эти значения приводит к печати в основном inf и NaN; тот же код работает без проблем при сборке для x86). Поэтому я изменил свои вычисления, чтобы использовать плавающую точку одинарной точности, поскольку задокументировано, что NEON не обрабатывает плавающую точку двойной точности . Мои тесты по-прежнему не дают правильных результатов (и что хуже всего, теперь они больше не работают на x86; я думаю, что это из-за потери точности, но я не уверен). Так что я почти полностью растерялся: с одной стороны, я хочу использовать NEON для возможностей SIMD и использовать его, поскольку FPU не дает надлежащих результатов, с другой стороны, смешивание его с VFP не кажется очень хорошей идеей. Будем весьма благодарны за любые советы в этой области !!

Я нашел в статье в вышеупомянутой вики сводку того, что нужно сделать для оптимизации с плавающей запятой в контексте NEON:

"

  • Использовать только одинарную точность с плавающей точкой
  • Используйте NEON intrinsics / ASM, когда вы обнаружите узкую функцию FP. Вы можете сделать лучше, чем компилятор.
  • Свернуть условные ветви
  • Включить режим RunFast

Для softfp:

  • Встроенный код с плавающей запятой (если он не очень большой)
  • Передайте аргументы FP через указатели вместо значений и выполняйте целочисленную работу между вызовами функций.

"

Я не могу использовать hard для плавающего ABI, так как не могу связываться с имеющимися у меня библиотеками. Большинство рекомендаций имеют смысл для меня (за исключением «режима быстрого запуска», который я точно не понимаю, что должно делать, и того факта, что в данный момент я могу добиться большего успеха, чем компилятор), но я продолжаю получать противоречивые результаты и Я сейчас ни в чем не уверен.

Может ли кто-нибудь пролить свет на то, как правильно использовать число с плавающей запятой и NEON для Cortex A9 / A8 и какие флаги компиляции мне следует использовать?

Ответы [ 3 ]

8 голосов
/ 04 августа 2016

... сообщения на форумах и в блогах, и все, кажется, согласны с тем, что использование NEON лучше, чем использование VFP или, по крайней мере, смешивание NEON (например, использование instrinsics для реализации некоторых алгоритмов в SIMD), а VFP не очень хорошидея

Я не уверен, что это правильно.Согласно ARM на Представляя NEON Development Статья |Регистры NEON :

Банк регистров NEON состоит из 32 64-битных регистров.Если реализованы и Advanced SIMD, и VFPv3, они совместно используют этот банк регистров.В этом случае VFPv3 реализован в форме VFPv3-D32, которая поддерживает 32 регистра с плавающей запятой двойной точности.Эта интеграция упрощает реализацию поддержки переключения контекста, поскольку те же подпрограммы, которые сохраняют и восстанавливают контекст VFP, также сохраняют и восстанавливают контекст NEON.

Устройство NEON может просматривать тот же банк регистров, что и:

  • шестнадцать 128-битных регистров четырех слов, Q0-Q15
  • тридцать два 64-битных регистра двойных слов, D0-D31.

Регистры NEON D0-D31 такие же, какРегистры VFPv3 D0-D31 и каждый из регистров Q0-Q15 отображаются на пару регистров D.На рисунке 1.3 показаны различные виды общего банка регистров NEON и VFP.Все эти виды доступны в любое время.Программное обеспечение не должно явно переключаться между ними, потому что используемая инструкция определяет соответствующий вид.

Регистры не конкурируют;скорее они сосуществуют как взгляды банка регистрации.Нет способа сорвать снаряжение NEON и FPU.


В связи с этим я использую следующие флаги компиляции:

-O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
-O3 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp

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

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

BeagleBone Black :

$ gcc -v 2>&1 | grep Target          
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
model name  : ARMv7 Processor rev 2 (v7l)
Features    : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 
...

Таким образом, BeagleBone использует:

-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard

CubieTruck v5 :

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
Processor   : ARMv7 Processor rev 5 (v7l)
Features    : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 

Поэтому CubieTruck использует:

-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard

Banana Pi Pro :

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo
Processor   : ARMv7 Processor rev 4 (v7l)
Features    : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt

Итак, Banana Pi использует:

-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard

Raspberry Pi 3 :

RPI3 уникален тем, что его ARMv8, но работает под управлением 32-разрядной ОС.Это означает, что это эффективно 32-битный ARM или Aarch32.Есть немного больше, чем 32-битный ARM против Aarch32, но он покажет вам флаги Aarch32

Кроме того, RPI3 использует SoC Broadcom A53, и он имеет NEON и дополнительные инструкции CRC32, но не имеет дополнительныхCrypto extensions.

$ gcc -v 2>&1 | grep Target 
Target: arm-linux-gnueabihf

$ cat /proc/cpuinfo 
model name  : ARMv7 Processor rev 4 (v7l)
Features    : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
...

Таким образом, Raspberry Pi может использовать:

-march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard

Или может использовать (я не знаю, что использовать для -mtune):

-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard 

ODROID C2 :

ODROID C2 использует SoC Amlogic A53, но использует 64-битную ОС.ODROID C2, он имеет NEON и дополнительные инструкции CRC32, но не имеет дополнительных расширений Crypto (аналогично конфигурации RPI3).

$ gcc -v 2>&1 | grep Target 
Target: aarch64-linux-gnu

$ cat /proc/cpuinfo 
Features    : fp asimd evtstrm crc32

Таким образом, ODROID использует:

-march=armv8-a+crc -mtune=cortex-a53

В приведенных выше рецептах я изучил процессор ARM (например, Cortex A9 или A53), изучив таблицы данных.Согласно этому ответу на Unix и Linux Stack Exchange , который расшифровывает вывод из /proc/cpuinfo:

Часть ЦП: Номер детали.0xd03 обозначает процессор Cortex-A53.

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

8 голосов
/ 13 сентября 2011

Я думаю, что этот вопрос следует разделить на несколько, добавив несколько примеров кода и детализируя целевую платформу и используемые версии цепочек инструментов.

Но чтобы охватить одну часть путаницы: рекомендация "использовать NEON какFPU "звучит как недоразумение.NEON - это SIMD-движок, VFP - это FPU.Вы можете использовать NEON для операций с плавающей запятой одинарной точности на 4 параллельных значениях с одинарной точностью, что (по возможности) хорошо для производительности.

-mfpu=neon можно рассматривать как сокращение для -mfpu=neon-vfpv3.

Подробнее см. http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.

3 голосов
/ 01 ноября 2011

Я бы держался подальше от VFP. Это похоже на режим Thmub: он предназначен для компиляторов. Нет смысла их оптимизировать.

Это может звучать грубо, но я на самом деле не вижу смысла и в НЕОН. Больше проблем, чем помощи - если есть.

Просто потратьте два или три дня на базовую сборку ARM: вам нужно всего лишь изучить несколько инструкций по контролю / завершению цикла.

Тогда вы можете начать писать нативные коды NEON, не беспокоясь о том, что компилятор делает что-то астральное, выплевывая тонны ошибок / предупреждений.

Изучение NEON-инструкций менее требовательно, чем все эти встроенные макросы. И все это намного лучше.

Полностью оптимизированные нативные коды NEON обычно выполняются более чем в два раза быстрее, чем хорошо написанные встроенные аналоги.

Просто сравните версию ОП с моей по ссылке ниже, и вы поймете, что я имею в виду.

Оптимизация преобразования RGBA8888 в RGB565 с NEON

привет

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