Estou trabalhando em um projeto DSP (filtragem IIR) em um processador de sinal digital da Analog Devices (BF706) com o conjunto de compiladores que vem com ele, o CrossCore Studio. Ele contém alguns exemplos de itens DSP simples, como filtros FIR e IIR e funções de biblioteca. O manual do processador descreve o conjunto de instruções de montagem e não comenta sobre C.
Minha pergunta surge dessa aplicação específica, mas achei que havia uma prática recomendada que os desenvolvedores do DSP seguem. Então, eu vou enquadrar de uma maneira geral:
O que percebi pelos exemplos que acompanham este DSP é que, se eu quiser usar os circuitos projetados para aplicativos DSP, preciso programar em montagem para executar diretamente essas instruções (como multiplicar e adicionar, etc.). Eu apenas programa em C, o compilador (que também vem da empresa de chips DSP) não o otimizaria para esse DSP e usaria seus recursos? Ou eu realmente preciso escrever rotinas DSP diretamente na montagem?
fonte
Respostas:
É sempre melhor ter seu algoritmo implementado em uma linguagem de nível superior (que C é comparado ao assembly), mesmo que você planeje implementar tudo no assembly no final.
é provável que você nem precise de montagem . Se o código gerado pelo seu compilador atender aos seus objetivos de design, seu trabalho estará concluído.
caso contrário, você não iniciará a codificação da montagem do zero . Deixe o compilador gerar o código inicial para você e use-o como base para sua versão de montagem otimizada.
mais tarde, quando você precisar testar seu código de montagem otimizado , ficará feliz em ter a versão C. Em vez de calcular manualmente a saída correta para os dados de entrada de teste, você pode apenas alimentar esses dados com a implementação C não otimizada e verificar se a montagem produz exatamente a mesma saída após as otimizações que você fez.
Se, após alguns anos, um novo desenvolvedor precisar fazer modificações no seu algoritmo e tudo o que eles tiverem em mãos for um código de montagem altamente otimizado, há uma grande chance de que eles tenham que começar do zero.
fonte
Se os escritores do compilador se esforçarem para otimizá-lo para esse destino, ele fará pelo menos algum uso das instruções / arquitetura especiais do DSP. Mas, para obter o melhor desempenho, nunca será tão bom quanto a montagem ajustada à mão. Porém, pode ser bom o suficiente - depende da sua aplicação.
Outras alternativas incluem:
fonte
Otimização prematura é a raiz de todo o mal. - Donald Knuth
Quando você achar que não obtém desempenho suficiente do seu código, analise primeiro o seu programa, encontre os gargalos, analise seus requisitos de desempenho e só então comece a fazer otimizações. Escrever código de montagem é o último recurso.
Sim, o compilador C pode fazer uma boa quantidade de otimização. Mas isso depende da qualidade do compilador. Freqüentemente, um humano pode escrever um código de montagem mais rápido que o código C compilado. Com grande despesa de dor e sofrimento humano, isso é.
Primeiro escreva em C, depois perfil e, em seguida, decida se você precisa escrever na montagem. Felizmente, você não precisaria da montagem.
fonte
Seu DSP será anunciado com um máximo de MACs sustentados, assumindo que todos os pipes estejam preenchidos. Obviamente, esse é um limite superior ao que pode ser alcançado. Você sabe quantos MACs seus filtros e outros processamentos levarão da sua análise. Procure ter o primeiro pelo menos duas vezes o segundo, pois você não conseguirá manter o núcleo do DSP no máximo. Assim como você não tentaria preencher um FPGA acima de 70% do recurso (o PAR fica muito lento acima disso), o desenvolvimento pode ficar muito lento tentando extrair os últimos MACs teóricos de um DSP.
Você codificará todo o seu aplicativo em C. É impraticável escrever todo o material extra necessário em montador, injeção e visibilidade de teste, limpeza, etc. Escreva uma versão em C do filtro de teste. Escreva uma versão assembler do mesmo filtro, para verificar se você realmente pode escrever assembler para este animal.
Agora faça alguns intervalos. Use um RTOS aprovado pelo fornecedor. Compare o tempo de execução do seu módulo assembler de teste com uma versão C. Se eles estiverem dentro de alguns por cento, siga em frente. Se for triplo, leia a documentação, teste o fornecedor e descubra por que o compilador não o está ajustando. Pode ser necessário aprender a escrever seu sabor C, tanto quanto definir os sinalizadores corretos do compilador, será mais rápido descobrir como dirigir o compilador corretamente do que reescrever tudo no assembler.
Você já fez tudo isso antes de se comprometer com um DSP, com uma cadeia de ferramentas.
Depois de ter uma cadeia de ferramentas com a qual você pode trabalhar, um compilador com o qual você pode ajustar para ficar razoavelmente próximo do máximo, um DSP com algum espaço de tempo restante, então você pode estar razoavelmente confiante de que poucas partes do seu conjunto de códigos precisarão ser inseridas montador para concluir o trabalho.
fonte
Mesmo que eu já tenha respondido a essa pergunta, adicionarei outra resposta para ilustrar um ponto de vista diferente:
Escreva em C, leia na montagem!
Portanto, em vez de escrever em assembly, você escreverá a lógica em C, certificando-se cuidadosamente de que a saída do código C do assembler seja ótima. Muitas vezes, você pode executar certos truques no código C para afetar a saída do assembler. Use funções embutidas estáticas quando isso fizer sentido. Se você precisar usar algumas instruções especiais suportadas pelo DSP, faça uma abstração estática da função em linha da instrução especial e chame a instrução especial usando a abstração.
Embora eu deva dizer que nunca programei DSPs, essa abordagem de escrever o código C enquanto observa cuidadosamente o assembly compilado funcionou extremamente bem para mim em máquinas x86. Tão bem, na verdade, que nunca precisei escrever nada em montagem para obter o melhor desempenho possível. Em vez de otimizar o código de montagem, modificarei o código C de maneira que a montagem seja ótima.
Obviamente, isso depende da disponibilidade de bons compiladores C. Para x86, esses compiladores estão disponíveis (você geralmente precisa especificar um nível de otimização mais alto que o padrão). Para os DSPs, sinceramente não sei se os compiladores são tão bons.
O benefício dessa abordagem é que você tem uma única base de código portátil, otimizada para resultar em uma montagem ideal para um determinado DSP, mas funciona também se o DSP for alterado para outra coisa. É claro que você pode precisar ajustar levemente o código C para obter o melhor desempenho possível no novo DSP.
fonte
Em geral, não é necessário escrever fontes do assembler se:
Isso significa revisar manualmente o assembler gerado pelo compilador C (para as partes críticas) e modificar a fonte até um nível suficiente de otimização.
fonte
Eu diria aqui que, se você faz filtros FIR / IIR, é muito mais importante qual algoritmo você usa (o algoritmo trivial versus a transformada rápida de Fourier (FFT)) do que qual idioma você usa (C versus assembly).
Eu escreveria FFT na montagem? Provavelmente não.
Eu mesmo escreveria FFT? A resposta para isso também provavelmente não é, pois a FFT já foi implementada muitas vezes. Então é provável que você encontre alguma biblioteca que já tenha a FFT implementada. Considerando que C é uma linguagem portátil, enquanto o assembly não é, é muito mais provável que você encontre bibliotecas existentes já implementadas em C.
Se você deseja o desempenho mais extremo possível, obviamente pode ajustar manualmente um algoritmo FFT para funcionar o mais rápido possível na linguagem assembly. Mas realmente não acredito que faça sentido, exceto em circunstâncias muito excepcionais.
fonte
Na minha opinião, o FWIW é que sempre que você deseja velocidade / eficiência / taxa de transferência máximas, o montador é seu amigo, desde que você seja proficiente. Um compilador é burro; ele "sabe" apenas o que o autor pensou programar nele e o autor não conhecia sua aplicação.
Devo admitir que adoro assembler desde o início dos anos 80 micros de 8 bits (não muito diferentes dos MCUs modernos em muitos aspectos) em que aprender "código de máquina" era um pré-requisito para obter qualquer desempenho útil deles, mas acho que seu papel permanece como a maneira de programar para obter a máxima eficiência. Além disso, é altamente gratificante, pois você pode usar todos os tipos de atalhos de otimização que um compilador não pensa, porque um compilador não consegue pensar.
C está bem, eu acho. Mas se você realmente sabe o que deseja que sua máquina faça no nível do hardware, vá em assembler.
fonte