Написание алгоритмов DSP непосредственно в C или сборке? [закрыто]


18

Я работаю над проектом DSP (фильтрация IIR) на цифровом сигнальном процессоре Analog Devices (BF706) с пакетом компиляторов, CrossCore Studio. У него есть несколько примеров для простых DSP, таких как фильтры FIR и IIR и библиотечные функции для него. Руководство по процессору описывает набор инструкций по сборке и не комментирует C.

Мой вопрос возникает из этого конкретного приложения, но я подумал, что есть лучшая практика, которой следуют разработчики DSP. Поэтому я сформулирую это в общем виде:

Что я понял из примеров, поставляемых с этим DSP, так это то, что если я хочу использовать схемы, предназначенные для приложений DSP, мне нужно программировать на ассемблере для непосредственного выполнения этих инструкций (например, умножение, сложение и т. Д.). Мой вопрос: Я просто программирую на C, не оптимизирует ли компилятор (который также поставляется компанией-производителем DSP) его для этого DSP и использует его возможности? Или мне действительно нужно писать подпрограммы DSP непосредственно в сборке?


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

1
@jonk надеюсь, что вы собираетесь написать ответ на этот вопрос - я когда-либо делал только один хардкорный проект DSP Blackfin, но у меня остались приятные воспоминания о некоторых
хаках

6
@pericynthion Нет, я не могу представить, как на него ответить, если ОП не расскажет много о конкретном DSP и целях проекта. В противном случае это были бы расплывчатые, неконтролируемые мнения, которые могли бы быть очень правильными или очень неправильными, в зависимости от того, что ФП написал об этом. Так что я просто подожду.
17

1
Если вы хотите, чтобы он работал быстрее, вы можете оптимизировать его при сборке. Это компромисс между временем и деньгами. Если вы знаете, как писать хороший C, вы можете пройти большую часть пути туда.
напряжения

2
Я не уверен насчет DSP, но для большинства микропроцессоров вы можете использовать встроенные функции, которые находятся на полпути между написанием ассемблера и Си-кода.
Мацей Пехотка

Ответы:


20

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

  • Скорее всего, вам даже не понадобится сборка . Если код, сгенерированный вашим компилятором, соответствует вашим целям проектирования, ваша работа выполнена.

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

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

Если через несколько лет новому разработчику потребуется внести изменения в ваш алгоритм, и все, что у него есть, это высоко оптимизированный код сборки, есть большая вероятность, что ему придется начинать с нуля.


23

Если авторы компилятора приложат некоторые усилия для его оптимизации для этой цели, он, по крайней мере, будет использовать специальные инструкции / архитектуру DSP. Но для максимальной производительности он никогда не будет так хорош, как сборка с ручной настройкой. Это может быть достаточно хорошо, хотя - зависит от вашего приложения.

Другие альтернативы включают в себя:

  1. Напишите большую часть вашей программы на C и просто самую важную числовую часть в сборке.
  2. Напишите программу на C и используйте библиотеки, предоставленные производителем или третьими лицами - если вы выполняете обычные задачи DSP, такие как FFT, фильтры FIR / IIR и т. Д., Кто-то, вероятно, уже написал для этого вручную настроенный машинный код, так что вы можете использовать это (возможно, вам придется заплатить за это) и связать его с вашим приложением.

Обычно поставщики DSP предоставляют исходный код для общих функций. Если их код «достаточно хорош», вы можете сразу его вставить. Если он не совсем верный, вы должны настроить его. Несколько лет назад мне пришлось сделать слой БПФ, чтобы получить реальное БПФ только по частоте. Есть трюк, который позволяет вам сделать 2-точечное реальное БПФ как N-точечное комплексное БПФ, но затем вам нужно сделать последний проход по сложному выходу, чтобы восстановить реальные частотные данные. Аналоговые устройства не имели этого конкретного случая в своем примере кода.
Джон Р. Штром,

21

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

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

Мой вопрос: если бы я просто программировал на C, не оптимизировал ли бы его компилятор (который также поставляется компанией-производителем микросхем DSP) для этого DSP и использовал бы его возможности?

Да, компилятор C может сделать довольно много оптимизации. Но это зависит от качества компилятора. Часто человек может написать более быстрый ассемблерный код, чем скомпилированный C-код. За счет человеческой боли и страданий.

Или мне действительно нужно писать подпрограммы DSP непосредственно в сборке?

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


20
В общем программировании это, конечно, хороший совет, но DSP немного отличается - если OP действительно хочет эффективно использовать DSP, возможно, потребуется где-то рукописный код. И на самом деле, с проектами DSP иногда даже хочется начать с написания этого ядра с числовым ядром, чтобы убедиться, что процессор подходит для поставленной задачи.
перицинтион

11
Ваше заключительное заявление - хороший общий совет. Но это довольно бледно, когда рассматриваются конкретные детали ALU AD DSP. Я не думаю, что вы когда-либо изучали их.
17

