Domanda

Che compila in codice più veloce:"ans = n * 3" o "ans = n+(n*2)"?

Supponendo che n sia un int o un long e che sia in esecuzione su un moderno box Intel Win32.

Sarebbe diverso se fosse coinvolto qualche dereferenziamento, ovvero quale di questi sarebbe più veloce?

long    a;
long    *pn;
long     ans;

...
*pn = some_number;
ans = *pn * 3;

O

ans = *pn+(*pn*2);

Oppure è qualcosa di cui non bisogna preoccuparsi poiché è probabile che i compilatori ottimizzatori ne tengano conto in ogni caso?

È stato utile?

Soluzione

IMO tale micro-ottimizzazione non è necessaria a meno che non si lavori con qualche compilatore esotico.Metterei la leggibilità al primo posto.

Altri suggerimenti

Non importa.I processori moderni possono eseguire un'istruzione MUL intera in un ciclo di clock o meno, a differenza dei processori più vecchi che dovevano eseguire una serie di spostamenti e addizioni internamente per eseguire il MUL, utilizzando quindi più cicli.Ci scommetterei

MUL EAX,3

viene eseguito più velocemente di

MOV EBX,EAX
SHL EAX,1
ADD EAX,EBX

L'ultimo processore in cui questo tipo di ottimizzazione avrebbe potuto essere utile è stato probabilmente il 486.(sì, questo è influenzato dai processori Intel, ma probabilmente è rappresentativo anche di altre architetture).

In ogni caso, qualsiasi compilatore ragionevole dovrebbe essere in grado di generare il codice più piccolo/veloce.Quindi vai sempre prima con la leggibilità.

Dato che è facile misurarlo da soli, perché non farlo?(Utilizzando gcc E time da Cygwin)

/* test1.c */
int main()
{
    int result = 0;
    int times = 1000000000;
    while (--times)
        result = result * 3;
    return result;
}

machine:~$ gcc -O2 test1.c -o test1
machine:~$ time ./test1.exe

real    0m0.673s
user    0m0.608s
sys     0m0.000s

Fate il test per un paio di volte e ripetetelo per l'altro caso.

Se vuoi dare un'occhiata al codice assembly, gcc -S -O2 test1.c

Ciò dipenderebbe dal compilatore, dalla sua configurazione e dal codice circostante.

Non dovresti provare a indovinare se le cose sono "più veloci" senza effettuare misurazioni.

Generalmente al giorno d'oggi non dovresti preoccuparti di questo tipo di cose di ottimizzazione su scala nanometrica: è quasi sempre completamente irrilevante e se lavorassi veramente in un dominio in cui contava, staresti già utilizzando un profiler e guarderesti l'output in linguaggio assembly del compilatore .

Non è difficile scoprire cosa sta facendo il compilatore con il tuo codice (qui sto usando DevStudio 2005).Scrivi un semplice programma con il seguente codice:

int i = 45, j, k;
j = i * 3;
k = i + (i * 2);

Posiziona un punto di interruzione sulla riga centrale ed esegui il codice utilizzando il debugger.Quando viene attivato il punto di interruzione, fare clic con il pulsante destro del mouse sul file sorgente e selezionare "Vai a disassemblaggio".Ora avrai una finestra con il codice che la CPU sta eseguendo.Noterai in questo caso che le ultime due righe producono esattamente le stesse istruzioni, vale a dire "lea eax,[ebx+ebx*2]" (non spostamento e aggiunta di bit in questo caso particolare).Su una moderna CPU IA32, è probabilmente più efficiente eseguire un MUL diretto piuttosto che uno spostamento di bit a causa della natura pipeline della CPU che comporta una penalità quando si utilizza un valore modificato troppo presto.

Ciò dimostra di cosa sta parlando aku, vale a dire che i compilatori sono abbastanza intelligenti da scegliere le migliori istruzioni per il tuo codice.

Dipende dal compilatore che stai effettivamente utilizzando, ma molto probabilmente si traducono nello stesso codice.

Puoi verificarlo tu stesso creando un piccolo programma di test e verificandone il disassemblaggio.

La maggior parte dei compilatori è abbastanza intelligente da scomporre una moltiplicazione di numeri interi in una serie di spostamenti e addizioni di bit.Non conosco i compilatori Windows, ma almeno con gcc puoi fargli sputare l'assemblatore, e se lo guardi probabilmente puoi vedere l'assemblatore identico per entrambi i modi di scriverlo.

Non importa.Penso che ci siano cose più importanti da ottimizzare.Quanto tempo hai investito pensando e scrivendo quella domanda invece di programmare e testare da solo?

:-)

Finché usi un compilatore di ottimizzazione decente, basta scrivere codice che sia facile da comprendere per il compilatore.Ciò rende più semplice per il compilatore eseguire ottimizzazioni intelligenti.

La tua domanda indica che un compilatore ottimizzatore sa più di te sull'ottimizzazione.Quindi fidati del compilatore.Utilizzo n * 3.

Dai un'occhiata a questa risposta anche.

I compilatori sono bravi a ottimizzare codice come il tuo.Qualsiasi compilatore moderno produrrebbe lo stesso codice per entrambi i casi e inoltre lo sostituirebbe * 2 da uno spostamento a sinistra.

Affidati al tuo compilatore per ottimizzare piccoli pezzi di codice del genere.La leggibilità è molto più importante a livello di codice.La vera ottimizzazione dovrebbe arrivare a un livello più alto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top