Я работаю над проектом DSP (фильтрация IIR) на цифровом сигнальном процессоре Analog Devices (BF706) с пакетом компиляторов, CrossCore Studio. У него есть несколько примеров для простых DSP, таких как фильтры FIR и IIR и библиотечные функции для него. Руководство по процессору описывает набор инструкций по сборке и не комментирует C.
Мой вопрос возникает из этого конкретного приложения, но я подумал, что есть лучшая практика, которой следуют разработчики DSP. Поэтому я сформулирую это в общем виде:
Что я понял из примеров, поставляемых с этим DSP, так это то, что если я хочу использовать схемы, предназначенные для приложений DSP, мне нужно программировать на ассемблере для непосредственного выполнения этих инструкций (например, умножение, сложение и т. Д.). Мой вопрос: Я просто программирую на C, не оптимизирует ли компилятор (который также поставляется компанией-производителем DSP) его для этого DSP и использует его возможности? Или мне действительно нужно писать подпрограммы DSP непосредственно в сборке?
источник
Ответы:
Всегда лучше, чтобы ваш алгоритм был реализован на языке более высокого уровня (который C сравнивается со сборкой), даже если вы планируете реализовать все в сборке в конце.
Скорее всего, вам даже не понадобится сборка . Если код, сгенерированный вашим компилятором, соответствует вашим целям проектирования, ваша работа выполнена.
в противном случае вы не начнете сборку кода с нуля . Позвольте компилятору сгенерировать исходный код для вас и использовать его в качестве основы для вашей оптимизированной версии сборки.
позже, когда вам нужно будет протестировать ваш оптимизированный код сборки , вы будете рады иметь C-версию. Вместо того, чтобы вручную вычислять правильный вывод для ваших тестовых входных данных, вы можете просто передать эти входные данные в неоптимизированную реализацию C, а затем проверить, что сборка выдает точно такой же результат после проведенных вами оптимизаций.
Если через несколько лет новому разработчику потребуется внести изменения в ваш алгоритм, и все, что у него есть, это высоко оптимизированный код сборки, есть большая вероятность, что ему придется начинать с нуля.
источник
Если авторы компилятора приложат некоторые усилия для его оптимизации для этой цели, он, по крайней мере, будет использовать специальные инструкции / архитектуру DSP. Но для максимальной производительности он никогда не будет так хорош, как сборка с ручной настройкой. Это может быть достаточно хорошо, хотя - зависит от вашего приложения.
Другие альтернативы включают в себя:
источник
Преждевременная оптимизация - корень всего зла. - Дональд Кнут
Когда вы обнаружите, что не получаете достаточной производительности от своего кода, сначала профилируйте свою программу, найдите узкие места, проанализируйте требования к производительности и только потом начинайте выполнять оптимизацию. Написание ассемблера является последним средством.
Да, компилятор C может сделать довольно много оптимизации. Но это зависит от качества компилятора. Часто человек может написать более быстрый ассемблерный код, чем скомпилированный C-код. За счет человеческой боли и страданий.
Сначала напишите на C, затем в профиле, а затем решите, нужно ли писать в сборке. Надеюсь, вам не понадобится сборка.
источник
Ваш DSP будет объявлен с максимально устойчивыми MAC, при условии, что все каналы заполнены. Это, очевидно, верхний предел того, что может быть достигнуто. Вы знаете, сколько MAC-адресов ваши фильтры и другая обработка будут принимать из вашего анализа. Старайтесь, чтобы первое было как минимум дважды второе, так как вы не сможете поддерживать работу ядра DSP на максимуме. Точно так же, как вы не пытались бы заполнить FPGA ресурсом выше 70% (PAR становится очень медленным выше этого уровня), разработка может быть очень медленной, пытаясь выжать последние несколько теоретических MAC из DSP.
Вы закодируете все свое приложение на языке C. Нецелесообразно писать все дополнительные, необходимые вещи на ассемблере, тестовые инъекции и видимость, ведение домашнего хозяйства и т. Д. Написать C-версию тестового фильтра. Напишите версию ассемблера того же фильтра, чтобы убедиться, что вы действительно можете написать ассемблер для этого зверя.
Теперь сделайте несколько таймингов. Используйте ОСРВ, утвержденную поставщиком. Сравните время выполнения вашего тестового ассемблера с версией C. Если они в пределах нескольких процентов, двигайтесь дальше. Если он тройной, прочтите документацию, опросите поставщика и выясните, почему компилятор его не настраивает. Возможно, вам придется научиться писать его разновидность C столько же, сколько устанавливать правильные флаги компилятора, быстрее узнать, как правильно управлять компилятором, чем переписывать все на ассемблере.
Вы сделали все это, прежде чем переходить к DSP, к цепочке инструментов.
Если у вас есть набор инструментов, с которым вы можете работать, компилятор, который вы можете настроить, чтобы получить разумно близкий к максимуму, DSP с некоторым запасом времени, то вы можете быть достаточно уверены, что очень мало частей вашего набора кода нужно будет поместить в ассемблер, чтобы закончить работу.
источник
Хотя я уже ответил на этот вопрос, я добавлю еще один ответ, чтобы проиллюстрировать другую точку зрения:
Пишите в C, читайте в сборке!
Таким образом, вместо написания на ассемблере, вы будете писать логику на C, тщательно следя за тем, чтобы вывод C-кода на ассемблере был оптимальным. Вы можете часто делать определенные трюки с кодом C, чтобы повлиять на вывод ассемблера. Используйте статические встроенные функции, когда это имеет смысл. Если вам нужно использовать некоторые специальные инструкции, которые поддерживает DSP, создайте статическую встроенную функцию абстракции специальной инструкции и вызовите специальную инструкцию, используя абстракцию.
Хотя я должен сказать, что никогда не программировал DSP, этот подход написания кода на C при тщательном наблюдении за скомпилированной сборкой очень хорошо работал на машинах с архитектурой x86. На самом деле настолько хорошо, что мне никогда не приходилось писать что-либо в сборке, чтобы добиться наилучшей производительности. Вместо оптимизации кода сборки я буду изменять код C таким образом, чтобы сборка была оптимальной.
Конечно, это зависит от наличия хороших компиляторов Си. Для x86 такие компиляторы доступны (вам часто приходится указывать более высокий уровень оптимизации, чем по умолчанию). Для DSP, честно говоря, я не знаю, насколько хороши компиляторы.
Преимущество этого подхода заключается в том, что у вас есть единая переносимая кодовая база, оптимизированная для обеспечения оптимальной сборки для данного DSP, но она работает также в том случае, если DSP изменяется на что-то другое. Конечно, вам, возможно, придется немного откорректировать код C, чтобы получить максимально возможную производительность на новом DSP.
источник
В общем случае нет необходимости писать ассемблерные исходники, если:
Это означает, что нужно вручную просмотреть ассемблер, сгенерированный компилятором C (для критических частей), и изменить исходный код до достаточного уровня оптимизации.
источник
Здесь я бы сказал, что если вы применяете FIR / IIR-фильтры, гораздо важнее, какой алгоритм вы используете (тривиальный алгоритм по сравнению с быстрым преобразованием Фурье (FFT)), чем какой язык вы используете (C по сравнению со сборкой).
Буду ли я писать FFT в сборке? Возможно нет.
Буду ли я писать FFT сам? Ответ на это также, вероятно, нет, так как FFT уже был реализован много раз. Так что, скорее всего, вы найдете библиотеку, в которой уже реализовано FFT. Учитывая, что C является переносимым языком, а ассемблер - нет, у вас будет гораздо больше шансов найти существующие библиотеки, уже реализованные в C.
Если вы хотите максимально возможную производительность, вы, очевидно, могли бы вручную настроить алгоритм FFT, чтобы он работал как можно быстрее на ассемблере. Но я не очень верю, что имеет смысл делать это, за исключением очень исключительных обстоятельств.
источник
На мой взгляд, FWIW заключается в том, что в любое время, когда вам нужна максимальная скорость / эффективность / пропускная способность / что угодно, ассемблер - ваш друг, если вы опытный. Компилятор тупой; он «знает» только то, что его автор подумал запрограммировать в него, а его автор вообще не знал вашего приложения.
Должен признаться, я любил ассемблер с начала 80-х годов 8-битные микросхемы (во многом не отличающиеся от современных микроконтроллеров), где изучение «машинного кода» было необходимым условием для получения любой полезной производительности из них, но я думаю, что его роль остается а на пути к программе для достижения максимальной эффективности. Кроме того, это очень полезно, так как вы можете добавить все виды оптимизирующих ярлыков, о которых не задумывается компилятор, потому что компилятор вообще не может думать.
С хорошо, я думаю. Но если вы действительно знаете, что вы хотите, чтобы ваша машина делала на аппаратном уровне, иди на ассемблер.
источник