18

Ваш DSP будет объявлен с максимально устойчивыми MAC, при условии, что все каналы заполнены. Это, очевидно, верхний предел того, что может быть достигнуто. Вы знаете, сколько MAC-адресов ваши фильтры и другая обработка будут принимать из вашего анализа. Старайтесь, чтобы первое было как минимум дважды второе, так как вы не сможете поддерживать работу ядра DSP на максимуме. Точно так же, как вы не пытались бы заполнить FPGA ресурсом выше 70% (PAR становится очень медленным выше этого уровня), разработка может быть очень медленной, пытаясь выжать последние несколько теоретических MAC из DSP.

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

Теперь сделайте несколько таймингов. Используйте ОСРВ, утвержденную поставщиком. Сравните время выполнения вашего тестового ассемблера с версией C. Если они в пределах нескольких процентов, двигайтесь дальше. Если он тройной, прочтите документацию, опросите поставщика и выясните, почему компилятор его не настраивает. Возможно, вам придется научиться писать его разновидность C столько же, сколько устанавливать правильные флаги компилятора, быстрее узнать, как правильно управлять компилятором, чем переписывать все на ассемблере.

Вы сделали все это, прежде чем переходить к DSP, к цепочке инструментов.

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


7

Хотя я уже ответил на этот вопрос, я добавлю еще один ответ, чтобы проиллюстрировать другую точку зрения:

Пишите в C, читайте в сборке!

Таким образом, вместо написания на ассемблере, вы будете писать логику на C, тщательно следя за тем, чтобы вывод C-кода на ассемблере был оптимальным. Вы можете часто делать определенные трюки с кодом C, чтобы повлиять на вывод ассемблера. Используйте статические встроенные функции, когда это имеет смысл. Если вам нужно использовать некоторые специальные инструкции, которые поддерживает DSP, создайте статическую встроенную функцию абстракции специальной инструкции и вызовите специальную инструкцию, используя абстракцию.

Хотя я должен сказать, что никогда не программировал DSP, этот подход написания кода на C при тщательном наблюдении за скомпилированной сборкой очень хорошо работал на машинах с архитектурой x86. На самом деле настолько хорошо, что мне никогда не приходилось писать что-либо в сборке, чтобы добиться наилучшей производительности. Вместо оптимизации кода сборки я буду изменять код C таким образом, чтобы сборка была оптимальной.

Конечно, это зависит от наличия хороших компиляторов Си. Для x86 такие компиляторы доступны (вам часто приходится указывать более высокий уровень оптимизации, чем по умолчанию). Для DSP, честно говоря, я не знаю, насколько хороши компиляторы.

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


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

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

4

В общем случае нет необходимости писать ассемблерные исходники, если:

  • вы оптимизируете C в критических разделах: хорошее использование ключевого слова "register", встроенные функции, ...
  • могут быть некоторые функции программы на C, использующие блоки asm

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


Практически все современные компиляторы игнорируют ключевое слово «register» независимо от платформы. Его использование вряд ли приведет к лучшему коду.
Кеф Шектер

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

1
@KefSchecter: за исключением компиляторов, написанных для встроенных устройств, где это очень важное ключевое слово, если вы программируете на голом железе.
17

@pasabaporaqui: я забыл об этом синтаксисе. Но если вы не укажете имя регистра - другими словами, если вы будете использовать его стандартным способом ISO - я уверен, что GCC проигнорирует его.
Кеф Шектер

3

Здесь я бы сказал, что если вы применяете FIR / IIR-фильтры, гораздо важнее, какой алгоритм вы используете (тривиальный алгоритм по сравнению с быстрым преобразованием Фурье (FFT)), чем какой язык вы используете (C по сравнению со сборкой).

Буду ли я писать FFT в сборке? Возможно нет.

Буду ли я писать FFT сам? Ответ на это также, вероятно, нет, так как FFT уже был реализован много раз. Так что, скорее всего, вы найдете библиотеку, в которой уже реализовано FFT. Учитывая, что C является переносимым языком, а ассемблер - нет, у вас будет гораздо больше шансов найти существующие библиотеки, уже реализованные в C.

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


2

На мой взгляд, FWIW заключается в том, что в любое время, когда вам нужна максимальная скорость / эффективность / пропускная способность / что угодно, ассемблер - ваш друг, если вы опытный. Компилятор тупой; он «знает» только то, что его автор подумал запрограммировать в него, а его автор вообще не знал вашего приложения.

Должен признаться, я любил ассемблер с начала 80-х годов 8-битные микросхемы (во многом не отличающиеся от современных микроконтроллеров), где изучение «машинного кода» было необходимым условием для получения любой полезной производительности из них, но я думаю, что его роль остается а на пути к программе для достижения максимальной эффективности. Кроме того, это очень полезно, так как вы можете добавить все виды оптимизирующих ярлыков, о которых не задумывается компилятор, потому что компилятор вообще не может думать.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.