vettorizzazione è buona se
- Rende il codice più facile da leggere e le prestazioni non sono c ritical
- Se è un'operazione di algebra lineare, l'uso di uno stile vettoriale può essere utile perché Julia può utilizzare BLAS e LAPACK per eseguire l'operazione con codice altamente specializzato e ad alte prestazioni.
In generale, personalmente trovo il modo migliore di iniziare con il codice vettoriale, cercare eventuali problemi di velocità, quindi devetrizzare eventuali problemi problematici.
Il tuo secondo codice è lento non tanto per il suo vettore, ma per l'uso di una funzione anonima: sfortunatamente in Julia 0.3, questi sono normalmente un po 'più lenti. map
in generale non funziona molto bene, credo perché Julia non può inferire il tipo di output della funzione (è ancora "anonima" dal punto di vista della funzione map
). Ho scritto un vettorizzati versione diversa che evita funzioni anonime, ed è forse un po 'più facile da leggere:
function determine_pi_vec2(n)
return cumsum((rand(n).^2 .+ rand(n).^2) .<= 1) ./ (1:n)
end
Benchmarking con
function bench(n, f)
f(10)
srand(1000)
@time f(n)
srand(1000)
@time f(n)
srand(1000)
@time f(n)
end
bench(10^8, determine_pi)
gc()
bench(10^8, determine_pi_vec)
gc()
bench(10^8, determine_pi_vec2)
mi dà i risultati
elapsed time: 5.996090409 seconds (800000064 bytes allocated)
elapsed time: 6.028323688 seconds (800000064 bytes allocated)
elapsed time: 6.172004807 seconds (800000064 bytes allocated)
elapsed time: 14.09414031 seconds (8800005224 bytes allocated, 7.69% gc time)
elapsed time: 14.323797823 seconds (8800001272 bytes allocated, 8.61% gc time)
elapsed time: 14.048216404 seconds (8800001272 bytes allocated, 8.46% gc time)
elapsed time: 8.906563284 seconds (5612510776 bytes allocated, 3.21% gc time)
elapsed time: 8.939001114 seconds (5612506184 bytes allocated, 4.25% gc time)
elapsed time: 9.028656043 seconds (5612506184 bytes allocated, 4.23% gc time)
così vectorized il codice può essere sicuramente buono quanto devectorizzato in alcuni casi, anche quando non siamo in un caso di algebra lineare.
Grazie. Ho modificato il secondo codice per rimuovere la funzione anonima ma il suo rendimento è ancora negativo: la funzione èInside (x) x <= 1? 1: 0 fine; function define_pi_vec (n) res = cumsum (mappa (isInside, rand (n).^2 + rand (n).^2)) ./ [1: n]; restituzioni fine; @time returnArray2 = define_pi_vec (n); # tempo trascorso: 2.303632751 secondi (880001336 byte allocati, 31.88% tempo gc) –
La funzione anonima non è il problema più grande - è più che 'mappa' non esegue argomenti di funzione in linea e genera codice specializzato, mentre evitando la mappa, il controllo isInside può essere sottolineato. – StefanKarpinski
Hah si Ho appena aggiornato la mia risposta per tentare di chiarire quel punto – IainDunning