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:
function 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
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 @inbound
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:
using CSV
using CodecZlib
uncompressed = CSV.read("crsp_daily.csv", DataFrame);
compressed = CSV.read(GzipDecompressorStream(open("crsp_daily.gz")), DataFrame)
Per la gestione di file di grandi dimensioni, R si dimostra il linguaggio più indicato, MATLAB quello meno efficiente.
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:
using Statistics
using DataFrames
R = combine(groupby(data, [:year, :PERMNO]),
:RET => mean => :m, :RET => std => :s, nrow => :c)
I risultati mostrano Julia al primo posto (assegniamo valore 1), seguito da Python con 1,18, MATLAB il peggiore con 4,62.
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.