2013-08-10 21 views
10

Mentre leggevo i suggerimenti in c. Ho visto questo suggerimento qui http://www.cprogramming.com/tips/tip/multiply-rather-than-divide ma non sono sicuro. Mi è stato detto che sia la moltiplicazione che la divisione sono più lenti e richiedono molto tempo e richiedono molti cicli.moltiplicare per 0,5 anziché dividere per 2

e ho visto persone utilizzare spesso i << 2 anziché i x 4 poiché lo spostamento è più veloce.

Così mi aiuti con this.Is un buon suggerimento usando x0.5 or /2? o comunque i compilatori moderni lo ottimizzano in un modo migliore? Voglio conoscere le opinioni dei ragazzi da StackOverflow.

Inoltre, è possibile pubblicare alcuni collegamenti per suggerimenti utili n trap in c. Qualsiasi aiuto è molto apprezzato.

+7

'i * 0.5' non è sempre lo stesso di' I/2' (se 'I' è un' int', la divisione è integrale e il punto non mobile) – SheetJS

+5

Si dovrebbe scrivere il codice in modo chiaro ('i * 4' e' i/2') per prima cosa e attiva le ottimizzazioni del compilatore. I compilatori sono molto bravi a queste ottimizzazioni. – Blastfurnace

+0

Grazie per il tuo consiglio @Blastfurnace – niko

risposta

13

È vero che alcuni (se non la maggior parte) processori possono moltiplicarsi più velocemente di eseguire una divisione. Ma è come se il mito di ++i fosse più veloce di i++ in un ciclo for. Sì, lo era una volta, ma oggigiorno i compilatori sono abbastanza intelligenti da ottimizzare tutte queste cose per te, quindi non dovresti più preoccupartene.

E di bit-shifting, una volta era più veloce di spostare << 2 poi a moltiplicarsi con 4, ma in questi giorni sono finiti, la maggior parte dei processori possono moltiplicarsi in un ciclo di clock, proprio come un'operazione di spostamento. Un grande esempio di questo è stato il calcolo dell'indirizzo pixel nella modalità VGA 320x240. Tutti hanno fatto questo:

address = x + (y << 8) + (y << 6) 

a moltiplicarsi y con 320. Sui processori moderni, questo è in realtà molte volte più lento di

address = x + y * 320; 

Quindi, basta scrivere ciò che si pensa e il compilatore farà il resto :)

+0

Nessun processore noto di moltiplicarsi in 1 ciclo (fonte: http://instlatx64.atw.hu/). (tuttavia, la moltiplicazione per 4 sarà probabilmente ottimizzata per uno spostamento dal compilatore comunque) – harold

+0

@harold: la latenza potrebbe essere> 1 ciclo, ma il throughput dovrebbe essere 1 ciclo/mult sulla maggior parte delle CPU moderne ... –

+0

@OliCharlesworth sì e shift (di una costante) di solito hanno un throughput di due turni/ciclo – harold

14

trovo che questo servizio ha un valore inestimabile per testare questo genere di cose:

http://gcc.godbolt.org/

Basta guardare l'assemblaggio finale. Il 99% delle volte, vedrai che il compilatore ottimizza comunque tutto sullo stesso codice. Non sprecare il potere del cervello!

In alcuni casi, è preferibile scriverlo in modo esplicito. Ad esempio, 2^n (dove n è un numero intero positivo) potrebbe essere scritto come (int) pow(2.0, n) ma è ovviamente meglio usare 1<<n (e il compilatore non renderà tale ottimizzazione per te). Quindi può valere la pena tenere queste cose nel retro della tua mente. Come con qualsiasi cosa però, non ottimizzarlo prematuramente.

+1

Grazie per il link. @Dave – niko

1

Molte CPU possono eseguire la moltiplicazione in 1 o 2 cicli di clock ma divisione richiede sempre più (sebbene divisione FP è talvolta più veloce di divisione intera).

Se si guarda a questa risposta How can I compare the performance of log() and fp division in C++? si vedrà che la divisione può superare 24 cicli.

Perché la divisione impiega molto più tempo della moltiplicazione? Se ti ricordi di tornare alla scuola elementare, puoi ricordare che la moltiplicazione può essere essenzialmente eseguita con molte aggiunte simultanee. La divisione richiede una sottrazione iterativa che non può essere eseguita simultaneamente, quindi richiede più tempo. In effetti, alcune unità FP accelerano la divisione eseguendo un'approssimazione reciproca e moltiplicando per quello. Non è altrettanto preciso ma è un po 'più veloce.

1

Se si lavora con numeri interi, e si aspetta di ottenere un intero come risultato, è meglio usare / 2, in questo modo evita conversioni inutili negli da/per float

+1

Se si lavora con numeri interi e si aspetta un intero come risultato, '>> 1' è superiore a'/2'. Il compilatore non può sostituire quest'ultimo con il primo perché non sono equivalenti per i numeri negativi (eccetto quando il risultato è un numero intero, conoscenza che il programmatore ha ma il compilatore potrebbe non essere in grado di dedurre) –

+0

@PascalCuoq è vero, ma il la differenza scompare se si lavora con 'unsigned int's, per ovvi motivi. E se stai lavorando con 'int's con segno, probabilmente non vuoi un comportamento scorretto per i numeri negativi. – Dave

+0

Non è corretto se "si prevede di ottenere un numero intero come risultato". –

0
  1. "moltiplicare per 0,5 anziché dividere di 2 "(2.0) è più veloce su in meno di ambienti in questi giorni rispetto a prima, principalmente a causa di compilatori migliorati che ottimizzeranno il codice.

  2. "utilizzare i < < 2 invece di i x 4" è più veloce in meno ambienti per ragioni analoghe.

  3. In selezionare casi, il programmatore deve ancora occuparsi di tali problemi, ma è sempre più raro. Codice manutenzione continua a crescere come un problema dominante. Quindi, utilizzare ciò che rende più senso per quel frammento di codice: x*0.5, x/2.0, half(x), ecc

  4. compilatori facilmente ottimizzare il codice. Consiglia il codice con in mente i problemi di alto livello. Per esempio. L'algoritmo O (n) o O (n * n)?

  5. L'importante idea da trasmettere è che le migliori pratiche di progettazione del codice si evolvano e che le variazioni avvengano tra gli ambienti. Essere adattabile Ciò che è meglio oggi potrebbe spostarsi (o moltiplicarsi) in futuro.

Problemi correlati