2012-05-29 12 views
16

Ho sviluppato codice C++ per la realtà aumentata su dispositivi ARM e l'ottimizzazione del codice è molto importante al fine di mantenere un buon frame rate . Al fine di aumentare l'efficienza al livello massimo, penso che sia importante raccogliere suggerimenti generali che semplificano la vita dei compilatori e riducono il numero di cicli del programma. Qualsiasi suggerimento è accolto favorevolmente.C++ Suggerimenti per l'ottimizzazione del codice su dispositivi ARM

1- Evitare istruzioni ad alto costo: divisione, radice quadrata, seno, coseno

  • Utilizzare i turni logiche per dividere o moltiplicare per 2.
  • Moltiplicare per l'inverso, quando possibile.

2- Optimize interno "per" loop: sono un botleneck quindi dovremmo evitare di fare molti calcoli all'interno, in particolare le divisioni, radici quadrate ..

3- Utilizzare tabelle look-up per alcune funzioni matematiche (sin, cos, ...)

STRUMENTI UTILI

  • objdump: ottiene il codice assembly del programma compilato. Ciò consente di confrontare due funzioni e verificare se è davvero ottimizzata.
+8

** Attenzione **: al giorno d'oggi il collo di bottiglia è la memoria più spesso che no (e quindi LUT non sono così grandi ...). Potrebbe essere diverso su ARM, bisogna ammetterlo, ma ... meglio controllare che non investi per niente. –

+0

Sì. Ma nelle applicazioni in tempo reale, eseguendo molti calcoli per fotogramma, credetemi che l'ottimizzazione può salvare "alcuni fotogrammi al secondo". Dire "alcuni" sono 8 fps, come nel mio caso, ecco perché penso che questa domanda sia importante. –

+3

Hai la possibilità di controllare diverse metriche, come mancate cache, accessi al bus di memoria, ecc.? Questo è anche molto utile per sapere se il tuo mem bus è un collo di bottiglia. BTW, fuori tema, (donostia == San Sebastian)? Se è così, mi piace davvero quella città! – Brady

risposta

17

per rispondere alla tua domanda circa le regole generali per l'ottimizzazione del codice C++ per ARM, ecco alcuni suggerimenti:

1) Come lei ha ricordato , non c'è istruzione di divisione. Utilizzare spostamenti logici o moltiplicare per l'inverso quando possibile.
2) La memoria è molto più lenta dell'esecuzione della CPU; utilizzare le operazioni logiche per evitare tabelle di ricerca ridotte.
3) Provare a scrivere 32 bit alla volta per utilizzare al meglio il buffer di scrittura. Scrivere cortometraggi o caratteri rallenterà notevolmente il codice. In altre parole, è più logico-OR i bit più piccoli e li scrivono come DWORD.
4) Prestare attenzione alle dimensioni della cache L1/L2. Come regola generale, i chip ARM hanno cache molto più piccole di Intel.
5) Utilizzare SIMD (NEON) quando possibile.Le istruzioni NEON sono piuttosto potenti e per il codice "vectorizable" possono essere abbastanza veloci. Gli intrinseci di NEON sono disponibili nella maggior parte degli ambienti C++ e possono essere veloci quasi quanto scrivere codice ASM sintonizzato a mano.
6) Utilizzare il suggerimento cache precetch (PLD) per velocizzare le letture in loop. ARM non ha una logica precache intelligente come fanno i moderni chip Intel.
7) Non fidatevi del compilatore per generare un buon codice. Guarda l'output ASM e riscrivi gli hotspot in ASM. Per la manipolazione bit/byte, il linguaggio C non può specificare le cose con la stessa efficienza con cui possono essere eseguite in ASM. ARM ha potenti istruzioni a 3 operandi, multi-load/store e turni "liberi" che possono superare quello che il compilatore è in grado di generare.

+0

Mi piace moltiplicare per gli spostamenti inversi e logici. Cerco anche di usare il punto fisso sui dispositivi senza NEON. Aggiornerò il post con i tuoi consigli, grazie! –

+0

Riguardo a 5): Ho visto alcune discussioni SO sull'utilizzo degli intrinseci NEON. Per riassumere, sembra che molte persone stiano scoprendo che il compilatore non sta facendo un ottimo lavoro nel tradurre gli intrinsechi in un buon codice assembly. Il consenso sembra essere che se si desidera utilizzare NEON, è meglio scrivere direttamente come codice assembly. – Leo

+0

@Leo - dipende dal compilatore. GCC è pessimo nella compilazione di intrinseche NEON. LLVM di Apple è così così e i compilatori di Microsoft sono abbastanza buoni. – BitBank

15

Il modo migliore per ottimizzare un'applicazione consiste nell'utilizzare un buon profiler. È sempre una buona idea scrivere codice pensando all'efficienza, ma anche evitare di apportare modifiche laddove si "pensa" che il codice possa essere lento, questo potrebbe peggiorare le cose se non si è sicuri al 100%.

Scopri dove sono i colli di bottiglia e concentrati su quelli.

Per me la profilazione è un processo iterativo, perché di solito quando si risolve un collo di bottiglia, si manifestano anche altri meno importanti.

Oltre a profilare il SW, verificare quale tipo di profilo HW è disponibile. Verifica se puoi ottenere metriche HW diverse, ad esempio errori di cache, accessi al bus di memoria, ecc. Questo è anche molto utile per sapere se il tuo mem bus o cache è un collo di bottiglia.

Recentemente ho fatto questa domanda simile ed ho ottenuto alcune buone risposte: Looking for a low impact c++ profiler

Problemi correlati