Написання алгоритмів DSP безпосередньо в С або складання? [зачинено]


18

Я працюю над проектом DSP (фільтрація IIR) на цифровому сигнальному процесорі аналогових пристроїв (BF706) з комплектом компілятора, що йде разом з ним, CrossCore Studio. У ньому є кілька прикладів для простих DSP-матеріалів, таких як фільтри FIR та IIR та бібліотечні функції. Посібник з процесора описує набір інструкцій по збірці та не коментує C.

Моє запитання виникає саме в цій програмі, але я подумав, що існує найкраща практика, яку слідкують розробники DSP. Тож я буду це обрамляти загальним чином:

Що я зрозумів на прикладах із цим DSP, це те, що якщо я хочу використовувати схеми, призначені для DSP-програм, мені потрібно запрограмувати в зборі, щоб безпосередньо виконувати ці інструкції (як, наприклад, множення та додавання тощо). Моє запитання: Я просто програмував на C, чи не став би компілятор (який також походить від компанії чіпів DSP) не оптимізував його для цього DSP і не використовував його можливості? Або мені дійсно потрібно писати підпрограми DSP безпосередньо в зборах?


17
Я витратив багато років на написання збірки для ADSP-21xx (і збірки та C для Blackfin, пізніше.) Ви не розголошуєте, що використовуєте, тому будь-яка відповідь буде більше здогадом та думкою, ніж будь-що інше. Але DSP-процесори AD - це гарний матеріал, і авторам-компіляторам C дуже важко правильно заповнити трубу, так би мовити. У мене є досвід роботи в цій галузі за два десятиліття (включаючи дуже скромний досвід написання компілятора C) і до тих пір, поки я не припинив писати код (кілька років тому), компілятори C не змогли наблизитися до ручного кодування. Але те, що ви робите, залежить від ваших цілей.
jonk

1
@jonk сподіваюсь, що ви збираєтесь написати відповідь на цей - я коли-небудь робив один хардкорний проект DSP Blackfin, але у мене є приємні спогади про деякі
хакерські

6
@pericynthion Ні, я не можу уявити, щоб написати відповідь на нього, якщо ОП не розповість багато більше про конкретний DSP та цілі проекту. В іншому випадку це було б невиразними, некерованими думками, які могли б бути дуже правильними або дуже помилковими залежно від того, що про це тоді написала ОП. Тож я просто зачекаю.
jonk

1
Якщо ви хочете, щоб він запускався найшвидше, ви вручну оптимізували його в зборі. Це час \ грошові компроміси. Якщо ви вмієте писати гарний C, ви можете пройти туди більшу частину шляху.
Спайк напруги

2
Я не впевнений у DSP, але для більшості мікропроцесорів ви можете використовувати внутрішні елементи, які знаходяться на півдорозі між написанням асемблера та кодом С.
Maciej Piechotka

Відповіді:


20

Завжди краще, щоб ваш алгоритм був реалізований мовою вищого рівня (що C порівнюється зі складанням), навіть якщо ви плануєте в кінцевому підсумку реалізувати все в зборі.

  • швидше за все, вам навіть не знадобиться збірка . Якщо код, сформований вашим компілятором, відповідає вашим цілям дизайну, ваша робота виконана.

  • якщо ні, ви не будете починати кодування збірки з нуля . Дозвольте компілятору генерувати для вас початковий код і використовуйте його як основу для оптимізованої версії збірки.

  • пізніше, коли вам потрібно буде протестувати оптимізований код складання , ви будете раді, що ви отримаєте версію C. Замість того, щоб вручну обчислити правильний вихід для своїх тестових вхідних даних, ви можете просто подати ці вхідні дані у вашу неоптимізовану реалізацію C, а потім перевірити, чи збірка дає точно такий же вихід після оптимізацій, які ви здійснили.

Якщо через кілька років новому розробнику потрібно буде внести зміни в ваш алгоритм, і все, що вони мають під рукою, - це високооптимізований код складання, є велика ймовірність, що їм доведеться почати з нуля.


23

Якщо автори-компілятори докладуть певних зусиль для оптимізації її для цієї мети, вона, принаймні, скористається спеціальними інструкціями / архітектурою DSP. Але для максимальної продуктивності це ніколи не буде настільки добре, як ручна настройка збірки. Це може бути досить добре, але це залежить від вашої заявки.

Інші альтернативи включають:

  1. Напишіть більшу частину вашої програми на мові С, і лише найважливішу числову частину в зборі.
  2. Напишіть програму на C та використовуйте бібліотеки, надані виробником або сторонніми особами - якщо ви виконуєте загальні завдання DSP, такі як FFT, фільтри FIR / IIR тощо. Ви можете скористатися цим (можливо, доведеться заплатити за нього) та зв’язати це зі своєю заявою.

