¿Escribir algoritmos DSP directamente en C o ensamblado? [cerrado]

18

Estoy trabajando en un proyecto DSP (filtrado IIR) en un procesador de señal digital de Analog Devices (BF706) con el conjunto de compiladores incluido, CrossCore Studio. Tiene algunos ejemplos para cosas DSP simples como filtros FIR y IIR y funciones de biblioteca para ello. El manual del procesador describe el conjunto de instrucciones de ensamblaje y no comenta sobre C.

MI pregunta surge de esta aplicación en particular, pero pensé que hay una mejor práctica que siguen los desarrolladores de DSP. Así que lo enmarcaré de manera general:

De lo que me he dado cuenta con los ejemplos que vienen con este DSP, es que si quiero usar los circuitos diseñados para aplicaciones DSP, necesito programar en ensamblado para ejecutar directamente esas instrucciones (como multiplicar y agregar, etc.) Mi pregunta es si Solo programo en C, ¿el compilador (que también proviene de la compañía de chips DSP) lo optimizaría para ese DSP y usaría sus capacidades? ¿O realmente necesito escribir rutinas DSP directamente en ensamblador?

dobleE
fuente
17
Pasé muchos años escribiendo ensamblaje para ADSP-21xx (y ensamblaje y C para Blackfin, más adelante). No revela lo que está utilizando, por lo que cualquier respuesta será más una suposición y una opinión que cualquier otra cosa. Pero los procesadores DSP de AD son muy buenos y es muy difícil para los escritores de compiladores de C llenar la tubería correctamente, por así decirlo. Tengo dos décadas de experiencia en esta área (incluida una experiencia muy modesta escribiendo un compilador de C) y hasta el momento en que dejé de escribir código (hace unos años) los compiladores de C no podían acercarse a la codificación manual. Pero lo que haces depende de tus objetivos.
jonk
1
@jonk espero que va a escribir una respuesta a esta pregunta - yo sólo lo hizo uno de hardcore proyecto DSP Blackfin, pero tengo buenos recuerdos de algunos de los cortes de rendimiento que necesitaba :)
pericynthion
66
@pericynthion No, no me puedo imaginar escribir una respuesta a menos que el OP hable MUCHO más sobre el DSP particular y los objetivos del proyecto. De lo contrario, serían opiniones vagas y no guiadas que podrían ser muy correctas o muy incorrectas dependiendo de lo que el OP escribió al respecto. Así que solo esperaré.
jonk
1
Si desea que se ejecute más rápido, puede optimizarlo manualmente en el ensamblaje. Esa es una compensación tiempo / dinero. Si sabes cómo escribir una buena C, puedes llegar la mayor parte del camino.
Voltaje pico
2
No estoy seguro acerca de DSP, pero para la mayoría de los microprocesadores puede usar intrínsecos, que está a medio camino entre la escritura del ensamblador y el código C.
Maciej Piechotka

Respuestas:

20

Siempre es mejor tener su algoritmo implementado en un lenguaje de nivel superior (que C se compara con el ensamblado), incluso si planea implementar todo en el ensamblaje al final.

  • lo más probable es que ni siquiera necesites ensamblarlo . Si el código generado por su compilador cumple con sus objetivos de diseño, su trabajo está hecho.

  • si no, no comenzará su codificación de ensamblaje desde cero . Deje que el compilador genere el código inicial para usted y úselo como base para su versión de ensamblaje optimizada.

  • más tarde, cuando necesite probar su código de ensamblaje optimizado , se alegrará de tener la versión C. En lugar de calcular manualmente la salida correcta para sus datos de entrada de prueba, puede alimentar esos datos de entrada a su implementación C no optimizada, luego verificar que el ensamblaje produce exactamente la misma salida después de las optimizaciones que ha realizado.

Si, después de unos años, un nuevo desarrollador tendrá que hacer modificaciones a su algoritmo y todo lo que tienen a mano es un código de ensamblaje altamente optimizado, hay una gran posibilidad de que tengan que comenzar desde cero.

Dmitry Grigoryev
fuente
23

Si los escritores del compilador se esfuerzan por optimizarlo para ese objetivo, al menos utilizarán las instrucciones / arquitectura DSP especiales. Pero para obtener el máximo rendimiento, nunca será tan bueno como el ensamblaje sintonizado a mano. Sin embargo, puede ser lo suficientemente bueno, depende de su aplicación.

Otras alternativas incluyen:

  1. Escriba la mayoría de su programa en C, y solo la parte numérica más crítica en el ensamblaje.
  2. Escriba el programa en C y use bibliotecas proporcionadas por el fabricante o por terceros; si está realizando tareas DSP comunes, como FFT, filtros FIR / IIR, etc., probablemente alguien ya haya escrito el código de máquina ajustado a mano para hacerlo, por lo que puede usar eso (puede que tenga que pagarlo) y vincularlo a su aplicación.
