Silly Python testing


Decollo!Python è un linguaggio di programmazione molto diffuso, soprattutto in ambiente Linux. E’ considerato facile da imparare e potente nell’utilizzo. E’ spesso criticato per la scarsa velocità, anche se poi molti tecnici e scienziati lo adoperano. Mi sono divertito a fare qualche test, ispirandomi ad un “benchmark” pubblicato sul sito di un compilatore Basic, un po’ insensato ma facile da capire e realizzare, un semplice ciclo ripetuto milioni di volte in cui sono eseguite alcune funzioni matematiche. Come riferimento è certamente criticabile. Eccone qua la prima versione.

import math 
import time 
 
starttime = time.time() 
 
Y = .5 
I=0 
for I in range(50000000): 
# while I < 50000000: 
    Y = Y / 1.1234 
    Y = Y * 1.1234 
    X = math.acos(Y) 
    X = math.asin(Y) 
    X = math.atan(Y) 
    X = math.cos(Y) 
    X = math.exp(Y) 
    X = math.log(Y) 
    X = math.sin(Y) 
    X = math.sqrt(Y) 
    X = math.tan(Y) 
 
print(X, " ", Y) 
 
print("Elapsed time = ", time.time() - starttime, " seconds")

 

Sul mio vecchio desktop con Python 2.6 ed Ubuntu 10.04 LTS il tempo di esecuzione è stato di circa 235 secondi. Niente di eccezionale ma neanche tragico, circa dieci volte il tempo ottenuto con compilatori utilizzati senza richiamare ottimizzazioni, mi sembra che per un linguaggio interpretato ci possa stare.

Ho poi trovato questa pagina web che spiega come ottimizzare gli “script” Python. Per prima cosa ho raccolto tutte le operazioni in una subroutine, in modo da utilizzare variabili locali:

 

import math 
import time 
 
def calc(): 
    Y = .5 
    for I in range(50000000): 
        Y = Y / 1.1234 
        Y = Y * 1.1234 
        X = math.acos(Y) 
        X = math.asin(Y) 
        X = math.atan(Y) 
        X = math.cos(Y) 
        X = math.exp(Y) 
        X = math.log(Y) 
        X = math.sin(Y) 
        X = math.sqrt(Y) 
        X = math.tan(Y) 
         
    return X 
 
# MAIN 
starttime = time.time() 
XX = calc() 
print(XX) 
print("Elapsed time = ", time.time() - starttime, " seconds")

 
Il tempo di esecuzione è “crollato” a168 secondi. Un guadagno di quasi il 30% con pochissimo sforzo! Ho poi tentato un’altra operazione suggerita: eliminare la “dot notation” rendendo locali anche le funzioni di libreria “invocate” molte volte.

 
import math 
import time 
 
def calc(): 
    acos = math.acos 
    asin = math.sin 
    atan = math.tan 
    cos = math.cos 
    exp = math.exp 
    log = math.log 
    sin = math.sin 
    sqrt = math.sqrt 
    tan = math.tan 
    Y = .5 
    for I in range(50000000): 
        Y = Y / 1.1234 
        Y = Y * 1.1234 
        X = acos(Y) 
        X = asin(Y) 
        X = atan(Y) 
        X = cos(Y) 
        X = exp(Y) 
        X = log(Y) 
        X = sin(Y) 
        X = sqrt(Y) 
        X = tan(Y) 
         
    return X 
 
# MAIN 
starttime = time.time() 
XX = calc() 
print(XX) 
print("Elapsed time = ", time.time() - starttime, " seconds")

 

Come si vede questa operazione è più macchinosa, ma il guadagno c’è, anche se non drammatico come nel caso precedente: 143 secondi di tempo totale.

Poi ho scoperto l’ “arma totale” per il Python, almeno se si vogliono fare solo calcoli: con il Pypy, “just in time compiler”, i tempi crollano a 34 secondi per la prima versione del test ed a 27 per l’ultima.

Che siano pochi o molti, in assoluto, non lo so, ma i risultati mi hanno colpito. La morale mi sembra che bisogna fare le cose in modo corretto prima di dare giudizi, e forse non solo in informatica.

 

Annunci

Lascia pure un Commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...