Je travaille sur un projet DSP (filtrage IIR) sur un processeur de signal numérique Analog Devices (BF706) avec la suite de compilateurs qui l'accompagne, CrossCore Studio. Il a quelques exemples de trucs DSP simples comme les filtres FIR et IIR et les fonctions de bibliothèque pour cela. Le manuel du processeur décrit le jeu d'instructions d'assemblage et ne commente pas C.
Ma question découle de cette application particulière, mais je pensais que les développeurs DSP suivaient une bonne pratique. Je vais donc l'encadrer de manière générale:
Ce que j'ai réalisé avec les exemples fournis avec ce DSP, c'est que si je veux utiliser les circuits conçus pour les applications DSP, je dois programmer en assembleur pour exécuter directement ces instructions (comme multiplier et ajouter, etc.) Ma question est de savoir si Je viens de programmer en C, le compilateur (qui vient également de la société de puces DSP) ne l'optimiserait-il pas pour ce DSP et n'utiliserait-il pas ses capacités? Ou dois-je vraiment écrire des routines DSP directement dans l'assemblage?
la source
Réponses:
Il est toujours préférable d'avoir votre algorithme implémenté dans un langage de niveau supérieur (que C est comparé à l'assembly), même si vous prévoyez de tout implémenter dans l'assembly à la fin.
les chances sont, vous n'aurez même pas besoin d'assemblage . Si le code généré par votre compilateur atteint vos objectifs de conception, votre travail est terminé.
sinon, vous ne commencerez pas votre codage d'assemblage à partir de zéro . Laissez le compilateur générer le code initial pour vous et utilisez-le comme base pour votre version d'assembly optimisée.
plus tard, lorsque vous aurez besoin de tester votre code d'assemblage optimisé , vous serez heureux d'avoir la version C. Au lieu de calculer manuellement la sortie correcte pour vos données d'entrée de test, vous pouvez simplement alimenter ces données d'entrée vers votre implémentation C non optimisée, puis vérifier que l'assembly produit exactement la même sortie après les optimisations que vous avez faites.
Si, après quelques années, un nouveau développeur doit apporter des modifications à votre algorithme et qu'il ne dispose que d'un code d'assemblage hautement optimisé, il y a de fortes chances qu'il devra recommencer à zéro.
la source
Si les rédacteurs du compilateur s'efforcent de l'optimiser pour cette cible, ils utiliseront au moins une partie des instructions / architecture DSP spéciales. Mais pour des performances ultimes, il ne sera jamais aussi bon qu'un assemblage réglé à la main. Cela peut être suffisant, mais cela dépend de votre application.
D'autres alternatives incluent:
la source
L'optimisation prématurée est la racine de tout Mal. - Donald Knuth
Lorsque vous constatez que vous n'obtenez pas suffisamment de performances de votre code, profilez d'abord votre programme, trouvez les goulots d'étranglement, analysez vos exigences de performances, puis commencez à faire des optimisations. L'écriture du code d'assemblage est le dernier recours.
Oui, le compilateur C peut faire une bonne quantité d'optimisation. Mais cela dépend de la qualité du compilateur. Souvent, un humain peut écrire du code d'assemblage plus rapide que le code C compilé. Au détriment de la douleur et de la souffrance humaines, bien sûr.
Écrivez d'abord en C, puis le profil, puis décidez si vous devez écrire dans l'assemblage. J'espère que vous n'auriez pas besoin de l'assemblage.
la source
Votre DSP sera annoncé avec un maximum de MAC soutenus, en supposant que tous les canaux sont remplis. C'est évidemment une limite supérieure à ce qui peut être réalisé. Vous savez combien de MAC vos filtres et autres traitements prendront, d'après votre analyse. Essayez d'avoir le premier au moins deux fois le second, car vous ne pourrez pas faire fonctionner le noyau DSP au maximum. Tout comme vous n'essaieriez pas de remplir un FPGA au-dessus de 70% des ressources (le PAR devient très lent au-dessus de cela), le développement pourrait devenir très lent en essayant d'extraire les derniers MAC théoriques d'un DSP.
Vous coderez l'intégralité de votre application en C. Il n'est pas pratique d'écrire tous les éléments supplémentaires nécessaires dans l'assembleur, l'injection de test et la visibilité, le nettoyage, etc. Écrivez une version C du filtre de test. Écrivez une version assembleur du même filtre, pour vérifier que vous pouvez bien écrire un assembleur pour cette bête.
Maintenant, faites quelques synchronisations. Utilisez un RTOS approuvé par le fournisseur. Comparez le temps d'exécution de votre module assembleur de test à une version C. S'ils sont à quelques pour cent, passez à autre chose. Si c'est triple, lisez la documentation, interrogez le fournisseur et découvrez pourquoi le compilateur ne le règle pas. Vous devrez peut-être apprendre à écrire sa saveur de C autant qu'à définir les bons drapeaux du compilateur, il sera plus rapide de savoir comment piloter le compilateur correctement que de tout réécrire dans l'assembleur.
Vous avez fait tout cela avant de vous engager dans un DSP, dans une chaîne d'outils.
Une fois que vous avez une chaîne d'outils avec laquelle vous pouvez travailler, un compilateur que vous pouvez régler pour vous rapprocher raisonnablement du maximum, un DSP avec un peu de marge de manœuvre, alors vous pouvez être raisonnablement sûr que très peu de parties de votre suite de code devront être insérées dans assembleur pour terminer le travail.
la source
Même si j'ai déjà répondu à cette question, j'ajouterai une autre réponse pour illustrer un point de vue différent:
Ecrivez en C, lisez en assemblée!
Ainsi, au lieu d'écrire en assembleur, vous écrirez la logique en C, en vous assurant soigneusement que la sortie de l'assembleur du code C est optimale. Vous pouvez souvent effectuer certaines astuces sur le code C pour affecter la sortie de l'assembleur. Utilisez des fonctions statiques en ligne lorsque cela est logique. Si vous devez utiliser certaines instructions spéciales prises en charge par le DSP, effectuez une abstraction statique de la fonction en ligne de l'instruction spéciale et appelez l'instruction spéciale à l'aide de l'abstraction.
Bien que je doive dire que je n'ai jamais programmé de DSP, cette approche d'écriture du code C tout en observant attentivement l'assemblage compilé a extrêmement bien fonctionné pour moi sur les machines x86. Tellement bien, en fait, que je n'ai jamais eu à écrire quoi que ce soit en assembleur pour obtenir les meilleures performances possibles. Je vais au lieu d'optimiser le code assembleur modifier le code C de telle manière que l'assemblage soit optimal.
Bien sûr, cela dépend de la disponibilité de bons compilateurs C. Pour x86, de tels compilateurs sont disponibles (vous devez souvent spécifier un niveau d'optimisation supérieur à celui par défaut). Pour les DSP, je ne sais franchement pas si les compilateurs sont aussi bons.
L'avantage de cette approche est que vous disposez d'une base de code portable unique, optimisée pour aboutir à un assemblage optimal pour un DSP donné, mais cela fonctionne également si le DSP est changé pour quelque chose d'autre. Bien sûr, vous devrez peut-être ajuster légèrement le code C pour obtenir les meilleures performances possibles sur le nouveau DSP.
la source
En général, il n'est pas nécessaire d'écrire des sources assembleur si:
Cela signifie revoir manuellement l'assembleur généré par le compilateur C (pour les parties critiques) et modifier la source jusqu'à un niveau d'optimisation suffisant.
la source
Je dirais ici que si vous faites des filtres FIR / IIR, il est beaucoup plus important quel algorithme vous utilisez (l'algorithme trivial contre la transformée de Fourier rapide (FFT)) que le langage que vous utilisez (C contre l'assemblage).
Dois-je écrire la FFT dans l'assemblage? Probablement pas.
Est-ce que j'écrirais moi-même la FFT? La réponse à cela n'est probablement pas non plus, car la FFT a déjà été implémentée à plusieurs reprises. Il y a donc de fortes chances que vous trouviez une bibliothèque qui a déjà implémenté FFT. Étant donné que C est un langage portable alors que l'assembly ne l'est pas, vous serez beaucoup plus susceptible de trouver des bibliothèques existantes déjà implémentées en C.
Si vous voulez les performances les plus extrêmes possibles, vous pouvez évidemment régler manuellement un algorithme FFT pour qu'il fonctionne le plus rapidement possible en langage assembleur. Mais je ne crois pas vraiment que cela ait du sens, sauf dans des circonstances très exceptionnelles.
la source
Mon propre point de vue FWIW est que chaque fois que vous voulez une vitesse / efficacité / débit / quoi que ce soit maximum, l'assembleur est votre ami, tant que vous êtes compétent. Un compilateur est stupide; il "sait" seulement ce que son auteur pensait y programmer, et son auteur ne connaissait pas du tout votre application.
Je dois admettre que j'aime l'assembleur depuis le début des années 80, les micros 8 bits (pas du tout différents des MCU modernes à bien des égards) où l'apprentissage du "code machine" était une condition préalable pour en tirer des performances utiles, mais je pense que son rôle reste comme le moyen de programme pour une efficacité maximale. De plus, c'est très gratifiant car vous pouvez ajouter toutes sortes de raccourcis d'optimisation auxquels un compilateur ne pense pas, car un compilateur ne peut pas penser du tout.
C va bien je suppose. Mais si vous savez vraiment ce que vous voulez que votre machine fasse au niveau matériel, allez assembleur.
la source