2017-02-17 49 views
3

Я пытаюсь сделать FFT ->signal manipulation ->Inverse FFT с использованием Project NE10 в моем СРР проекта и преобразовать сложный вывод амплитуд и фаз для быстрого преобразования Фурье и наоборот для IFFT , Но производительность моего кода на C++ не так хороша, как код NE10 с поддержкой SIMD в соответствии с эталонами. Поскольку у меня нет опыта в сборке рук, я ищу некоторую помощь для написания неонового кода для неоптимизированного модуля C. Например, перед ОБПФОМ я сделать это:Неон код для преобразования/б прямоугольных и полярных форм

for (int bin = 0; bin < NUM_FREQUENCY_BINS; bin++) { 
    input[bin].real = amplitudes[bin] * cosf(phases[bin]); 
    input[bin].imag = amplitudes[bin] * sinf(phases[bin]); 
} 

, где input является массивом структур C (для комплексных значений), amplitudes & phases является float массивов.

Вышеуказанный блок (O(n) complexity) занимает около 0,6 мс для 8192 лотков, а NE10 FFT (O(n*log(n)) complexity) занимает всего 0,1 мс из-за операций SIMD. Из того, что я читал до сих пор в StackOverflow и других местах, intrinsics не стоит усилий, поэтому я стараюсь только в руке neon.

+0

Intrinsics может * абсолютно * стоить усилий. В частности, вы можете оставить утомительную работу, такую ​​как распределение регистров компилятору, что позволит * улучшить * производительность по сравнению с рукописной сборкой, если вы не очень хорошо умеете писать сборку и не знаете детали микроархитектуры, на которой будет работать код. – EOF

+1

У меня есть пример (пример) (https://godbolt.org/g/te0BzE), который показывает вызовы 'cosf' и' sinf' в цикле. Функциональные вызовы дают много накладных расходов. Здесь [ссылка здесь для вас] (http://stackoverflow.com/questions/1854254/fast-sine-cosine-for-armv7neon-looking-for-testers) и [еще одна ссылка] (http: // gruntthepeon. free.fr/ssemath/neon_mathfun.html). 'cosf' и' sinf' связаны между собой так, что вычисляют оба. Стандартная библиотека «C» имеет очень строгую точность (или, по крайней мере, это акцент). [Sin (х)^2 + соз (х)^2 = 1] (https://en.wikibooks.org/wiki/Trigonometry/Sine_Squared_plus_Cosine_Squared). –

+0

... оба сразу выше ... При этом ваша «манипуляция сигналом» может выполняться на полярной или реальной/мнимой, поэтому вам не нужно делать это преобразование. На самом деле вам нужно сделать некоторую математику, чтобы держать вещи в одинаковых координатах (или, по крайней мере, это стоит исследовать). «Convolution» может быть что-то для вас, чтобы добавить в свой набор инструментов? Или, по крайней мере, аспект вашей манипуляции с сигналом, вероятно, важен; Т.е. почему вам нужно преобразование? –

ответ

0

Как я знаю, NEON не поддерживает векторные операции для геометрических функций (sin, cos). Но, конечно, вы можете улучшить свой код. В качестве варианта вы можете использовать таблицу предварительно рассчитанных значений функций sinus и cosine. Это может привести к значительному повышению производительности.

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^