2013-08-22 19 views
5

Il log (a * b) è sempre più veloce in Matlab di log (a) + log (b)?Il log (a * b) è sempre più veloce in Matlab di log (a) + log (b)?

Ho provato per diversi ingressi e sembra log (a * b) è più veloce. Puoi ragazzi più esperti darmi qualche opinione su questo? Forse avverte che questo potrebbe non essere sempre il caso, o qualcosa di altrimenti dovrei stare attento con? Quindi nel primo caso abbiamo 1 operazione di registro e 1 moltiplicazione, nel secondo caso abbiamo due operazioni di registro e una sommatoria.

Edit:

Per aggiungere al mio post originale, la questione più generale è:

è log (a * b * ... * z) sempre più veloce di registro (a) + log (b) + ... + log (z)?

Grazie

+4

Vorrei pensare a "ora di log >>" tempo di moltiplicazione'> "tempo di aggiunta".Quindi questa osservazione ha un senso. – lurker

risposta

13

log(a*b) dovrebbero sempre essere più veloce, perché il calcolo del logaritmo è costoso. In log(a*b) lo fai solo una volta, in log(a)+log(b) lo fai due volte.

Computing prodotti e somme viene confrontato banale logaritmi, esponenziali ecc In termini di cicli del processore, sia le somme e prodotti sono generalmente inferiore a 5, mentre esponenziali e logaritmi può andare da 50 a 200 cicli per alcune architetture.

è log (a * b * ... * z) sempre più veloce di registro (a) + log (b) + ... + log (z)

Sì. Decisamente. Evitare il calcolo dei logaritmi quando possibile.

Ecco un piccolo esperimento:

a=rand(5000000,1); 

% log(a(1)*a(2)...) 
tic 
for ii=1:100 
    res=log(prod(a)); 
end 
toc 
% Elapsed time is 0.649393 seconds. 

% log(a(1))+log(a(2))+... 
tic 
for ii=1:100 
    res=sum(log(a)); 
end 
toc 
% Elapsed time is 6.894769 seconds. 

Ad un certo punto il rapporto nel tempo saturerà. La saturazione dipende dall'architettura del processore, ma la differenza sarà almeno di un ordine di grandezza.

+0

La differenza è ancora più drastica nel caso del registro complesso, ad esempio, 'a' è un vettore di valori casuali complessi. – horchler

+3

attento qui, moltiplicando molti piccoli valori nell'intervallo [0,1] diventerà rapidamente zero. Questo tipo di problema si verifica spesso nella vita reale quando si lavora con [probabilità] (http://en.wikipedia.org/wiki/Log_probability) ... Quindi la velocità non è tutto, e si dovrebbe anche preoccuparsi della stabilità numerica quando si lavora con numeri a virgola mobile. – Amro

+0

Per illustrare quanto è grave, nel tuo esempio sopra solo dopo circa 700 elementi (su 5 milioni) che il prodotto è diventato zero: 'sum (cumprod (a)> 0)' mi ha dato 729 – Amro

9

Attenzione, mentre il calcolo del log del prodotto è più veloce, a volte può essere errato a causa della precisione della macchina.

Uno dei casi problematici è l'utilizzo di molti operandi interi o numeri grandi come operandi. In questo caso, il prodotto a_1 * a_2 * ... a_n genererà un overflow, mentre non calcolerà la somma dei logaritmi.

Un altro caso problematico è l'utilizzo di numeri piccoli in modo che il loro prodotto diventi zero a causa della precisione della macchina (come menzionato da Amro).

+1

OK, in quel caso noi puoi creare prodotti parziali, moltiplicarli prima dell'overflow e quindi prendere il registro di quello. Quindi continua a fare la stessa cosa, continua a raccogliere termini nei prodotti, prima che l'overflow porti il ​​log. Essere d'accordo? – user2381422

+1

Sì, sembra fattibile. –

+2

+1 Buona osservazione a una domanda in cui la risposta era già stata dichiarata. – Werner

2

Anche se di solito è più veloce fare log(a*b) anziché log(a) + log(b), ciò non vale se è difficile valutare a*b. In questo caso, in realtà, può essere più rapido utilizzare il secondo metodo.

Esempio:

a = 0; 
b = Inf; 
tic,for t = 1:1e6 log(a*b); end,toc 
tic,for t = 1:1e6 log(a)+log(b); end,toc 

Naturalmente valuterà a NaN in entrambi i casi, ma la seconda è notevolmente più veloce rispetto al primo.

+0

0 * Inf è gestito a velocità su processori moderni; non c'è nulla di "difficile da valutare" a riguardo. (In passato, alcuni processori avrebbero incontrato bancarelle che facevano aritmetica con Infinities e NaNs, ma non è più una preoccupazione reale) –

+0

@StephenCanon i tempi di esecuzione mostrano che in qualche modo è ancora lento. Forse la parte lenta è la valutazione di 'log (NaN)' piuttosto che la creazione del 'NaN' moltiplicando lo zero con l'infinito. Ovviamente il rallentamento è relativo, il caso "normale" è solo 2 volte più veloce. –

+1

È certamente possibile che nel tuo log di sistema (nan) sia più lento di log (0) e log (inf), ma quello sarebbe una stranezza di un'implementazione di una libreria matematica, non un risultato generalmente applicabile. –

Problemi correlati