Quanto l'uso di macro "probabili" e "improbabili" è eccessivo?

11

Le macro spesso definite come likely e unlikely aiutano il compilatore a sapere se un if di solito verrà inserito o ignorato. Usandolo si ottengono alcuni (piuttosto minori) miglioramenti delle prestazioni.

Ho iniziato a usarli di recente e non sono sicuro di quanto spesso dovrebbero essere utilizzati tali suggerimenti. Attualmente lo uso con il controllo degli errori if s, che in genere sono contrassegnati come unlikely . Ad esempio:

mem = malloc(size);
if (unlikely(mem == NULL))
  goto exit_no_mem;

Sembra ok, ma il controllo degli errori if s si verifica abbastanza spesso e di conseguenza l'uso delle suddette macro.

La mia domanda è: è troppo per avere likely e unlikely macro su ogni controllo degli errori if ?

Mentre ci siamo, quali altri posti sono usati spesso?

Nel mio attuale utilizzo è in una libreria che crea un'astrazione dal sottosistema in tempo reale, quindi i programmi diventerebbero portatili tra RTAI, QNX e altri. Detto questo, la maggior parte delle funzioni è piuttosto piccola e chiama direttamente una o due altre funzioni. Molte sono anche funzioni static inline .

Quindi, prima di tutto, non è un'applicazione che potrei definire. Non ha senso "identificare i colli di bottiglia" dato che si tratta di una libreria, non di un'applicazione autonoma.

In secondo luogo, è un po 'come "So che è improbabile, potrei anche dirlo al compilatore". Non cerco attivamente di ottimizzare if .

    
posta Shahbaz 01.03.2013 - 12:28
fonte

2 risposte

11

Hai bisogno di prestazioni così male che sei disposto ad inquinare il tuo codice con quello? È un'ottimizzazione minore.

  • Il codice viene eseguito in un ciclo stretto?
  • La tua applicazione presenta problemi di prestazioni?
  • Hai profilato la tua applicazione e stabilito che questo particolare ciclo costa molto tempo della CPU?

A meno che tu non possa rispondere a yes a quanto sopra, non preoccuparti di cose del genere.

Modifica: in risposta alla modifica. Anche quando non puoi profilare, puoi solitamente stimare gli hotspot. Una funzione di allocazione di memoria chiamata da tutti è un buon candidato, soprattutto dal momento che richiede solo un singolo utilizzo della macro per funzionare per l'intera libreria.

    
risposta data 01.03.2013 - 13:02
fonte
1

Se stai scrivendo per x86 / x64 (e non stai usando CPU di 20 anni), il guadagno di prestazioni dall'uso di __builtin_expect () sarà trascurabile se ce ne sono. La ragione è che le moderne CPU x86 / x64 (non certo al 100% su Atom), hanno una previsione di branch dinamica, quindi essenzialmente la CPU "impara" sul ramo che viene preso più spesso. Certo, queste informazioni possono essere memorizzate solo per un numero limitato di filiali, tuttavia, ci sono solo due casi possibili. Se (a) si tratta di un ramo "usato frequentemente", allora il tuo programma trarrà vantaggio da quella previsione dinamica del ramo, e se (b) è un ramo "raro", non vedrai alcun risultato realistico in termini di prestazioni a causa di previsioni errate in tali rami rari (20 cicli di CPU di misprediction di ramo non sono TROPPO male se accade una volta in una luna blu).

NB: questo NON implica che sulla moderna importanza x86 / x64 della mispredicione dei rami sia più basso: qualsiasi ramo con 50-50 possibilità di saltare-nojump incorrerà comunque in una penalità (cicli IIRC 10-20 CPU), quindi in inner i rami di loops possono ancora essere evitati. È solo l'importanza di __builtin_expect () su x86 / x64 che è diminuita (IIRC, circa 10-15 anni fa circa) - principalmente a causa della previsione di branch dinamico.

NB2: per altre piattaforme oltre x86 / x64, YMMV.

    
risposta data 17.07.2018 - 17:53
fonte

Leggi altre domande sui tag