Parallelizza generazione run su più processi CPU

Ogni run usa un seme RNG indipendente derivato dal seed globale, così
l'esecuzione su ProcessPoolExecutor resta riproducibile.
This commit is contained in:
2026-07-06 11:38:25 +02:00
parent 4d83ac4e70
commit 288ae81b3e
2 changed files with 26 additions and 6 deletions
+4
View File
@@ -53,6 +53,10 @@ SIMULAZIONE = {
# Cartella di output. # Cartella di output.
"cartella_output": "dataset", "cartella_output": "dataset",
# Numero di processi paralleli per la generazione dei run.
# None = usa tutti i core disponibili.
"num_processi": None,
} }
FASCETTA = { FASCETTA = {
+22 -6
View File
@@ -1,7 +1,9 @@
import csv import csv
import math import math
import os
import random import random
import shutil import shutil
from concurrent.futures import ProcessPoolExecutor
from copy import deepcopy from copy import deepcopy
from pathlib import Path from pathlib import Path
@@ -442,19 +444,33 @@ def simula_singolo(cfg_run: dict, output_csv: Path, rng: random.Random) -> dict:
} }
def _esegui_run(indice_e_seme: tuple[int, int]) -> dict:
# Ogni run riceve un seme indipendente derivato dal seed globale, così
# l'esecuzione in parallelo resta riproducibile indipendentemente
# dall'ordine in cui i processi la completano.
indice, seme = indice_e_seme
rng = random.Random(seme)
cfg_run = configurazione_randomizzata(indice, rng)
cartella_output = Path(SIMULAZIONE["cartella_output"])
percorso_csv = cartella_output / f"{cfg_run['id_run']}.csv"
return simula_singolo(cfg_run, percorso_csv, rng)
def main() -> None: def main() -> None:
cartella_output = Path(SIMULAZIONE["cartella_output"]) cartella_output = Path(SIMULAZIONE["cartella_output"])
if cartella_output.exists(): if cartella_output.exists():
shutil.rmtree(cartella_output) shutil.rmtree(cartella_output)
cartella_output.mkdir(parents=True, exist_ok=True) cartella_output.mkdir(parents=True, exist_ok=True)
rng = random.Random(SIMULAZIONE["seed"]) rng_semi = random.Random(SIMULAZIONE["seed"])
num_run = SIMULAZIONE["num_run"]
semi = [rng_semi.randrange(2**63) for _ in range(num_run)]
righe_metadata = [] num_processi = SIMULAZIONE["num_processi"] or os.cpu_count() or 1
for i in range(1, SIMULAZIONE["num_run"] + 1): with ProcessPoolExecutor(max_workers=num_processi) as executor:
cfg_run = configurazione_randomizzata(i, rng) righe_metadata = list(
percorso_csv = cartella_output / f"{cfg_run['id_run']}.csv" executor.map(_esegui_run, enumerate(semi, start=1))
righe_metadata.append(simula_singolo(cfg_run, percorso_csv, rng)) )
percorso_metadata = cartella_output / "metadata.csv" percorso_metadata = cartella_output / "metadata.csv"
with percorso_metadata.open("w", newline="") as f: with percorso_metadata.open("w", newline="") as f: