Ho giocato con alcuni Perl programs to calculate excellent numbers. Sebbene i tempi di esecuzione delle mie soluzioni fossero accettabili, ho pensato che un linguaggio diverso, in particolare quello progettato per materiale numerico, potesse essere più veloce. Un amico ha suggerito Julia, ma la prestazione che sto vedendo è così grave che devo fare qualcosa di sbagliato. Ho guardato attraverso il Performance Tips e non vedo che cosa devo migliorare:Come posso migliorare le prestazioni del mio programma Julia per numeri eccellenti?
digits = int(ARGS[1])
const k = div(digits, 2)
for a = (10^(k - 1)) : (10^(k) - 1)
front = a * (10^k + a)
root = floor(front^0.5)
for b = (root - 1): (root + 1)
back = b * (b - 1);
if back > front
break
end
if log(10,b) > k
continue
end
if front == back
@printf "%d%d\n" a b
end
end
end
Ho un programma di C equivalente di un ordine di grandezza più veloce al posto del fattore 2 annotati sulla Julia page (anche se la maggior parte di le domande StackOverflow circa la velocità di Julia sembrano indicare benchmark viziate da quella pagina):
E il non ottimizzato pura Perl ho scritto prende la metà del tempo:
use v5.20;
my $digits = $ARGV[0] // 2;
die "Number of digits must be even and non-zero! You said [$digits]\n"
unless($digits > 0 and $digits % 2 == 0 and int($digits) eq $digits);
my $k = ($digits/2);
foreach my $n (10**($k-1) .. 10**($k) - 1) {
my $front = $n*(10**$k + $n);
my $root = int(sqrt($front));
foreach my $try ($root - 2 .. $root + 2) {
my $back = $try * ($try - 1);
last if length($try) > $k;
last if $back > $front;
# say "\tn: $n back: $back try: $try front: $front";
if($back == $front) {
say "$n$try";
last;
}
}
}
sto usando il pre-compilato Julia per Mac OS X da allora Non ho potuto ottenere la fonte da compilare (ma non ho provato oltre a farlo esplodere la prima volta). Immagino che ne faccia parte.
Inoltre, vedo circa 0,7 secondi di tempo di avvio per qualsiasi programma Julia (vedere), il che significa che il programma C compilato in modo equivalente può essere eseguito circa 200 volte prima che Julia termini una volta. Con l'aumentare del tempo di esecuzione (maggiori valori di digits
) e il tempo di avvio significa meno, il mio programma Julia è ancora molto lento.
Non ho ottenuto la parte per numeri molto grandi (numeri eccellenti di 20 cifre) che non ho capito che Julia non gestisce quelli meglio della maggior parte delle altre lingue.
Ecco il mio codice C, che è un po 'diverso da quando ho iniziato questo. Le mie abilità C arrugginite e ineleganti sono essenzialmente la stessa cosa del mio Perl.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long
k, digits,
start, end,
a, b,
front, back,
root
;
digits = atoi(argv[1]);
k = digits/2;
start = (long) pow(10, k - 1);
end = (long) pow(10, k);
for(a = start; a < end; a++) {
front = (long) a * (pow(10,k) + a);
root = (long) floor(sqrt(front));
for(b = root - 1; b <= root + 1; b++) {
back = (long) b * (b - 1);
if(back > front) { break; }
if(log10(b) > k) { continue; }
if(front == back) {
printf("%ld%ld\n", a, b);
}
}
}
return 0;
}
È necessario includere i tempi di riferimento effettivi e alcune descrizioni di come sono stati ottenuti. – jpmc26
La libreria standard è precompilata in v0.3, ma nient'altro, quindi il tempo di avvio di 0,7 secondi. Sembra che avremo la compilazione di pacchetti in v0.4 - a quanto pare è già possibile se si vuole giocare un po '(si veda [qui] (https://groups.google.com/forum/#! argomento/julia-dev/qdnggTuIp9s)). Quindi, in altre parole, lentamente ma sicuramente gli ostacoli alla riduzione del tempo di avvio vengono abbattuti uno per uno. –
Inoltre, il wrapping del codice in una funzione come suggerito da @VincentZoonekynd dà un aumento di quattro fattori sulla mia macchina. Non proprio le prestazioni che stai cercando, ma per arrivarci. –