Secondo uno studio di ricerca di Models and Risk, sono state valutate le performance nell'esecuzione di un codice tradotto in vari linguaggi, a parità di hardware ovviamente, per creare poi una classifica e fare un confronto (rapportandolo al C e FORTRAN, che sappiamo essere i due più efficienti). In particolare i linguaggi:
- Julia 1.7.3
- R 4.2.0
- Python 3.9.12 (con o senza la libreria Numba, <<Numba makes Python code fast>>)
- MATLAB R2022a
Sono stati eseguiti tre esperimenti diversi.
esperimento 1: GARCH log-likelihood (funzione di log-verosimiglianza), metodo numerico iterativo con un grande numero di iterazioni. I codici sono i seguenti:
- C:
double likelihood(double o, double a, double b, double h, double *y2, int N){ double lik=0; for (int j=1;j<N;j++){ h = o+a*y2[j-1]+b*h; lik += log(h)+y2[j]/h; } return(lik); }
- R:
likelihood =function(o,a,b,y2,h,N){ lik=0 for(i in 2:N){ h = o + a * y2[i-1]+ b * h lik = lik + log(h) + y2[i]/hs } return(lik) }
- Python nativo:
def likelihood(hh,o,a,b,y2,N): lik = 0.0 h = hh for i in range(1,N): h=o+a*y2[i-1]+b*h lik += np.log(h) + y2[i]/h return(lik)
- Python con l'uso di Numba:
from numba import jit @jit def likelihood(hh,o,a,b,y2,N): lik = 0.0 h = hh for i in range(1,N): h=o+a*y2[i-1]+b*h lik += np.log(h) + y2[i]/h return(lik)
- MATLAB:
function lik = likelihood(o,a,b,h,y2,N) lik=0; for i = 2:N h=o+a*y2(i-1)+b*h; lik=lik+log(h)+y2(i)/h; end end
- Julia:
function likelihood(o, a, b, h, y2, N) local lik = 0.0 for i in 2:N h = o+a*y2[i-1]+b*h lik += log(h)+y2[i]/h end return(lik) end
- Julia con @inbound:
I risultati sono soprendenti, assegnando a C/FORTRAN valore 1 come tempo di esecuzione, Python nativo arriva a 212,84 quindi estremamente inefficiente (parliamo di un linguaggio interpretato, ad alto livello); con l'uso di Numba migliora notevolmente arrivando a 1,15 e supera Julia, linguaggio compilato molto efficiente che ha 1,54-1,61 a seconda che sia nativo o con @inboundfunction likelihood(o, a, b, h, y2, N) local lik = 0.0 for i in 2:N @inbounds h = o+a*y2[i-1]+b*h lik += log(h)+y2[i]/h end return(lik) end
- C:
esperimento 2: Loading a large database (caricare un file di grosse dimensioni, file CSV da 3GB non compresso, 600MB con compressione gzip):
- R:
require(data.table) uncompressed <- fread("crsp_daily.csv") compressed <- fread("crsp_daily.gz")
- Python:
import pandas as pd import gzip uncompressed = pd.read_csv("crsp_daily.csv") f = gzip.open("crsp_daily.gz") compressed = pd.read_csv(f)
- MATLAB:
uncompressed = readtable('crsp_daily.csv');
- Julia:
Per la gestione di file di grandi dimensioni, R si dimostra il linguaggio più indicato, MATLAB quello meno efficiente.using CSV using CodecZlib uncompressed = CSV.read("crsp_daily.csv", DataFrame); compressed = CSV.read(GzipDecompressorStream(open("crsp_daily.gz")), DataFrame)
- R:
esperimento 3: annual mean and standard deviation (calcolo di media e deviazione standard da un ampio set di dati, proprio quello del file CSV dell'esperimento 2):
- R:
Using R’s data.table package: library(data.table) R <- data[,list(length(RET), mean(RET), sd(RET)), keyby = list(year, PERMNO)]
- Python:
import pandas as pd data.groupby(['PERMNO', 'year'])['RET'].agg(['mean', 'std', 'count'])
- MATLAB:
statarray = grpstats(data, {'PERMNO', 'year'}, {'mean', 'std'}, 'DataVars', 'RET');
- Julia:
I risultati mostrano Julia al primo posto (assegniamo valore 1), seguito da Python con 1,18, MATLAB il peggiore con 4,62.using Statistics using DataFrames R = combine(groupby(data, [:year, :PERMNO]), :RET => mean => :m, :RET => std => :s, nrow => :c)
- R:
Conclusioni: è evidente che, come risaputo, un linguaggio compilato abbia prestazioni migliori rispetto ad uno interpretato. Nel complesso Julia risulta il più indicato per la computazione, quando occorre eseguire diverse operazioni; R il migliore quando abbiamo a che fare con un grande set di dati, che occupa molta memoria. Python ha performance molto diverse a seconda che sia usato quello nativo oppure grazie al package Numba che di fatto è un Just-in-Time (JIT) Compiler.