Зазвичай постачальники DSP постачають вихідний код для загальних функцій. Якщо їх код "достатньо хороший", ви можете залишити його прямо. Якщо це не зовсім правильно, вам доведеться його налаштувати. Мені довелося робити шар FFT кілька років тому, щоб отримати справжній частотний FFT. Існує хитрість, яка дозволяє зробити 2-бальну реальну FFT як комплексну FFT з N-точок, але тоді вам доведеться зробити остаточний прохід над складним виходом, щоб відновити дані реальної частоти. У своєму прикладі коду аналогових пристроїв не було такого конкретного випадку.
Джон Р. Стром

21

Передчасна оптимізація - корінь усього зла. - Дональд Кнут

Коли ви виявите, що не отримуєте достатньої продуктивності від свого коду, спершу профілюйте програму, знайдіть вузькі місця, проаналізуйте свої вимоги до продуктивності та лише потім починайте робити оптимізації. Написання асемблерного коду в останню чергу.

Моє запитання: якщо я просто програмую на C, чи не став би компілятор (який також походить від компанії чіпів DSP), не оптимізував його для цього DSP і не використовував його можливості?

Так, компілятор C може зробити неабияку оптимізацію. Але це залежить від якості компілятора. Часто людина може записати швидший збірний код, ніж компільований код C. За великі витрати людського болю і страждань, тобто.

Або мені дійсно потрібно писати підпрограми DSP безпосередньо в зборах?

Спочатку напишіть на C, потім профіль, а потім вирішіть, чи потрібно писати в зборі. Сподіваємось, вам не знадобиться збірка.


20
В цілому програмування це, безумовно, хороша порада, але DSP дещо інший - якщо ОП дійсно хоче ефективно використовувати DSP, можливо, десь уздовж рядка, мабуть, буде якийсь рукописний код. А насправді з проектами DSP іноді навіть потрібно почати, написавши це ядро ​​з числовим ядром, щоб перевірити, що процесор буде відповідним для задачі.
перицинтіон

11
Ваше заключне твердження - це хороша загальна порада. Але це дещо блідо, якщо враховувати конкретні деталі АЛУ AD DSP. Я не думаю, що ти їх коли-небудь оглядав.
jonk

18

Ваш DSP буде рекламований з максимально витриманими MAC, якщо припустимо, що всі труби заповнені. Це, очевидно, верхня межа того, що можна досягти. Ви знаєте, скільки МАК займуть ваші фільтри та інша обробка з вашого аналізу. Намагайтеся мати перший принаймні двічі другий, оскільки ви не зможете тримати ядро ​​DSP на максимумі. Так само, як ви б не намагалися заповнити FPGA вище 70% ресурсу (PAR стає дуже повільним над цим), розробка може отримати дуже повільну спробу витіснити останні кілька теоретичних MAC з DSP.

Ви будете кодувати всю свою заявку в C. Недоцільно писати всі додаткові, необхідні речі в асемблері, пробному впорскуванні та видимості, ведення домашнього господарства тощо. Напишіть С-версію тестового фільтра. Напишіть версію асемблера того ж фільтра, щоб переконатися, що можете насправді написати асемблер для цього звіра.

Тепер зробіть кілька таймінгів. Використовуйте RTOS, затверджений постачальником. Порівняйте час роботи модуля тестового асемблера з версією C. Якщо вони в межах кількох відсотків, рухайтеся далі. Якщо він потрійний, то прочитайте документацію, перевірте постачальника та з’ясуйте, чому компілятор не налаштовує його. Можливо, вам доведеться навчитися писати його смак на С настільки, щоб встановити правильні прапорці компілятора, швидше дізнаєтесь, як правильно керувати компілятором, ніж переписувати все в асемблері.

Ви все це зробили, перш ніж перейти до DSP, до ланцюжка інструментів.

Коли у вас є ланцюжок інструментів, з якою ви можете працювати, компілятор, який ви можете налаштувати, щоб отримати достатньо близький до максимуму, DSP з залишком деякого проміжку часу, тоді ви можете бути впевнені, що дуже мало частин вашого кодового набору потрібно буде розмістити асемблер, щоб закінчити роботу.


7

Хоча я вже відповів на це запитання, я додам ще одну відповідь, щоб проілюструвати іншу точку зору:

Пишіть на С, читайте в зборі!

Отже, замість того, щоб писати в зборі, ви запишете логіку в C, обережно переконавшись, що вихід асемблера коду С є оптимальним. Ви можете часто робити певні хитрощі на коді С, щоб вплинути на вихід асемблера. Використовуйте статичні вбудовані функції, коли це має сенс. Якщо вам потрібно скористатися деякими спеціальними інструкціями, які підтримує DSP, зробіть статичну функцію вбудованої абстракції спеціальної інструкції та зателефонуйте до спеціальної інструкції, використовуючи абстракцію.