pericintion
fuente
Por lo general, los proveedores de DSP proporcionarán el código fuente para las funciones comunes. Si su código es "lo suficientemente bueno", puede colocarlo directamente. Si no es del todo correcto, debe modificarlo. Tuve que hacer una capa de FFT hace algunos años, para obtener una FFT real de solo frecuencia. Hay un truco que te permite hacer una FFT real de 2 N puntos como una FFT compleja de N puntos, pero luego tienes que hacer un pase final sobre la salida compleja para recuperar los datos de frecuencia real. Los dispositivos analógicos no tenían ese caso particular en su código de ejemplo.
John R. Strohm
21

La optimización prematura es la fuente de todos los males. - Donald Knuth

Cuando descubra que no obtiene suficiente rendimiento de su código, primero perfile su programa, encuentre los cuellos de botella, analice sus requisitos de rendimiento y solo luego comience a hacer optimizaciones. Escribir código de ensamblaje es el último recurso.

Mi pregunta es si solo programo en C, ¿el compilador (que también proviene de la compañía de chips DSP) lo optimizaría para ese DSP y usaría sus capacidades?

Sí, el compilador de C puede hacer una buena cantidad de optimización. Pero esto depende de la calidad del compilador. Con frecuencia, un humano puede escribir un código de ensamblaje más rápido que el código C compilado. A expensas del gran dolor y sufrimiento humano, eso es.

¿O realmente necesito escribir rutinas DSP directamente en ensamblador?

Primero escriba en C, luego en el perfil, luego decida si necesita escribir en conjunto. Con suerte, no necesitarías la asamblea.

Nick Alexeev
fuente
20
En general, la programación es un buen consejo, pero el DSP es un poco diferente: si el OP realmente quiere hacer un uso eficiente de un DSP, es probable que necesite algún código escrito a mano en algún punto de la línea. Y, de hecho, con los proyectos DSP, a veces incluso desea comenzar escribiendo ese núcleo numérico central, para validar que el procesador será adecuado para la tarea en cuestión.
pericynthion
11
Su declaración final es un buen consejo general. Pero es un poco pálido cuando se consideran los detalles específicos de las ALU de AD DSP. Supongo que nunca los has examinado.
jonk
18

Su DSP se anunciará con un MAC sostenido máximo, suponiendo que se llenen todas las canalizaciones. Eso es obviamente un límite superior a lo que se puede lograr. Usted sabe cuántos MAC tomarán sus filtros y otros procesamientos, a partir de su análisis. Procure tener el primero al menos dos veces el segundo, ya que no podrá mantener el núcleo DSP funcionando al máximo. Del mismo modo que no intentaría llenar un FPGA por encima del 70% de recursos (PAR se vuelve muy lento por encima de eso), el desarrollo podría ser muy lento tratando de exprimir los últimos MAC teóricos de un DSP.

Codificará toda su aplicación en C. No es práctico escribir todos los elementos adicionales necesarios en el ensamblador, la inyección de prueba y la visibilidad, el mantenimiento, etc. Escriba una versión en C del filtro de prueba. Escriba una versión de ensamblador del mismo filtro, para verificar que de hecho pueda escribir ensamblador para esta bestia.

Ahora haz algunos horarios. Use un RTOS aprobado por el proveedor. Compare el tiempo de ejecución de su módulo ensamblador de prueba con una versión C. Si están dentro de un pequeño porcentaje, continúe. Si es triple, lea la documentación, pregunte al proveedor y descubra por qué el compilador no lo está ajustando. Es posible que deba aprender a escribir su sabor de C tanto como establecer los indicadores correctos del compilador, será más rápido descubrir cómo conducir el compilador correctamente que reescribir todo en el ensamblador.

Has hecho todo esto antes de comprometerte con un DSP, con una cadena de herramientas.

Una vez que tenga una cadena de herramientas con la que pueda trabajar, un compilador que pueda sintonizar para acercarse razonablemente al máximo, un DSP con algo de margen de tiempo restante, entonces puede estar razonablemente seguro de que se necesitarán muy pocas partes de su conjunto de códigos ensamblador para terminar el trabajo.

Neil_UK
fuente
7

Aunque ya respondí esta pregunta, agregaré otra respuesta para ilustrar un punto de vista diferente:

¡Escriba en C, lea en asamblea!

Entonces, en lugar de escribir en ensamblaje, escribirá la lógica en C, asegurándose cuidadosamente de que la salida del ensamblador del código C sea óptima. A menudo puede hacer ciertos trucos en el código C para afectar la salida del ensamblador. Use funciones estáticas en línea cuando tenga sentido. Si necesita utilizar algunas instrucciones especiales que admite el DSP, realice una abstracción de función en línea estática de la instrucción especial y llame a la instrucción especial utilizando la abstracción.

