Table of Contents
Johdanto
Digitaalinen signaalinkäsittely (DSP) on nykyaikaisen sulautettujen järjestelmien selkäranka, mikä mahdollistaa reaaliaikaisen audio-, video-, telemetria- ja viestintätoiminnan. Kirjoittaminen tehokas C-koodi DSP-tehtäville suoraan vaikuttaa järjestelmän läpisyöttö, virrankulutus ja latenssi. Toisin kuin yleiskäyttöinen koodi, DSP-algoritmien on toteutettava tiukan ajoituksen rajoissa samalla maksimoimalla rajoitettujen muisti- ja käsittelyresurssien käytön. Tämä opas laajentaa ydinperiaatteita ja tarjoaa toimintakelpoisia tekniikoita kirjoittaa tuotannon-luokan C-koodi DSP-sovelluksille, kiinteän piste aritmeettinen ja laitteistokohtaiset optimointia.
DSP:n perusteiden ymmärtäminen C:ssä
DSP sisältää matemaattisia operaatioita, kuten suodattamista, muunnelmia, konvoluutiota ja spektrianalyysia otokseen otetuista signaaleista. C:ssä ohjelmoija valvoo kaikkia datan esitys- ja virtausnäkökohtia, jotka ovat ratkaisevia deterministisen toteutuksen kannalta. DSP-koodi toimii usein mikro-ohjaimissa tai digitaalisissa signaaliprosessorissa, joissa laitteisto on tiiviisti kytketty.Esimerkiksi on omistettu MAC (moninkertaistettu) yksikköjä tai SIMD-vektorimoottoreita. Syvä ymmärrys kohdearkkitehtuurista on tärkeä ja ääretön kyky kirjoittaa tehokas C-koodi.
DSP-koodin keskeiset ominaisuudet:
- Koostutetut aritmeettiset:[ silmukat, joissa on kerroinlisäystä (esim. FIR-suodattimet).
- Reaaliaikarajoitukset: jokainen näyte on käsiteltävä näytejakson aikana.
- Tietojen suoratoisto:[ jatkuva syöte/tuotosvirrat edellyttävät tehokasta puskurointia ja mahdollisimman vähäistä kopiointia.
- Muistin kaistanleveys:[ monet DSP-algoritmit ovat rajoitettuja sen mukaan, kuinka nopeasti tietoja voidaan siirtää, ei aritmeettisten toimintojen avulla.
Perusviittauksena ks. [Analog Devicesin DSP-perustiedot.
Kiinteä piste-aritmeettinen: tarkkuus ilman kelluva piste-pää
Monilla DSP-prosessoreilla ei ole laitteistoa kelluvia pisteyksiköitä (FPU) tai niillä on hitaampia FPU:ita. Kiinteä piste aritmeettinen käyttö kokonaislukutoiminnoilla, joilla on implisiittinen radiksipiste, jotka tarjoavat deterministisen suorituskyvyn ja pienemmän tehonkulutuksen. Yleisin esitys on Q-merkintä: Q[m[]].[[]]]n[[]]]] bittien lukumäärä on ubikvitous 16-bittisissä DSP:issä.
Kiinteän pistetoiminnan toteuttaminen C-osassa
Kiinteä-piste lisääminen on yksinkertainen (yksinkertaistaa lisätä kokonaislukuja), mutta kertolasku edellyttää säätö radix kohta. Q15 kertolasku, tuote kaksi Q15 numerot tarvitsee 32-bittinen välitulos, sitten oikea-siirtymä 15 bittiä päästä takaisin Q15. Esimerkki:
typedef int16_t q15_t;
q15_t q15_mul(q15_t a, q15_t b) {
int32_t temp = (int32_t)a * (int32_t)b;
return (q15_t)(temp >> 15);
}
Kun kertyy (esim. suodattimet), suojabitit estävät ylivuodon. Käytä 32-bittisiä tai jopa 64-bittisiä akkuja ja kylläisiä tuloksia. Kiinteiden pistekirjastojen kuten ARM CMSIS-DSP[] tarjoavat optimoituja kiinteä-pistetoimintoja, kuten suodattamista, muunnoksia ja matriisitoimintoja.
Milloin kiinteää pistettä käytetään vs. kelluva piste
Nykyaikaiset prosessorit, joissa on FPU (esim. Cortex-M4/M7), voivat suorittaa liukulukutoimintoja niin nopeasti kuin kiinteällä pisteen kohdalla.
- Algoritmin dynaaminen alue on korkea (esim. adaptiiviset suodattimet).
- Koodien säilyvyys on ensisijainen tavoite (vähäinen skaalausanalyysi).
- FPU-laitteisto on läsnä ja putkisto voi päällekkäin lisätä ja moninkertaistaa.
Suuritehoisten laitteiden, joissa ei ole FPU-yksiköitä, kiinteä piste on edelleen kustannusherkkien sovellusten standardi.
Optimoin muistin Access DSP
DSP-algoritmit käsittelevät usein suuria tietoryhmiä peräkkäin. Välimuistit ja bussikojut voivat tappaa suorituskyvyn. Noudata näitä periaatteita:
- Lähetystietojen saatavuus:[, kulkujärjestelmät vierekkäisessä järjestyksessä (rivinpääosa C). Vältä askeltettuja käyttömalleja, ellei algoritmi vaadi niitä (esim. FFT:n bittikäännös).
- Tietojen yhdenmukaistaminen:[ varmistavat, että järjestelmät ovat linjassa välimuistin rajojen kanssa. Käytä kääntäjän ominaisuuksia kuten tai erityisiä muistin osia.
- Puskuri:[] käyttää kaksoispuskuria päällekkäisiin DMA-siirtoihin CPU-käsittelyn kanssa. Kun suoritin toimii yhdellä puskurilla, seuraava näytelohko ladataan.
- Rajoittaa avainsana:[ käyttää C99.s osoittimia ilmoittaa kääntäjälle, että osoittimet eivät valehtele, mikä mahdollistaa vektoroinnin ja parempi opetusaikataulu.
Esimerkiksi yksinkertainen FIR-suodatintoiminto olisi kirjoitettava ...restriktiolla... ........................................................................................................................................................................................................................................
void fir_lowpass(const int16_t * restrict x, int16_t * restrict y,
const int16_t * restrict coeffs, int len, int order) {
for (int i = 0; i < len; i++) {
int32_t acc = 0;
for (int j = 0; j < order; j++) {
acc += (int32_t)x[i + j] * coeffs[j];
}
y[i] = (int16_t)(acc >> 15);
}
}
Tehokas algoritmin valinta ja toteutus
Algoritminen monimutkaisuus kääntää suoraan suoritusaika ja teho. Valitse aina tehokkain algoritmi tehtävään:
- Fast Fourier Transform (FFT):[] käyttää Cooley-Tukey radix-2 tai split-radiox kahden pituudet teho. Vältä naiivi DFT, joka on O(N2). Pre compute twiddle tekijät ja tallentaa ROM.
- FIR-suodattimet:[ käyttävät monivaiheista hajoamista deduktion/interpoloinnin yhteydessä; hyödyntävät symmetriaa lineaarisen vaiheen suodattimissa puolittaakseen kerrosten määrän.
- IIR-suodattimet:[ käytetään suoraa muotoa II, joka on saatettu osaksi kansallista lainsäädäntöä numeerisen vakauden parantamiseksi; käytetään kaskadedikaksijalkaisia osia (toisen asteen vaiheita) herkkyyden vähentämiseksi kertoimen kvantitaation suhteen.
- Konvoluutio:[ pitkissä sekvensseissä, käytä FFT-pohjaisia päällekkäisyyksiä lisääviä tai päällekkäisiä pelastavia menetelmiä suoran konvoluution sijaan.
Ks. FFTW-kirjasto, joka viittaa nykyaikaisiin FFT-tekniikoihin (vaikka ei C:ssä, sen periaatteet ovat laajalti kopioituina sulautettuihin DSP-kirjastoihin).
Leveraging Hardware Ominaisuudet: Simd ja DSP Ohjeet
Lähes kaikki nykyaikaiset mikro-ohjaimet sisältävät SimD- (Single Instruction Multiple Data) tai DSP-tarkennetut ohjeet.
- ARM Cortex-M4/M7: SIMD (SADD, SMUAD jne.), tyydyttynyt aritmeettinen ja murto-osatoiminnot (QADD, QSUB). Käytä CMSIS-DSP sisäisiä toimintoja.
- TI C6000 DSP: kahdeksan kerrosta yksikköä, dual MAC, ja ohjelmisto pillinointi. [TI DSP optimointi opas[ tarjoaa yksityiskohtaisia tekniikoita.
- RISC-V ja P-laajennukset: tulevissa ydinaineissa on DSP-ohjeet.
Käytä näitä ominaisuuksia C:ssä kirjoittamalla koodi, jonka kääntäjä voi automaattisesti vektorioida (esim. yksinkertaiset silmukat, joissa ei ole riippuvuuksia) tai käyttämällä kääntäjän sisäisiä toimintoja. Esimerkkinä ARM CMSIS-DSP:n käytöstä FIR-suodattimessa:
#include "arm_math.h"
arm_fir_instance_f32 S;
float32_t firState[128];
arm_fir_init_f32(&S, numTaps, coeffs, firState, blockSize);
arm_fir_f32(&S, input, output, blockSize);
Tällaiset kirjastot on kytketty käsin mahdollisimman tehokkaaseen kokoonpanoon. Profiili on aina ennen ja jälkeen siirtymisen C-generaalitoiminnoista kirjastoon.
Loop Optimointitekniikat
Koska DSP-algoritmit ovat silmukan painavia, optimoinnit silmukan tasolla maksavat suuria osinkoja:
- Kirjoita kääre:[ käsin tai kääntäjä pragma (...#pragma unroll N...) silmukkapinnoitteen yläpuolella ja lisää ohjetason rinnakkaisuutta.
- Ohjelmistojen pillitys:[ uudelleenjärjestely silmukat niin, että useita iteraatioita lennetään samanaikaisesti. Jotkut kääntäjät tekevät tämän automaattisesti; käytä ...-O3... ja arkkitehtuurikohtaisia lippuja.
- Vähennetään haarautumista:[ korvataan ehdoilla aritmeettisella (esim. min/max ternaarisella) tai käytetään hakutaulukoita epälineaarisiin toimintoihin.
- Käytä paikallisia muuttujia:[ tallentaa usein rekistereissä olevia tietoja ilmoittamalla muuttujat sisällä silmukalla tai käyttämällä ...
- Minimize divisions: korvaa jakovakion kertomalla se vastavuoroisella; käytä siirtymää kahden voimien osalta.
Ennakoi vakioita ja hakutaulukoita
DSP-toiminnot, kuten trigonometriset arvot, kertoimet ja twiddle-kertoimet, tulisi esikomponentoida offline-tilassa ja tallentaa vakioina ROM-muodossa. Ei-reaaliaikakäynnistys, voit laskea ne kerran ja uudelleen. Esimerkki: 1024-pisteen FFT, precomprecompate sine/cosine arvot kunkin vaiheen. Tämä eliminoi ajoajan arviointi ja vähentää tehoa.
Lookup-taulukot (LUTs) auttavat myös toiminnoissa, kuten neliöjuuri, eksponentti ja log käytetään DSP (esim., puheen käsittelyssä). Käytä lineaarinen interpolointi taulukon merkinnät vaihtaa pois muisti vs tarkkuus.
Profilointi ja virittäminen
Optimointia ei ole suoritettu ilman mittausta. Käytä näitä tekniikoita pullonkaulojen tunnistamiseen:
- Sykleen tarkkuusprofilointi:[ käyttää syklin laskureita (esim. DWT CYCCNT Cortex-M:ssä) toiminnon keston mittaamiseen.
- Tilastollinen profilointi:[ näyteohjelmalaskuri (PC) nähdäkseen mitkä toiminnot kuluttavat suorittimen aikaa.
- Muistiprofilointi:[ käyttää työkaluja seurata välimuistin ohitus (jos saatavilla) ja bussitapahtumien.
- Kääntäjän palaute:[ mahdollistaa kääntäjän optimointiraportit (...-fopt-info-vec-optimoitu) GCC:ssä, jotta voidaan selvittää, onko silmukat vektoroitu.
Iteraatti: mittaa, muuta, mittaa uudelleen. Usein suurimmat hyödyt tulevat muistin kulun parantamisesta pikemminkin kuin laskutoimituksen säätämisestä.
Käytännön yhteenveto: Kokoaminen yhteen
Tehokkaan DSP-koodin kirjoittaminen C:ssä edellyttää kokonaisvaltaista lähestymistapaa:
- Valitse oikea tietojen esitys (kiinteä piste vs kelluva piste).
- Suunnittele tietorakenteet peräkkäistä käyttöä ja yhdenmukaistamista varten.
- Valitse algoritmeja, joiden monimutkaisuus on alhainen (FFT, polyfaasi).
- Käytä myyjä DSP kirjastoja, kun käytettävissä.
- Irrota silmukka ja vähentää haarautumista.
- Ennakoi vakiot ROM.
- Profiilin hellittämätön ja anna kääntäjän auttaa.
Sovelltamalla näitä periaatteita kehittäjät voivat saavuttaa signaalinkäsittelyn läpimenon, joka on verrattavissa käsin viritettyyn kokoonpanoon ja säilyttää C.S.S.S.S.S.T.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.