Skip to content

Latest commit

 

History

History
125 lines (87 loc) · 5.54 KB

README.md

File metadata and controls

125 lines (87 loc) · 5.54 KB

Metodo Montecarlo

Benchmarking, tra Python, Ruby, Nodejs, Golang, Java e Rust, per la risoluzione del valore di $\Pi$ utilizzando il metodo Monte Carlo.

Prerequisiti

Devono essere installati:

  • Python ver. 3.12.4 o successiva
  • Ruby ver. 3.3.5 o successiva
  • Nodejs ver. 20.18.0 o successiva
  • Golang ver. 1.22.4 o successiva
  • Rust ver. 1.82.0 o successiva
  • Java ver. 1.8.0_422 o successiva

Confronto efficienza

Utilizzando Python, Ruby, Nodejs, Golang, Java e Rust sono stati implementati quattro script con lo stesso algoritmo di risoluzione del valore di $\Pi$: per nessuno di essi è stato utilizzato parallelismi o multithreading per ottimizzazione delle prestazioni. Alla fine dell'esecuzione, ogni script restituisce il tempo complessivo dell'elaborazione.

Esecuzione

E' possibile eseguire tutti gli script in seguenza, tramite lo script run.sh <numero interazioni> o run.bat <numero interazioni>, oppure eseguirli singolarmente con:

  • Python

    export PI_SIMULATIONS=<numero interazione>
    python3 ./PY/main.py
  • Ruby

    export PI_SIMULATIONS=<numero interazione>
    ruby ./RB/main.rb
  • Nodejs

    export PI_SIMULATIONS=<numero interazione>
    node ./JS/index.js
  • Go

    go build -o ./GO/main ./GO/main.go
    export PI_SIMULATIONS=<numero interazione>
    ./GO/main
  • Rust

    cd RS
    cargo build --release -q
    export PI_SIMULATIONS=<numero interazione>
    ./target/release/main
  • Java

    cd JV
    javac ./Main.java
    export PI_SIMULATIONS=<numero interazione>
    java Main && cd ..
    ``` ```

Hyperfine

Per eseguire ./hyperfine.sh, si deve installare il binario: Hyperfine installation

Risultati

Utilizzando un Intel® Core™ i5-6500 e 32Gb i risultati, misurati in secondi, sono:

ver. 1.000 5.000 1.000.000 5.000.000
Python 3.12.4 0,00017
[739,13%]
0,000806
[680,92%]
0,171172
[1022,83%]
0,871845
[936,66%]
Ruby 3.3.5 0,003380644
[14698,45%]
0,01664606
[14062,85%]
3,185276161
[19033,5%]
16,004425921
[17194,31%]
Nodejs 20.18.0 * 0,001
[844,81%]
0,03
[179,26%]
0,135
[145,03%]
Golang 1.22.4 0,000023
[100%]
0,000132
[111,51%]
0,022069
[131,87%]
0,119983
[128,9%]
Rust 1.82.0 0,000030641
[133,22%]
0,000118369
[100%]
0,016735104
[100%]
0,093079769
[100%]
Java 1.8.0_422 0,001604
[6973,91%]
0,004325
[3653,82%]
0,050392
[301,11%]
0,224448
[241,13%]

Utilizzando un Apple® M2 e 16Gb i risultati, misurati in secondi, sono:

ver. 1.000 5.000 1.000.000 5.000.000
Python 3.12.4 0,000101
[721,43%]
0,000489
[444,55%]
0,100177
[778,62%]
0,529444
[788,34%]
Ruby 3.3.5 0,000484
[3457,15%]
0,002548
[2316,37%]
0,545488
[4239,77%]
2,631342
[3918,02%]
Nodejs 20.18.0 * 0,001
[909,1%]
0,036
[279,81%]
0,11
[163,79%]
Golang 1.22.4 0,000014
[100%]
0,000182
[165,46%]
0,012866
[100%]
0,06716
[100%]
Rust 1.82.0 0,000025167
[179,77%]
0,00011
[100%]
0,022051792
[171,4%]
0,115934333
[172,63%]
Java 17.0.12 0,000559
[3992,86%]
0,000761
[691,82%]
0,042703
[331,91%]
0,221541
[329,88%]

* Nodejs non misura frazioni del millisecondo

Algoritmo per risoluzione $\Pi$

Il metodo "Monte Carlo" è una stategia di risoluzione di problemi che utilizza la statistica: se la probabilità di un certo evento è P possiamo simulare in maniera random questo evento e ottenere P facendo:

P = (numero di volte in cui il nostro evento è avvenuto)/(simulazioni totali).

Vediamo come applicare questa strategia per ottenere un'approssimazione di pi greco $\Pi$.

Data un cerchio di raggio 1, esso può essere inscritto in un quadrato di lato 2.

Guardiamo solamente ad uno spicchio del cerchio:

PI_greco

In questo modo sappiamo che l'area del quadrato in blu è 1 e l'area dell'area rossa invece è $\Pi$/4.

Se generiamo N numeri random all'interno del quadrato il numero di punti che cadono nel cerchio M diviso il numero totale di numeri generati N dovrà approssimare appunto l'area del cerchio e quindi $\Pi$/4.

In sostanza otterremo $\Pi$ = 4 * M / N.

Maggiore sarà il numero di punti generati più precisa sarà l'approssimazione di $\Pi$.

Chiaramente ogni esecuzione darà un valore leggermente diverso ma aumentando il numero di punti possiamo "stabilizzare" un numero di cifre decimali a piacere. Osserviamo come l'implementazione del random sia determinante per questo calcolo: se i double non fossero generati in maniera uniforme tra 0 e 1 il valore di pi risulterebbe sbagliato!