Het meten van de ecologische voetafdruk van uw code met CodeCarbon
Elke keer dat u een machine learning-model traint, voert u een ETL-pijplijn uit of draait u een batchtaak 's Nachts verbruik je energie. Die energie heeft reële CO2-kosten, die afhangen van waar en wanneer je rent de code. De ICT-sector als geheel is verantwoordelijk voor de 2-4% van de mondiale uitstoot van CO₂, een aandeel dat vergelijkbaar is met dat van de gehele mondiale luchtvaartindustrie. Maar een In tegenstelling tot een vlucht zijn software-emissies vrijwel altijd onzichtbaar.
GPT-3-training produceerde ca 552 ton CO₂, wat overeenkomt met 300 ritten retourvlucht New York-San Francisco per vliegtuig. Een verfijning van BERT-large op een A100 GPU gedurende 10 uur Duitsland (energiemix van ~381 gCO₂/kWh) stoot ca 1,2 kg CO₂. Dezelfde training die naar Frankrijk is verhuisd (nucleair, ~56 gCO₂/kWh) produceert alleen maar 177 gram. Het verschil is bijna 7 keer, voor dezelfde code.
CodeCarbon is de open source tool die deze uitstoot meetbaar maakt vergelijkbaar. Met een paar regels Python kun je de ecologische voetafdruk van elk proces volgen computationeel, van het enkele ML-experiment tot de productiepijplijn, en integreer deze statistieken in uw MLflow-workflows, ESG-rapporten en CI/CD-pijplijnen.
Wat je gaat leren
- Interne architectuur van CodeCarbon: hoe het energie meet en de CO₂-uitstoot berekent
- Opstelling met
EmissionsTrackereOfflineEmissionsTracker - Tracking bij het trainen van TensorFlow- en PyTorch-modellen
- GPU-meting met CUDA en NVML voor NVIDIA-hardware
- Configuratie voor verschillende Europese landen en koolstofintensiteit op het elektriciteitsnet
- Integratie met MLflow voor emissies als experimentstatistieken
- Dashboard met matplotlib en plotly voor trendvisualisatie
- Cloud Carbon Footprint om de uitstoot op AWS, GCP en Azure te schatten
- Toolvergelijking: CodeCarbon versus Eco2AI versus CarbonTracker versus ML CO2 Impact
- Real case study: NLP-trainingsoptimalisatie met 96% vermindering van de uitstoot
Green Software Series: 10 artikelen voor het ontwikkelen van duurzame software
| # | Item | Onderwerp | Staat |
|---|---|---|---|
| 1 | Principes van de Green Software Foundation | GSF, SCI, 8 fundamentele principes | Beschikbaar |
| 2 | Het meten van uw ecologische voetafdruk met CodeCarbon | Meting, tracking, dashboard | Huidig artikel |
| 3 | Integreer de Climatiq-API | Berekeningen van het broeikasgasprotocol, scope 1-3 | Beschikbaar |
| 4 | Koolstofbewuste SDK | Tijdverschuiving, locatieverschuiving | Beschikbaar |
| 5 | Scope 1, 2 en 3: ESG-gegevensmodellering | Gegevensstructuur, berekeningen, aggregatie | Beschikbaar |
| 6 | GreenOps met Kubernetes | Koolstofbewuste planning, infrastructuur | Beschikbaar |
| 7 | Pipeline Scope 3 Waardeketen | Leveranciersgegevens, audittrail | Beschikbaar |
| 8 | ESG-rapportage en CSRD API | Europese compliance, automatisering | Beschikbaar |
| 9 | Duurzame architecturale patronen | Opslag, cache, koolstofbewuste batch | Beschikbaar |
| 10 | AI en Carbon: ML-trainingsvoetafdruk | Groene AI, trainingsoptimalisatie | Beschikbaar |
CodeCarbon: architectuur en bedieningsmechanisme
CodeCarbon is een open-source Python-bibliotheek ontwikkeld door een samenwerking tussen Mila Quebec AI Institute, Carnegie Mellon University, Comet.ml en BCG GAMMA. Het project werd in 2020 geboren met als doel het meten van code-emissies toegankelijk voor elke datawetenschapper, zonder dat daarvoor speciale hardwareapparatuur nodig is.
Het werkingsprincipe is gebaseerd op een fundamentele formule:
CodeCarbon centrale formule
Uitgestoten CO₂ [kg] = Verbruikte energie [kWh] × Koolstofintensiteit van het netwerk [kgCO₂/kWh]
De verbruikte energie wordt component voor component gemeten (GPU + CPU + RAM), terwijl de koolstofintensiteit wordt opgehaald uit databases die per land/regio zijn bijgewerkt of handmatig verstrekt voor offline omgevingen.
Interne meetpijpleiding
CodeCarbon meet elke keer het energieverbruik 15 seconden (configureerbaar) door een pijplijn met meerdere niveaus. Bij elke bemonstering meet het het momentane vermogen van de CPU, GPU en RAM, integreer in de loop van de tijd om kWh te krijgen, en vermenigvuldig dit met de emissiefactor van het land.
Hiërarchie van energiemetingen
| Onderdeel | Meetmethode | Precisie | Beschikbaarheid |
|---|---|---|---|
| NVIDIA GPU's | NVML via pynvml (NVIDIA Management Library) | Hoog (directe meting) | Alleen NVIDIA GPU's met stuurprogramma's |
| Intel-CPU | RAPL (Running Average Power Limit) via pyRAPL | Hoog (hardwaresensoren) | Linux met MSR-toegang, Intel |
| AMD/ARM-CPU's | Geschatte TDP + gebruikspercentage | Gemiddeld (schatting) | Alle systemen |
| RAM | Empirische formule: 3W per 8GB | Laag-medium (schatting) | Alle systemen |
| AMD GPU's | ROCm SMI (indien beschikbaar) | Hoog (directe meting) | AMD GPU met ROCm |
Koolstofintensiteit per land
Om kWh naar kgCO₂ te vertalen, maakt CodeCarbon gebruik van een hiërarchische database van emissiefactoren. In de onlinemodus kunt u gegevens ophalen via IP-geolocatie. In de offlinemodus, maakt gebruik van een interne database met jaarlijkse gemiddelde waarden voor meer dan 240 landen.
Koolstofintensiteit per Europees land (2024)
| Dorp | gCO₂/kWh | Belangrijkste energiemix | ISO-code |
|---|---|---|---|
| Noorwegen | ~28 | Hydro-elektrisch (90%) | NOCH |
| Frankrijk | ~56 | Nucleair (70%) | TUSSEN |
| Zweden | ~45 | Kernenergie + waterkracht | ZWE |
| Spanje | ~191 | Hernieuwbare energie + gas | EXP |
| Italië | ~233 | Aardgas + Hernieuwbare energiebronnen | ITA |
| Duitsland | ~381 | Gas + Kolen + Wind | DEU |
| Polen | ~640 | Steenkool (70%) | POL |
Installatie en installatie van CodeCarbon
Voor het installeren van CodeCarbon is Python 3.7+ vereist en is beschikbaar op PyPI en conda. Voor GPU-tracking heb je NVIDIA-stuurprogramma's en het pynvml-pakket nodig.
Installatie
# Installazione base
pip install codecarbon
# Con dipendenze per visualizzazione dashboard
pip install codecarbon[viz]
# Per ambienti conda
conda install -c conda-forge codecarbon
# Verifica installazione
python -c "from codecarbon import EmissionsTracker; print('CodeCarbon OK')"
# Controlla quale hardware viene rilevato
python -c "
import pynvml
try:
pynvml.nvmlInit()
count = pynvml.nvmlDeviceGetCount()
for i in range(count):
h = pynvml.nvmlDeviceGetHandleByIndex(i)
print(f'GPU {i}: ', pynvml.nvmlDeviceGetName(h))
pynvml.nvmlShutdown()
except Exception as e:
print(f'GPU non rilevata: {e}')
print('CodeCarbon usera stima TDP per CPU')
"
Configuratiebestand .codecarbon.config
CodeCarbon ondersteunt een projectbreed INI-configuratiebestand dat herhaling vermijdt
de parameters in elk script. Maak een bestand .codecarbon.config in de projectroot:
# .codecarbon.config
[codecarbon]
# Modalità: online (default) o offline
mode = online
# Paese ISO 3166-1 alpha-3 per carbon intensity
country_iso_code = ITA
# Intervallo di campionamento in secondi (default: 15)
measure_power_secs = 15
# File di output CSV
output_file = emissions.csv
# Directory output
output_dir = ./carbon_reports
# Log level: DEBUG, INFO, WARNING, ERROR
log_level = INFO
# Salva su CodeCarbon cloud dashboard (richiede API key)
save_to_api = false
# Modalità di tracking
tracking_mode = process
EmissionsTracker: drie gebruiksmodi
from codecarbon import EmissionsTracker
from codecarbon import track_emissions
import time
# ===== MODALITA 1: Context Manager (raccomandato) =====
with EmissionsTracker(
project_name="my-ml-project",
output_dir="./carbon_reports",
country_iso_code="ITA",
log_level="INFO"
) as tracker:
print("Training in corso...")
time.sleep(5) # Simula training
print(f"Emissioni: {tracker.final_emissions:.6f} kgCO2eq")
print(f"Energia: {tracker.final_emissions_data.energy_consumed:.4f} kWh")
# ===== MODALITA 2: Start/Stop Espliciti =====
tracker = EmissionsTracker(
project_name="batch-job",
output_file="batch_emissions.csv",
measure_power_secs=10
)
tracker.start()
print("Preprocessing...")
time.sleep(3)
tracker.flush() # Checkpoint senza fermare il tracking
print("Training...")
time.sleep(5)
emissions = tracker.stop()
print(f"CO2 emessa: {emissions:.6f} kgCO2eq")
# ===== MODALITA 3: Decorator =====
@track_emissions(
project_name="inference-pipeline",
country_iso_code="FRA",
output_dir="./carbon_reports"
)
def run_inference(model, data):
return model.predict(data)
OfflineEmissionsTracker: voor omgevingen zonder internet
Gebruik in HPC-clusters, productiecontainers of machines zonder internettoegang
OfflineEmissionsTracker. De ISO-landcode wordt verplicht.
from codecarbon import OfflineEmissionsTracker
tracker = OfflineEmissionsTracker(
country_iso_code="ITA", # Obbligatorio in modalità offline
project_name="hpc-training",
output_dir="/results/carbon",
measure_power_secs=30, # Meno frequente per ridurre overhead
log_level="WARNING"
)
tracker.start()
try:
run_training_pipeline()
except Exception as e:
print(f"Errore: {e}")
raise
finally:
# Chiama sempre stop() anche in caso di errore
emissions = tracker.stop()
if emissions:
print(f"[Carbon] {emissions:.4f} kgCO2eq")
# Override carbon intensity manuale (es: data center con energia 100% rinnovabile)
tracker_custom = OfflineEmissionsTracker(
country_iso_code="ITA",
# Specifica intensità carbonica del tuo fornitore (es: 20 gCO2/kWh)
# mediante variabile ambiente CODECARBON_CARBON_INTENSITY=0.020
measure_power_secs=15
)
Emissies volgen in machine learning-projecten
Het primaire gebruiksscenario van CodeCarbon is tracking bij het trainen van ML-modellen. Laten we praktische voorbeelden bekijken met PyTorch en TensorFlow/Keras.
PyTorch-training met Full Carbon Tracking
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from codecarbon import EmissionsTracker
import numpy as np
import json
from datetime import datetime
class TextClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, num_classes):
super(TextClassifier, self).__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, 128, batch_first=True, bidirectional=True)
self.classifier = nn.Sequential(
nn.Linear(256, 64),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(64, num_classes)
)
def forward(self, x):
embedded = self.embedding(x)
lstm_out, _ = self.lstm(embedded)
pooled = lstm_out.mean(dim=1)
return self.classifier(pooled)
def train_with_carbon_tracking(model, train_loader, val_loader, epochs=10, country="ITA"):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
optimizer = optim.AdamW(model.parameters(), lr=2e-4, weight_decay=0.01)
criterion = nn.CrossEntropyLoss()
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)
training_history = []
tracker = EmissionsTracker(
project_name=f"text-classifier-{datetime.now().strftime('%Y%m%d_%H%M')}",
output_dir="./carbon_reports",
country_iso_code=country,
log_level="WARNING",
measure_power_secs=15
)
tracker.start()
gpu_name = torch.cuda.get_device_name(0) if torch.cuda.is_available() else "N/A"
print(f"Dispositivo: {device} | GPU: {gpu_name} | Paese: {country}")
for epoch in range(epochs):
# Training
model.train()
train_loss, correct, total = 0.0, 0, 0
for X, y in train_loader:
X, y = X.to(device), y.to(device)
optimizer.zero_grad()
out = model(X)
loss = criterion(out, y)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
train_loss += loss.item()
correct += out.argmax(1).eq(y).sum().item()
total += y.size(0)
# Validation
model.eval()
val_correct, val_total = 0, 0
with torch.no_grad():
for X, y in val_loader:
X, y = X.to(device), y.to(device)
out = model(X)
val_correct += out.argmax(1).eq(y).sum().item()
val_total += y.size(0)
scheduler.step()
stats = {
"epoch": epoch + 1,
"train_acc": 100. * correct / total,
"val_acc": 100. * val_correct / val_total,
"train_loss": train_loss / len(train_loader),
}
training_history.append(stats)
print(f"Epoch {epoch+1}/{epochs} | "
f"Train: {stats['train_acc']:.2f}% | Val: {stats['val_acc']:.2f}%")
total_emissions = tracker.stop()
em_data = tracker.final_emissions_data
final_val_acc = training_history[-1]["val_acc"]
print(f"\n=== CARBON REPORT ===")
print(f"CO2 totale: {total_emissions:.6f} kgCO2eq")
print(f"Per epoch: {total_emissions / epochs * 1000:.2f} gCO2eq")
if em_data:
print(f"Energia: {em_data.energy_consumed:.4f} kWh")
print(f"Val accuracy: {final_val_acc:.2f}%")
if total_emissions:
print(f"Efficienza: {final_val_acc / (total_emissions * 1000):.2f} acc/gCO2")
results = {
"model": "TextClassifier-BiLSTM",
"epochs": epochs,
"final_val_accuracy": final_val_acc,
"total_co2_kg": total_emissions,
"country": country,
"training_history": training_history
}
with open("./carbon_reports/training_results.json", "w") as f:
json.dump(results, f, indent=2)
return results
if __name__ == "__main__":
X = torch.randint(0, 1000, (2000, 128))
y = torch.randint(0, 3, (2000,))
dataset = TensorDataset(X, y)
train_ds, val_ds = torch.utils.data.random_split(dataset, [1600, 400])
train_loader = DataLoader(train_ds, batch_size=32, shuffle=True)
val_loader = DataLoader(val_ds, batch_size=64)
model = TextClassifier(vocab_size=1000, embed_dim=64, num_classes=3)
train_with_carbon_tracking(model, train_loader, val_loader, epochs=5, country="ITA")
Keras-callback voor TensorFlow
import tensorflow as tf
from tensorflow import keras
from codecarbon import EmissionsTracker
import numpy as np
class CarbonTrackingCallback(keras.callbacks.Callback):
"""Callback Keras che integra CodeCarbon per il reporting per epoch."""
def __init__(self, tracker: EmissionsTracker):
super().__init__()
self.tracker = tracker
def on_epoch_end(self, epoch, logs=None):
logs = logs or {}
val_acc = logs.get('val_accuracy', 0)
print(f"\n [Carbon] Epoch {epoch+1} | Val accuracy: {val_acc:.4f}")
def train_keras_with_carbon():
vocab_size, max_len = 10000, 200
model = keras.Sequential([
keras.layers.Embedding(vocab_size, 128, input_length=max_len),
keras.layers.Bidirectional(keras.layers.LSTM(64, return_sequences=True)),
keras.layers.GlobalMaxPooling1D(),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.3),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(
optimizer=keras.optimizers.Adam(3e-4),
loss='binary_crossentropy',
metrics=['accuracy']
)
X_train = np.random.randint(0, vocab_size, (8000, max_len))
y_train = np.random.randint(0, 2, (8000,))
X_val = np.random.randint(0, vocab_size, (2000, max_len))
y_val = np.random.randint(0, 2, (2000,))
with EmissionsTracker(
project_name="keras-sentiment",
output_dir="./carbon_reports",
country_iso_code="ITA",
log_level="WARNING"
) as tracker:
history = model.fit(
X_train, y_train,
validation_data=(X_val, y_val),
epochs=10,
batch_size=64,
callbacks=[
CarbonTrackingCallback(tracker),
keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True),
keras.callbacks.ReduceLROnPlateau(factor=0.5, patience=2)
],
verbose=1
)
print(f"\nEmissioni totali: {tracker.final_emissions:.6f} kgCO2eq")
print(f"Val accuracy: {max(history.history['val_accuracy']):.4f}")
return model, tracker.final_emissions
train_keras_with_carbon()
GPU-tracking: nauwkeurige metingen met NVIDIA NVML
Voor GPU-intensieve workloads gebruikt CodeCarbon pynvml, de Python-binding van de NVIDIA Management Library (NVML), om het directe energieverbruik in watt te meten. Dit is de meest nauwkeurige methode die beschikbaar is, met een resolutie van 1-5 watt.
import pynvml
from codecarbon import EmissionsTracker
import torch
def inspect_gpu_power():
"""Ispezione diretta del consumo GPU con NVML (come fa CodeCarbon internamente)."""
pynvml.nvmlInit()
count = pynvml.nvmlDeviceGetCount()
print(f"GPU rilevate: {count}")
for i in range(count):
h = pynvml.nvmlDeviceGetHandleByIndex(i)
name = pynvml.nvmlDeviceGetName(h)
power_w = pynvml.nvmlDeviceGetPowerUsage(h) / 1000 # mW -> W
limit_w = pynvml.nvmlDeviceGetEnforcedPowerLimit(h) / 1000
mem = pynvml.nvmlDeviceGetMemoryInfo(h)
print(f" GPU {i}: {name}")
print(f" Consumo: {power_w:.1f}W / {limit_w:.0f}W (TDP)")
print(f" VRAM: {mem.used / 1e9:.1f}GB / {mem.total / 1e9:.1f}GB")
pynvml.nvmlShutdown()
def train_on_gpu_with_tracking():
"""Training su GPU con tracking dettagliato del consumo."""
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
tracker = EmissionsTracker(
project_name="gpu-intensive-run",
output_dir="./carbon_reports",
country_iso_code="ITA",
gpu_ids=[0], # Monitora solo GPU 0
measure_power_secs=5, # Alta frequenza per run brevi
log_level="DEBUG" # Mostra dettagli misurazione
)
tracker.start()
print(f"Dispositivo: {device}")
# Workload GPU intensivo: matrix multiplication
for step in range(100):
a = torch.randn(256, 1024, device=device)
b = torch.randn(1024, 1024, device=device)
c = torch.matmul(a, b)
loss = c.mean()
loss.backward()
if step % 25 == 0:
print(f"Step {step}/100 | Loss: {loss.item():.4f}")
emissions = tracker.stop()
data = tracker.final_emissions_data
print(f"\n=== GPU CARBON REPORT ===")
print(f"Emissioni: {emissions:.6f} kgCO2eq")
if data:
print(f"Energia: {data.energy_consumed:.4f} kWh")
return emissions
inspect_gpu_power()
train_on_gpu_with_tracking()
Beperkingen van GPU-tracking
- Alleen NVIDIA met CUDA: AMD GPU's vereisen ROCm; Intel Arc wordt niet ondersteund
- Niet-bevoorrechte Docker-containers: NVML heeft mogelijk geen toegang tot stuurprogramma's;
voeg de vlag toe
--privilegedof monteren/dev/nvidia* - Cloud-VM's: Op EC2/GCE/Azure NVML-instanties is het mogelijk dat het werkelijke verbruik niet zichtbaar is; gebruik Cloud Carbon Footprint voor cloudschattingen
- RAPL op CPU: Op Linux is toegang vereist tot
/sys/class/powercap/; op macOS en Windows gebruik TDP-schatting - Algemene nauwkeurigheid: Recent onderzoek (2025) geeft aan dat schattingsinstrumenten ze kunnen fouten tot 40% bevatten; gebruik de gegevens als een orde van grootte, niet als een absolute maatstaf
Integratie met MLflow: emissies als experimentstatistieken
Door CodeCarbon te integreren met MLflow kunt u naast de meetgegevens ook de CO₂-uitstoot registreren van het model (nauwkeurigheid, verlies, F1). De CO2-voetafdruk wordt een modelselectiecriterium precies zoals voorspellende prestaties.
import mlflow
import mlflow.pytorch
from codecarbon import EmissionsTracker
import torch
import torch.nn as nn
from datetime import datetime
def train_with_mlflow_carbon(
model_config: dict,
train_loader,
val_loader,
country: str = "ITA",
experiment_name: str = "carbon-aware-experiments"
):
"""Training con logging doppio: MLflow per metriche, CodeCarbon per CO2."""
mlflow.set_experiment(experiment_name)
with mlflow.start_run(run_name=f"run-{datetime.now().strftime('%H%M%S')}") as run:
# Log iperparametri
mlflow.log_params({
"model_type": model_config.get("type", "unknown"),
"learning_rate": model_config.get("lr", 1e-3),
"batch_size": model_config.get("batch_size", 32),
"epochs": model_config.get("epochs", 10),
"country": country
})
# Avvia tracking CO2
tracker = EmissionsTracker(
project_name=f"mlflow-{run.info.run_id[:8]}",
output_dir="./carbon_reports",
country_iso_code=country,
log_level="WARNING"
)
tracker.start()
# Training loop
model = build_model(model_config)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
opt = torch.optim.Adam(model.parameters(), lr=model_config.get("lr", 1e-3))
crit = nn.CrossEntropyLoss()
epochs = model_config.get("epochs", 10)
best_val_acc = 0.0
for epoch in range(epochs):
# Train
model.train()
train_loss, correct, total = 0.0, 0, 0
for X, y in train_loader:
X, y = X.to(device), y.to(device)
opt.zero_grad()
out = model(X)
loss = crit(out, y)
loss.backward()
opt.step()
train_loss += loss.item()
correct += out.argmax(1).eq(y).sum().item()
total += y.size(0)
# Validation
model.eval()
val_c, val_t = 0, 0
with torch.no_grad():
for X, y in val_loader:
X, y = X.to(device), y.to(device)
val_c += model(X).argmax(1).eq(y).sum().item()
val_t += y.size(0)
train_acc = correct / total
val_acc = val_c / val_t
best_val_acc = max(best_val_acc, val_acc)
mlflow.log_metrics({
"train_accuracy": train_acc,
"val_accuracy": val_acc,
"train_loss": train_loss / len(train_loader),
}, step=epoch)
# Log metriche CO2 al termine del training
total_emissions = tracker.stop()
em_data = tracker.final_emissions_data
carbon_metrics = {
"co2_kg": total_emissions or 0.0,
"best_val_accuracy": best_val_acc,
"carbon_efficiency": best_val_acc / (total_emissions * 1000) if total_emissions else 0.0,
}
if em_data:
carbon_metrics["energy_kwh"] = em_data.energy_consumed or 0.0
mlflow.log_metrics(carbon_metrics)
mlflow.set_tags({
"carbon_tracked": "true",
"country": country,
"hardware": "gpu" if torch.cuda.is_available() else "cpu"
})
mlflow.pytorch.log_model(model, "model")
print(f"\n=== Run {run.info.run_id} ===")
print(f"Best Val Acc: {best_val_acc:.4f}")
print(f"CO2 emessa: {total_emissions:.6f} kgCO2eq")
print(f"Carbon Efficiency: {carbon_metrics['carbon_efficiency']:.2f} acc/gCO2")
return {
"run_id": run.info.run_id,
"best_val_acc": best_val_acc,
"co2_kg": total_emissions,
"carbon_efficiency": carbon_metrics["carbon_efficiency"]
}
def build_model(config: dict) -> nn.Module:
h = config.get("hidden_size", 128)
return nn.Sequential(
nn.Linear(config.get("input_size", 784), h),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(h, config.get("num_classes", 10))
)
mlflow-emissions-sdk: native integratie
Dataroots heeft een speciaal pakket ontwikkeld dat MLflow uitbreidt met native ondersteuning voor CodeCarbon,
het verzorgen van de klas EmissionsTrackerMlflow die automatisch de emissies registreert
in de levenscyclus van een MLflow-uitvoering.
pip install mlflow-emissions-sdk
from mlflow_emissions_sdk.tracker import EmissionsTrackerMlflow
import mlflow
with mlflow.start_run():
with EmissionsTrackerMlflow(country_iso_code="ITA") as tracker:
# Le emissioni vengono loggato automaticamente su MLflow
run_training()
# Metriche disponibili nel run MLflow dopo il context manager
Dashboard- en emissievisualisatie
CodeCarbon genereert een CSV-bestand met alle metingen. U kunt aangepaste dashboards bouwen met plotly of matplotlib om trends te analyseren, experimenten te vergelijken en ESG-rapporten op te stellen.
Structuur van de uitvoer-CSV
Hoofdvelden van de CodeCarbon CSV
| Veld | Eenheid | Beschrijving |
|---|---|---|
timestamp |
ISO8601 | Meetmoment |
project_name |
- | Projectnaam |
duration |
seconden | Totale trackingduur |
emissions |
kgCO₂-eq | Totale uitstoot |
cpu_energy |
kWh | CPU-energie |
gpu_energy |
kWh | GPU-energie |
ram_energy |
kWh | RAM-energie |
energy_consumed |
kWh | Totale energie (CPU+GPU+RAM) |
carbon_intensity |
kgCO₂/kWh | Koolstofintensiteit gebruikt |
country_name |
- | Land van uitvoering |
gpu_model |
- | GPU-model gedetecteerd |
Dashboard met plot en statisch rapport met Matplotlib
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import matplotlib.pyplot as plt
def load_emissions_data(csv_path: str = "./carbon_reports/emissions.csv") -> pd.DataFrame:
df = pd.read_csv(csv_path)
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['emissions_g'] = df['emissions'] * 1000 # kgCO2 -> gCO2
df['duration_min'] = df['duration'] / 60
return df
def create_plotly_dashboard(df: pd.DataFrame, output_path: str = "./carbon_dashboard.html"):
fig = make_subplots(
rows=2, cols=2,
subplot_titles=[
"Emissioni CO2 per Run (gCO2eq)",
"Breakdown Energetico Medio",
"Emissioni per Progetto (Totale)",
"CO2 Cumulativa nel Tempo"
],
specs=[
[{"type": "bar"}, {"type": "pie"}],
[{"type": "bar"}, {"type": "scatter"}]
]
)
# 1. Bar chart emissioni per run
fig.add_trace(
go.Bar(x=df['project_name'], y=df['emissions_g'],
name="CO2 (g)", marker_color='#e74c3c',
text=df['emissions_g'].round(3), textposition='auto'),
row=1, col=1
)
# 2. Pie chart breakdown energetico
breakdown = {
'CPU': df['cpu_energy'].mean(),
'GPU': df['gpu_energy'].fillna(0).mean(),
'RAM': df['ram_energy'].mean()
}
fig.add_trace(
go.Pie(labels=list(breakdown.keys()), values=list(breakdown.values()),
marker_colors=['#3498db', '#e67e22', '#2ecc71']),
row=1, col=2
)
# 3. Emissioni aggregate per progetto
proj = df.groupby('project_name')['emissions_g'].sum().reset_index()
fig.add_trace(
go.Bar(x=proj['project_name'], y=proj['emissions_g'],
marker_color='#9b59b6'),
row=2, col=1
)
# 4. Trend cumulativo
df_s = df.sort_values('timestamp')
fig.add_trace(
go.Scatter(x=df_s['timestamp'], y=df_s['emissions_g'].cumsum(),
mode='lines+markers', line=dict(color='#e74c3c', width=2),
fill='tozeroy', fillcolor='rgba(231,76,60,0.1)'),
row=2, col=2
)
fig.update_layout(
title="CodeCarbon Dashboard: Carbon Footprint del Progetto",
height=700, showlegend=False, template="plotly_dark"
)
fig.write_html(output_path)
print(f"Dashboard salvata in: {output_path}")
return fig
def create_matplotlib_report(df: pd.DataFrame, output_dir: str = "./carbon_reports"):
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle("Carbon Footprint Report - CodeCarbon", fontsize=16, fontweight='bold')
colors = ['#27ae60', '#2ecc71', '#a8e6cf', '#dcedc1']
# 1. Emissioni per progetto
proj = df.groupby('project_name')['emissions_g'].sum()
axes[0,0].bar(range(len(proj)), proj.values, color=colors[0])
axes[0,0].set_xticks(range(len(proj)))
axes[0,0].set_xticklabels(proj.index, rotation=30, ha='right', fontsize=9)
axes[0,0].set_ylabel("CO2 emessa (gCO2eq)")
axes[0,0].set_title("Emissioni per Progetto")
# 2. Breakdown energetico
ev = [df['cpu_energy'].mean()*1000, df['gpu_energy'].fillna(0).mean()*1000,
df['ram_energy'].mean()*1000]
axes[0,1].pie(ev, labels=['CPU','GPU','RAM'], autopct='%1.1f%%', colors=colors)
axes[0,1].set_title("Breakdown Energetico Medio")
# 3. Emissioni vs durata
axes[1,0].scatter(df['duration_min'], df['emissions_g'],
c=colors[0], alpha=0.7, s=80, edgecolors='white')
axes[1,0].set_xlabel("Durata run (minuti)")
axes[1,0].set_ylabel("Emissioni (gCO2eq)")
axes[1,0].set_title("Emissioni vs Durata Run")
# 4. Cumulativo
cumulative = df.sort_values('timestamp')['emissions_g'].cumsum()
axes[1,1].fill_between(range(len(cumulative)), cumulative, alpha=0.3, color=colors[0])
axes[1,1].plot(range(len(cumulative)), cumulative, color=colors[0], linewidth=2)
axes[1,1].set_xlabel("Numero run")
axes[1,1].set_ylabel("CO2 Cumulativa (gCO2eq)")
axes[1,1].set_title("Andamento Emissioni Cumulativo")
plt.tight_layout()
plt.savefig(f"{output_dir}/carbon_report.png", dpi=150, bbox_inches='tight')
plt.savefig(f"{output_dir}/carbon_report.pdf", bbox_inches='tight')
print("Report salvato in carbon_report.png e .pdf")
return fig
if __name__ == "__main__":
df = load_emissions_data("./carbon_reports/emissions.csv")
create_plotly_dashboard(df)
create_matplotlib_report(df)
Koolstofvoetafdruk van de cloud: uitstoot van cloudwerklasten
CodeCarbon meet de lokale uitstoot op de machine waarop de code draait. Voor gedistribueerde werklasten op cloud heb je een aanvullende tool nodig: Koolstofvoetafdruk van de cloud (CCF), open-sourceproject oorspronkelijk ontwikkeld door ThoughWorks.
CodeCarbon versus CO2-voetafdruk in de cloud
| Kenmerkend | CodeCarbon | Koolstofvoetafdruk in de cloud |
|---|---|---|
| Hoofddoel | Lokale/on-premise code | Werklast in de publieke cloud |
| Gegevensbron | Hardware Direct (NVML, RAPL) | Facturerings-API-cloudproviders |
| Cloudproviders | Elke hardware | AWS, GCP, Azure |
| Realtime | Ja (15-30 sec) | Nee (vertraagde factureringsgegevens) |
| Granulariteit | Per proces, per GPU | Per account, per regio, per service |
| Belichaamde koolstof (scope 3) | No | Ja (productieschatting) |
| Webdashboards | CSV + aangepast | Reageer-dashboard inbegrepen |
# Setup Cloud Carbon Footprint
git clone https://github.com/cloud-carbon-footprint/cloud-carbon-footprint.git
cd cloud-carbon-footprint
# Crea file .env da template
cp packages/cli/.env.template packages/cli/.env
# Configurazione AWS (aggiungi in .env):
# AWS_TARGET_ACCOUNT_ID=123456789012
# AWS_REGIONS=eu-west-1,eu-central-1
# AWS_USE_BILLING_DATA=true
# Configurazione GCP (aggiungi in .env):
# GCP_PROJECT_ID=my-project
# GCP_BIG_QUERY_TABLE=billing_export.gcp_billing_export_v1_*
npm install
# Stima emissioni dell'ultimo mese
npx ts-node packages/cli/src/index.ts \
--startDate 2025-02-01 \
--endDate 2025-02-28 \
--groupBy month \
--cloudProviderToSeed AWS
# Output in emissions.json con breakdown per servizio e regione
Toolvergelijking: CodeCarbon versus alternatieven
Het landschap van instrumenten voor het meten van de ecologische voetafdruk evolueert snel. Hier is een technische vergelijking van de meest gebruikte opties in 2025.
Volledige vergelijking
| Instrument | GPU | Offline | MLstroom | Nauwkeurigheid | Onderhoud |
|---|---|---|---|---|---|
| CodeCarbon | NVIDIA (NVML) | Sì | Via SDK | Middelhoog | Actief (2025) |
| Eco2AI | Beperkt | Sì | No | Gemiddeld | 2023 |
| Koolstof-tracker | Sì | Gedeeltelijk | No | Gemiddeld | 2022 |
| ML CO2-impact | Achting | N.v.t | No | Laag (schatting) | Webhulpmiddelen |
| PyRAPL | No | Sì | No | Hoog (Intel CPU) | 2021 |
| Koolstofbewuste SDK | N.v.t | No | No | N.v.t. (verschuivend) | Actief (GSF) |
Richtlijnen voor keuze
- CodeKoolstof: Toonaangevende keuze voor ML-training in Python op lokale of on-premise hardware. Uitstekende NVIDIA GPU-ondersteuning, MLflow-integratie, grote community.
- Koolstofvoetafdruk van de cloud: Voor CO2-kostenanalyse van cloudinfrastructuur. Aanvullend op CodeCarbon, geen vervanging.
- ML CO2-impactcalculator: Webtool voor snelle schattingen voordat u met de training begint. Handig in de planningsfase om hardware en cloudregio te kiezen.
- Koolstofbewuste SDK (GSF): Het meet de emissies niet, maar minimaliseert deze via tijd/locatie verschuiven. Gebruik het samen met CodeCarbon voor een complete strategie.
CI/CD-integratie met GitHub Actions
Systematische metingen worden pas echt nuttig als ze worden geautomatiseerd. Hier leest u hoe u CodeCarbon kunt integreren in een GitHub Actions-workflow met handhaving van het koolstofbudget.
# .github/workflows/carbon-tracking.yml
name: Carbon Footprint Tracking
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
carbon-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install codecarbon pandas
pip install -r requirements.txt
- name: Run training with carbon tracking
run: |
python scripts/train.py \
--country ITA \
--output-dir ./carbon_reports \
--epochs 5
env:
CODECARBON_LOG_LEVEL: WARNING
- name: Enforce carbon budget
run: |
python - <<'PYEOF'
import pandas as pd
import sys
df = pd.read_csv('./carbon_reports/emissions.csv')
total_g = df['emissions'].sum() * 1000
BUDGET_G = 100.0 # Budget massimo per run CI
print(f"Emissioni: {total_g:.2f}g | Budget: {BUDGET_G}g")
if total_g > BUDGET_G:
print(f"BUDGET SUPERATO: {total_g:.2f}g > {BUDGET_G}g")
sys.exit(1)
print(f"OK: {total_g/BUDGET_G*100:.1f}% del budget usato")
PYEOF
- name: Upload carbon reports
uses: actions/upload-artifact@v4
if: always()
with:
name: carbon-reports-${{ github.run_id }}
path: ./carbon_reports/
retention-days: 90
- name: Comment PR with carbon summary
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const csv = fs.readFileSync('./carbon_reports/emissions.csv', 'utf8');
const lines = csv.trim().split('\n');
const headers = lines[0].split(',');
const last = lines[lines.length - 1].split(',');
const idx = headers.indexOf('emissions');
const g = parseFloat(last[idx]) * 1000;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `### Carbon Report\n| Metrica | Valore |\n|---|---|\n| CO2 | ${g.toFixed(3)} gCO2eq |\n| Paese | ITA (233 gCO2/kWh) |`
});
Koolstofbudget en SCI (Software Koolstofintensiteit)
from codecarbon import EmissionsTracker
from dataclasses import dataclass
@dataclass
class CarbonBudget:
project_name: str
max_co2_per_run_g: float
max_co2_monthly_kg: float
def check_run(self, emissions_kg: float) -> bool:
g = emissions_kg * 1000
if g > self.max_co2_per_run_g:
print(f"BUDGET SUPERATO: {g:.2f}g > {self.max_co2_per_run_g}g")
return False
pct = g / self.max_co2_per_run_g * 100
print(f"Budget: {pct:.1f}% usato ({g:.2f}g / {self.max_co2_per_run_g}g)")
return True
BUDGETS = {
"research": CarbonBudget("research", max_co2_per_run_g=500, max_co2_monthly_kg=10),
"production": CarbonBudget("production", max_co2_per_run_g=50, max_co2_monthly_kg=2),
"ci": CarbonBudget("ci", max_co2_per_run_g=100, max_co2_monthly_kg=5),
}
def calculate_sci(emissions_kg: float, energy_kwh: float,
functional_unit: float, unit_desc: str = "prediction") -> dict:
"""
Calcola SCI (Software Carbon Intensity) secondo la specifica GSF:
SCI = CO2eq / R (functional unit)
"""
sci = emissions_kg / max(functional_unit, 1e-9)
return {
"sci": sci,
"sci_unit": f"kgCO2eq/{unit_desc}",
"co2_kg": emissions_kg,
"energy_kwh": energy_kwh,
"equiv_km_car": emissions_kg * 4.44, # ~225 gCO2/km
"equiv_iphone_charges": int(emissions_kg / 0.000008), # ~8 Wh per ricarica
}
def run_with_budget(training_fn, budget_name="production", country="ITA"):
budget = BUDGETS.get(budget_name, BUDGETS["research"])
with EmissionsTracker(
project_name=budget.project_name,
country_iso_code=country,
output_dir="./carbon_reports"
) as tracker:
result = training_fn()
em_kg = tracker.final_emissions
en_kwh = tracker.final_emissions_data.energy_consumed if tracker.final_emissions_data else 0
budget.check_run(em_kg)
n_preds = result.get("num_predictions", 1)
sci = calculate_sci(em_kg, en_kwh, n_preds)
print(f"SCI: {sci['sci']*1e6:.2f} microgCO2eq/prediction")
print(f"Equivalente a {sci['equiv_km_car']:.3f} km in auto")
return sci
Real Case Study: NLP-trainingsoptimalisatie met CodeCarbon
Een NLP-team trainde een sentimentclassificatiemodel voor productrecensies in het Italiaans. Het doel was om een nauwkeurigheid van meer dan 90% te bereiken. Voordat CodeCarbon werd geïntroduceerd, het trainingsproces was vanuit het oogpunt van de CO2-voetafdruk volkomen ondoorzichtig.
Beginsituatie (basislijn)
Basisconfiguratie
| Parameter | Basiswaarde | Geoptimaliseerde waarde |
|---|---|---|
| Model | BERT-groot-zonder behuizing (340M parameters) | DistilBERT meertalig (66M parameters) |
| Hardware | 1x NVIDIA A100 80 GB | 1x NVIDIA A100 80 GB |
| Datacenter regio | Duitsland (381 gCO₂/kWh) | Frankrijk (56 gCO₂/kWh) |
| Tijdperken | 20 (zonder vroegtijdig stoppen) | Vroegtijdig stoppen, convergentie in tijdperk 9 |
| Batchgrootte | 16 (A100 30% gebruikt) | 128 (A100 92% gebruikt) |
| Gemengde precisie | Nee (FP32) | Ja (FP16) |
| Valse nauwkeurigheid | 91,2% | 90,7% |
| Duur van de training | ~4,5 uur | ~36 minuten |
Resultaten gemeten met CodeCarbon
Vergelijking van de CO2-voetafdruk: basislijn versus geoptimaliseerd
| Metrisch | Basislijnen | Geoptimaliseerd | Afname |
|---|---|---|---|
| CO2 uitgestoten | 1.723 kgCO₂-eq | 0,061 kgCO₂-eq | -96,5% |
| Energie verbruikt | 4,52 kWh | 1,09 kWh | -75,9% |
| Duur van de training | 4,5 uur | 36 minuten | -86,7% |
| Nauwkeurigheid | 91,2% | 90,7% | -0,5% (aanvaardbaar) |
| GPU-gebruik | ~30% | ~92% | +62 blz |
| Geschatte cloudkosten | ~ $ 13,50 | ~ $ 1,80 | -86,7% |
De reductie van 96,5% van de uitstoot met slechts -0,5% nauwkeurigheid bewijst dat in de meeste gevallen kan de ecologische voetafdruk van ML-software drastisch zijn gereduceerd zonder dat dit ten koste gaat van de modelkwaliteit. De belangrijkste les: meten voordat u gaat optimaliseren.
De 5 interventies om ML-emissies te verminderen (in volgorde van impact)
- Locatieverschuiving (Duitsland → Frankrijk): belangrijkste bijdrage -85% uitstoot. De koolstofintensiteit van het elektriciteitsnet is de meest impactvolle factor. Frankrijk (nucleair, ~56 gCO₂/kWh) versus Duitsland (~381 gCO₂/kWh) levert een verschil op waarbij 7x al het andere gelijk is.
- Vroegtijdig stoppen: -55% gemiddelde duur. Het merendeel van de ML-trainingen convergeert veel eerder dan het geconfigureerde aantal tijdperken. Vroeg stoppen met geduld 3-5 elimineert onnodige tijdperken.
- Verkleinde modelgrootte (BERT-groot → DistilBERT): -80% parameters, -60% tijd. Gedistilleerde of kleinere modellen bereiken vaak een vergelijkbare nauwkeurigheid met een fractie van de rekenkracht.
- Gemengde precisie FP16: -30-50% GPU-energie. Op NVIDIA A100 GPU, RTX 3090+ de FP16 Het is hardwareversneld en halveert het verbruik bij matrixvermenigvuldigingsbewerkingen bijna.
- Optimale batchgrootte: -75% duur voor dezelfde tijdperken. Een optimale batchgrootte voor beschikbaar VRAM maximaliseert het GPU-gebruik en verkort de totale trainingstijd.
Beste praktijken voor systematische CO2-tracking
Aanbevolen projectstructuur
project/
├── .codecarbon.config # Configurazione globale
├── carbon_reports/ # Output CodeCarbon
│ ├── emissions.csv # Dati grezzi
│ ├── carbon_report.png # Report grafico
│ └── unified_report.json # Report locale + cloud
├── scripts/
│ ├── train.py # Training con EmissionsTracker
│ ├── evaluate.py # Evaluation con tracker
│ └── carbon_report.py # Genera dashboard
├── .github/workflows/
│ └── carbon-tracking.yml # CI/CD con carbon budget
└── Makefile
# make train - training con tracking
# make carbon-check - verifica budget
# make carbon-report - genera dashboard
Naamgevingsconventie en configuratie op basis van omgevingsvariabelen
import os
from datetime import datetime
from codecarbon import EmissionsTracker
def create_tracker(model: str, exp_type: str, dataset: str, country: str = None) -> EmissionsTracker:
"""
Naming convention: {model}-{type}-{dataset}-{timestamp}
Es: distilbert-finetuning-imdb-it-20250309_1430
"""
ts = datetime.now().strftime('%Y%m%d_%H%M')
project_name = f"{model}-{exp_type}-{dataset}-{ts}"
country_code = country or os.environ.get('CODECARBON_COUNTRY', 'ITA')
return EmissionsTracker(
project_name = project_name,
country_iso_code= country_code,
output_dir = os.environ.get('CODECARBON_OUTPUT_DIR', './carbon_reports'),
log_level = os.environ.get('CODECARBON_LOG_LEVEL', 'WARNING'),
measure_power_secs = int(os.environ.get('CODECARBON_INTERVAL', '15'))
)
# Utilizzo
with create_tracker("distilbert", "finetuning", "imdb-it", country="FRA"):
fine_tune_model()
Antipatronen die u moet vermijden
- Volg de voorverwerking niet: Tokenisatie en gegevensvergroting kunnen veel tijd kosten Aanzienlijke CPU. Neem altijd voorbewerking op in uw tracking om de volledige voetafdruk te krijgen.
- Vergelijk runs tussen verschillende landen: De CO₂-uitstoot is niet vergelijkbaar rechtstreeks tussen runs in landen met verschillende koolstofintensiteiten. Normaliseren op kWh of gebruik een vast land voor alle benchmarks.
- Maak geen versiebeheer van .codecarbon.config: De trackerconfiguratie moet zijn Er is een versie gemaakt in de repository om de reproduceerbaarheid van metingen tussen ontwikkelaars te garanderen.
-
Stop de tracker in geval van uitzondering: Gebruik altijd een try/finally-blok
of de contextmanager om daarvoor te zorgen
tracker.stop()wordt ook ingeroepen geval van een crash, waarbij gedeeltelijke gegevens behouden blijven. - Behandel CSV als het uiteindelijke eindpunt: Het CSV is het startpunt. Bouw analysepijplijnen om bruikbare inzichten te verkrijgen en experimenten te vergelijken.
Koolstofboekhouding en ESG-rapportage met CodeCarbon-gegevens
De door CodeCarbon gemeten emissies zijn niet alleen nuttig voor het optimaliseren van code: vertegenwoordigen waardevolle gegevens voor ESG-rapportage en compliance CSRD-richtlijn (richtlijn Corporate Sustainability Reporting), wat oplegt grote Europese bedrijven gaan vanaf 2025-2026 digitale emissies rapporteren. In deze context wordt CodeCarbon zowel een governancetool als een ontwikkelingstool.
Het raamwerk van het GHG Protocol (Greenhouse Gas Protocol) classificeert de emissies in drie reikwijdten: Toepassingsgebied 1 (directe emissies, bijvoorbeeld dieselgeneratoren), Toepassingsgebied 2 (aangekochte elektriciteit, inclusief CodeCarbon-uitstoot) e Toepassingsgebied 3 (waardeketen, bijvoorbeeld cloudleverancier en hardwareproduct). CodeCarbon dekt voornamelijk Scope 2-emissies met betrekking tot computerwerklasten.
Gegevensaggregatie voor driemaandelijkse ESG-rapporten
import pandas as pd
import json
from datetime import datetime, timedelta
from pathlib import Path
def generate_esg_report(
emissions_csv: str = "./carbon_reports/emissions.csv",
report_period: str = "Q1-2025",
company_name: str = "MyTechCompany SRL",
output_path: str = "./esg_report.json"
) -> dict:
"""
Genera un report ESG strutturato dai dati CodeCarbon.
Compatibile con CSRD / GHG Protocol Scope 2.
"""
df = pd.read_csv(emissions_csv)
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['emissions_g'] = df['emissions'] * 1000
# Statistiche aggregate
total_co2_kg = df['emissions'].sum()
total_energy_kwh = df['energy_consumed'].sum()
num_experiments = len(df)
avg_co2_per_run_g = df['emissions_g'].mean()
max_co2_run_g = df['emissions_g'].max()
# Breakdown per progetto
project_breakdown = (
df.groupby('project_name')
.agg(
total_co2_kg=('emissions', 'sum'),
total_energy_kwh=('energy_consumed', 'sum'),
num_runs=('emissions', 'count'),
avg_duration_min=('duration', lambda x: (x / 60).mean())
)
.reset_index()
.to_dict(orient='records')
)
# Equivalenze per comunicazione executive
equiv_km_car = total_co2_kg * 4.44 # km in auto media (225 gCO2/km)
equiv_flights = total_co2_kg / 255 # volo Roma-Milano ~255 gCO2 per passeggero
equiv_trees_days = total_co2_kg / 0.022 # giorni assorbimento di un albero (~22 gCO2/giorno)
# Intensità carbonica media pesata
if total_energy_kwh > 0:
weighted_intensity = (df['emissions'] * 1000 / df['energy_consumed']).mean()
else:
weighted_intensity = 0.0
report = {
"report_metadata": {
"generated_at": datetime.now().isoformat(),
"report_period": report_period,
"company": company_name,
"standard": "GHG Protocol - Scope 2 (Market-based)",
"tool": "CodeCarbon v2.x",
"boundary": "Computational workloads (ML training, batch jobs)"
},
"summary": {
"total_co2_kg": round(total_co2_kg, 4),
"total_co2_tco2eq": round(total_co2_kg / 1000, 6),
"total_energy_kwh": round(total_energy_kwh, 4),
"num_tracked_runs": num_experiments,
"avg_co2_per_run_g": round(avg_co2_per_run_g, 3),
"max_co2_single_run_g": round(max_co2_run_g, 3),
"avg_carbon_intensity": round(weighted_intensity, 4)
},
"equivalences": {
"km_car_equivalent": round(equiv_km_car, 1),
"flights_equivalent": round(equiv_flights, 2),
"tree_absorption_days": round(equiv_trees_days, 1)
},
"project_breakdown": project_breakdown,
"scope_classification": {
"scope": 2,
"category": "Purchased electricity for owned operations",
"methodology": "Activity-based (hardware power measurement)",
"data_quality": "High (direct measurement via NVML/RAPL)"
}
}
with open(output_path, 'w') as f:
json.dump(report, f, indent=2, default=str)
print(f"=== Report ESG {report_period} ===")
print(f"CO2 totale: {total_co2_kg:.4f} kgCO2eq")
print(f"Energia: {total_energy_kwh:.4f} kWh")
print(f"Equivalente a: {equiv_km_car:.1f} km in auto")
print(f"Run tracciati: {num_experiments}")
print(f"Report in: {output_path}")
return report
# Genera report per Q1 2025
report = generate_esg_report(
emissions_csv="./carbon_reports/emissions.csv",
report_period="Q1-2025",
company_name="Acme AI SRL",
output_path="./esg_carbon_q1_2025.json"
)
Reductiedoelstellingen en op wetenschap gebaseerde doelstellingen (SBTi)
Bedrijven die zich aansluiten bij het Science Based Targets-initiatief (SBTi) zetten zich in voor reductie emissies in overeenstemming met de klimaatdoelstellingen van de Overeenkomst van Parijs. Voor ICT-emissies geldt Dit betekent doorgaans een jaarlijkse reductie van 4-7%. CodeCarbon kan worden gebruikt om de voortgang richting deze doelstellingen automatisch te volgen.
import pandas as pd
from datetime import datetime
def track_reduction_progress(
emissions_csv: str,
baseline_year: int,
target_reduction_pct: float = 5.0, # 5% riduzione annuale
) -> dict:
"""
Traccia il progresso verso gli obiettivi di riduzione SBTi.
"""
df = pd.read_csv(emissions_csv)
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['year'] = df['timestamp'].dt.year
annual_emissions = df.groupby('year')['emissions'].sum().to_dict()
baseline_emissions = annual_emissions.get(baseline_year, 0)
current_year = datetime.now().year
current_emissions = annual_emissions.get(current_year, 0)
years_elapsed = current_year - baseline_year
target_reduction_factor = (1 - target_reduction_pct / 100) ** years_elapsed
target_emissions = baseline_emissions * target_reduction_factor
actual_reduction_pct = 0.0
on_track = False
if baseline_emissions > 0:
actual_reduction_pct = (baseline_emissions - current_emissions) / baseline_emissions * 100
on_track = current_emissions <= target_emissions
return {
"baseline_year": baseline_year,
"baseline_emissions_kg": round(baseline_emissions, 4),
"current_year": current_year,
"current_emissions_kg": round(current_emissions, 4),
"target_emissions_kg": round(target_emissions, 4),
"target_annual_reduction_pct": target_reduction_pct,
"actual_reduction_pct": round(actual_reduction_pct, 2),
"on_track": on_track,
"annual_history": {str(k): round(v, 4) for k, v in annual_emissions.items()}
}
# Utilizzo: verifica se il team e' in linea con gli obiettivi SBTi
progress = track_reduction_progress(
emissions_csv="./carbon_reports/emissions.csv",
baseline_year=2024,
target_reduction_pct=5.0
)
status = "IN LINEA" if progress['on_track'] else "SOTTO TARGET"
print(f"Obiettivi SBTi: {status}")
print(f"Riduzione attuale: {progress['actual_reduction_pct']:.1f}%")
print(f"Target annuale: {progress['target_annual_reduction_pct']:.1f}%")
CodeCarbon en CSRD: wat u moet weten
De CSRD-richtlijn (Corporate Sustainability Reporting Directive) verplicht Europese bedrijven met meer dan 500 medewerkers (vanaf 2025) en vervolgens naar die met meer dan 250 medewerkers (vanaf 2026) om de uitstoot van broeikasgassen te rapporteren volgens de ESRS-normen (European Sustainability Reporting Standards). Voor digitale releases:
- ESRS E1 (Klimaatverandering): Vereist openbaarmaking van Scope 1-, 2- en 3-emissies met de GHG Protocol-methodologie. CodeCarbon omvat Scope 2 van computerbewerkingen.
- Materialiteit: Als de ICT-emissies materieel zijn (significant vergeleken ten opzichte van het bedrijfstotaal), moet worden gerapporteerd. Voor technologiebedrijven is dit vrijwel altijd het geval.
- Audittrails: CodeCarbon CSV's bieden een gedetailleerd audittraject voor verificatie rapportage door derden, een essentiële vereiste voor de geloofwaardigheid van het ESG-rapport.
- Zekerheid: De CSRD vereist een beperkte (vanaf 2025) en redelijke (vanaf 2028) zekerheid. De kwaliteit van CodeCarbon-gegevens (directe meting versus schatting) is cruciaal.
Conclusies: Meten is de eerste stap
CodeCarbon heeft het bijhouden van codekoolstof getransformeerd van een academische oefening naar een praktijk beton en toegankelijke techniek. Met minder dan 10 regels Python kan elke datawetenschapper o ML-ingenieurs kunnen beginnen met het meten en kwantificeren van de milieu-impact van hun werk.
Uit de casestudy is gebleken dat er sprake is van een reductie 96,5% van de CO₂-uitstoot met slechts -0,5% nauwkeurigheid. Dit is geen uitzonderlijk geval: het is de norm wanneer we vertrekken van een niet-geoptimaliseerde configuratie. De meeste ML-trainingen hebben enorme marges van CO2-optimalisatie die onzichtbaar blijven totdat u begint met meten.
Het pad naar duurzamere software verloopt in drie fasen:
- Meeteenheid: Integreer CodeCarbon in alle workflows. Definieer het koolstofbudget. Creëer meetbare basislijnen. Maak emissies net zo zichtbaar als nauwkeurigheid.
- Optimaliseren: Gebruik gegevens om CO2-knelpunten te identificeren. Locatie verschuiven, modelgrootte, batchgrootte en gemengde precisie zijn de meest effectieve hefbomen.
- Voorkomen: Integreer CO2-tracking in CI/CD. Definieer het koolstofbudget per type van experimenteren. Gebruik de Carbon Aware SDK om locatie-/tijdverschuiving te automatiseren.
In het volgende artikel in de serie gaan we dit verkennen Climatiq-API, een hulpmiddel complementair waarmee u de uitstoot van het BKG-protocol (Scope 1, 2 en 3) kunt berekenen via REST API, die berekeningen integreert in de backend van applicaties voor geautomatiseerde ESG-rapportage.
Bronnen en nuttige links
De Green Software Series gaat verder
- Artikel 1: Green Software Foundation-principes — GSF, SCI, 8 principes
- Artikel 2 (huidig): Het meten van uw CO2-voetafdruk met CodeCarbon
- Artikel 3: Integreer Climatiq API - GHG Protocol-berekeningen in de backend
- Artikel 4: Carbon Aware SDK — Tijdverschuiving en locatieverschuiving
- Artikel 6: GreenOps met Kubernetes – Koolstofbewuste infrastructuur
- Artikel 10: AI en koolstof — Meten en verkleinen van de voetafdruk van ML-training