Aunque tengo que decir que nunca he programado DSP, este enfoque de escribir el código C al observar cuidadosamente el ensamblado compilado me ha funcionado muy bien en máquinas x86. Tan bien, de hecho, que nunca he tenido que escribir nada en conjunto para obtener el mejor rendimiento posible. En lugar de optimizar el código de ensamblaje, modificaré el código C de tal manera que el ensamblaje sea óptimo.

Por supuesto, esto depende de que haya buenos compiladores de C disponibles. Para x86, tales compiladores están disponibles (a menudo debe especificar un nivel de optimización más alto que el predeterminado). Para los DSP, francamente no sé si los compiladores son tan buenos.

El beneficio de este enfoque es que tiene una única base de código portátil, optimizada para dar como resultado un ensamblaje óptimo para un DSP determinado, pero también funciona si el DSP se cambia a otra cosa. Por supuesto, es posible que tenga que ajustar ligeramente el código C para obtener el mejor rendimiento posible en el nuevo DSP.

juhist
fuente
Tengo una pregunta sobre esto: trabajo en los procesadores STM32F4 Cortex-M4 y uso las bibliotecas CMSIS / Cube. También utilizo el indicador -O3 del compilador, porque demostró ser más eficiente que cualquier cosa que pudiera producir. El problema es que el ensamblaje compilado siempre es demasiado caótico para un análisis adecuado. ¿Siempre compilas sin la optimización del compilador? ¿O logras entender la víspera de la asamblea, si está por todas partes?
Florent
2
@FlorentEcochard: si un programador no puede entender el ensamblador del compilador, probablemente sea mejor que el ensamblador que este programador puede escribir. Como respuesta directa a su pregunta: utilice la optimización máxima y el análisis manual del ensamblador, las partes difíciles podrían ser educativas.
pasaba por aqui
4

En general, no es necesario escribir fuentes de ensamblador si:

  • optimiza C en las secciones críticas: un buen uso de la palabra clave "registrarse", funciones en línea, ...
  • podrían ser algunas funciones del programa C usando bloques asm

Eso significa revisar manualmente el ensamblador generado por el compilador de C (para las partes críticas) y modificar la fuente hasta un nivel suficiente de optimización.

pasaba por aqui
fuente
Prácticamente todos los compiladores modernos ignoran la palabra clave "registrarse", independientemente de la plataforma. Usarlo es muy poco probable que resulte en un mejor código.
Kef Schecter
@KefSchecter: no solo tienen en cuenta la sugerencia de registro, hoy en día incluso permiten seleccionar el registro que se utilizará: gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/…
pasaba por aqui
1
@KefSchecter: excepto para los compiladores escritos para dispositivos integrados, donde es una palabra clave muy importante si está programando en metal desnudo.
vsz
@pasabaporaqui: Olvidé ese poco de sintaxis. Pero si no especifica un nombre de registro, en otras palabras, si lo usa de la manera estándar ISO, apuesto a que GCC lo ignorará.
Kef Schecter
3

Diría aquí que si usa filtros FIR / IIR, es mucho más importante qué algoritmo usa (el algoritmo trivial versus la transformación rápida de Fourier (FFT)) que el lenguaje que usa (C versus ensamblaje).

¿Escribiría FFT en ensamblaje? Probablemente no.

¿Escribiría FFT yo mismo? La respuesta a esto tampoco es probable, ya que FFT ya se ha implementado muchas veces. Entonces, es probable que encuentre alguna biblioteca que ya tenga implementada FFT. Teniendo en cuenta que C es un lenguaje portátil mientras que el ensamblado no lo es, será mucho más probable que encuentre bibliotecas existentes ya implementadas en C.

Si desea el rendimiento más extremo posible, obviamente puede ajustar manualmente un algoritmo FFT para que funcione lo más rápido posible en lenguaje ensamblador. Pero realmente no creo que tenga sentido hacer eso, excepto en circunstancias muy excepcionales.

juhist
fuente
2

Mi propio punto de vista FWIW es que cada vez que desee la máxima velocidad / eficiencia / rendimiento / lo que sea, el ensamblador es su amigo, siempre que sea competente. Un compilador es tonto; "sabe" solo lo que su autor pensó programar en él, y su autor no conocía su aplicación en absoluto.

Debo admitir que me ha encantado el ensamblador desde principios de los 80, micros de 8 bits (no muy diferente de los MCU modernos en muchos aspectos) donde aprender "código de máquina" era un requisito previo para obtener un rendimiento útil de ellos, pero creo que su papel sigue siendo como la forma de programar para obtener la máxima eficiencia. Además, es muy gratificante, ya que puede incluir todo tipo de atajos de optimización que un compilador no pensará, porque un compilador no puede pensar en absoluto.

C está bien, supongo. Pero si realmente sabe lo que quiere que haga su máquina a nivel de hardware, vaya al ensamblador.

Ian Bland
fuente