Хоча я мушу сказати, що я ніколи не програмував DSP, цей підхід написання коду С при уважному дотриманні складеної збірки спрацював для мене надзвичайно добре на машинах x86. Так добре, насправді, що мені ніколи не доводилося нічого писати на зборах, щоб отримати найкращу можливу ефективність. Я замість оптимізації коду складання змінювати код C таким чином, щоб збірка була оптимальною.

Звичайно, це залежить від наявності хороших компіляторів С. Для x86 такі компілятори доступні (часто доводиться вказувати більш високий рівень оптимізації, ніж за замовчуванням). Що стосується DSP, я відверто не знаю, чи компілятори такі гарні.

Перевага такого підходу полягає в тому, що у вас є одна портативна база даних коду, оптимізована для отримання оптимальної збірки для даного DSP, але він працює також, якщо DSP буде змінено на щось інше. Звичайно, вам, можливо, доведеться трохи відрегулювати код C, щоб отримати найкращу ефективність нового DSP.


У мене є питання з цього приводу: я працюю над процесорами STM32F4 Cortex-M4 і використовую бібліотеки CMSIS / Cube. Я також використовую прапор компілятора -O3, тому що він виявився ефективнішим, ніж усе, що я міг створити. Проблема полягає в тому, що складена збірка завжди є занадто хаотичною для правильного аналізу. Ви завжди компілюєте без оптимізації компілятора? Або вам вдається переконатися в зборах напередодні, якщо це всюди?
Флорент

2
@FlorentEcochard: Якщо асемблер компілятора не може зрозуміти програміст, можливо, це краще, ніж асемблер, який може написати цей програміст. Як пряма відповідь на ваше запитання: використовуйте максимальну оптимізацію та ручний аналіз асемблера, складні частини можуть бути навчальними.
pasaba por aqui

4

Взагалі, не потрібно писати джерела асемблера, якщо:

  • ви оптимізуєте C у критичних розділах: добре використовувати ключове слово "зареєструватися", вбудовані функції, ...
  • можуть бути деякі функції програми C, використовуючи блоки ASM

Це означає вручну переглянути асемблер, сформований компілятором C (для критичних частин) та змінити джерело до достатнього рівня оптимізації.


Практично всі сучасні компілятори ігнорують ключове слово «зареєструватись», незалежно від платформи. Використання його дуже навряд чи призведе до кращого коду.
Кеф Шектер

@KefSchecter: вони враховують не лише підказку про регістр, але й зараз дозволяють вибрати реєстр, який буде використовуватися: gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/…
pasaba por aqui

1
@KefSchecter: крім компіляторів, написаних для вбудованих пристроїв, де це дуже важливе ключове слово, якщо ви програмуєте на голий метал.
vsz

@pasabaporaqui: Я забув про цей шматочок синтаксису. Але якщо ви не вкажете ім'я реєстру - іншими словами, якщо ви використовуєте його стандартним способом ISO - я буду вважати, що GCC його проігнорує.
Kef Schecter

3

Тут я б сказав, що якщо ви робите фільтри FIR / IIR, набагато важливіший алгоритм, який ви використовуєте (тривіальний алгоритм проти швидкого перетворення Фур'є (FFT)), ніж мову, якою ви користуєтесь (C проти збірки).

Я б писав FFT в зборі? Напевно, ні.

Чи писав би я FFT сам? Відповідь на це, мабуть, також не є, оскільки FFT вже реалізується вже багато разів. Тож є ймовірність, що ви знайдете бібліотеку, у якій FFT вже впроваджено. Враховуючи, що C - це портативна мова, тоді як збірка - ні, ви набагато більше шансів знайти існуючі бібліотеки, вже реалізовані в C.

Якщо ви бажаєте максимально екстремальної продуктивності, ви, очевидно, можете вручну настроїти алгоритм FFT, щоб якомога швидше працювати на мові збірки. Але я не вірю, що це має сенс робити, за винятком дуже виняткових обставин.


2

По моїй думці FWIW полягає в тому, що в будь-який час, коли ви хочете, щоб максимальна швидкість / ефективність / пропускна здатність / все що завгодно, асемблер є вашим другом, якщо ви досвідчений. Компілятор німий; він "знає" лише те, що його автор думав запрограмувати в нього, а його автор взагалі не знав вашої заявки.

Треба визнати, я любив асемблера з початку 80-х 8-ти бітний мікросхема (зовсім не відрізняється від сучасних MCU), де вивчення "машинного коду" було необхідною умовою для отримання будь-якої корисної продуктивності, але я думаю, що його роль залишається а на шляху до програми для досягнення максимальної ефективності. Крім того, це дуже корисно, оскільки ви можете використовувати всі види оптимізації ярликів, про які компілятор не подумає, оскільки компілятор взагалі не може думати.

Я гадаю, гаразд. Але якщо ви дійсно знаєте, що ви хочете, щоб ваша машина працювала на апаратному рівні, перейдіть на асемблер.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.