Umělá inteligence a uhlík: Měření a snižování stopy školení ML
Trénink GPT-4 spotřeboval cca 50 GWh elektřiny, dostačující napájet více než 4 600 evropských domácností po celý rok. GPT-3, jeho předchůdce, he produced 502 tun ekvivalentu CO₂ během tréninku - ekvivalent 112 benzinových automobilů, které ujedou 20 000 km ročně. BLOOM, open-source model se 176 miliardami parametrů vyškolený ve Francii v oblasti energetiky smíšené, vydal 25 tun CO₂ekv díky rozšířenému používání jaderné a obnovitelné energie.
To nejsou statistické kuriozity: jsou to známky rychle se rozvíjejícího strukturálního problému zrychlení. Generativní AI roste exponenciální rychlostí se vzory stále větší, stále větší soubory dat a stále větší cykly školení časté. Podle studie zveřejněné v Příroda v roce 2024, emise související s Pokud nebudou přijata žádná opatření, do roku 2027 by se mohl výcvik modelu umělé inteligence ztrojnásobit systémové účinnosti. IEA odhaduje, že datová centra věnovaná AI v roce 2026 spotřebují více energie než mnohé středně velké evropské státy.
Přesto naprostá většina týmů ML začíná trénovat na GPU clusterech, aniž by kdy provedli měření produkované emise. Ne proto, že by je to nezajímalo, ale protože jim chybí nástroje integrované do každodenního pracovního postupu, sdílené standardní metriky a kultura měření. V tomto posledním článku seriálu Zelené softwarové inženýrství budeme zkoumat celý životní cyklus uhlíkové stopy ve strojovém učení: od přesného měření s CodeCarbon a CarbonTracker, architektonická optimalizace s prořezáváním a destilací, až po plánování školení s ohledem na uhlík a optimalizaci odvození ve výrobě.
Co se naučíte
- Údaje o skutečných emisích pro základní modely: GPT-3, GPT-4, Llama 2, BLOOM, PaLM
- Nainstalujte a používejte CodeCarbon, CarbonTracker, ML CO₂ Impact a Green Algorithms
- Porovnejte GPU pro energetickou účinnost: A100, H100, H200, B200 ve FLOPS/W
- Techniky architektonické optimalizace: prořezávání, destilace znalostí, efektivní NAS
- Účinnost zaměřená na data: kvalita dat versus kvantita, učení se osnov
- Školení s ohledem na uhlík: naplánujte si pracovní zátěž v oblastech a časech s nízkou intenzitou uhlíku
- Optimalizace inference: kvantizace INT8/INT4, ONNX Runtime, TensorRT, vLLM
- Vypočítejte skóre SCI pro modely ML a vytvořte si žebříček zelené AI
- Kompletní případová studie: 60% snížení emisí na skutečném modelu NLP
- Praktický plán pro zavádění zelené umělé inteligence v organizacích
Green Software Engineering Series – 10 článků
| # | Položka | Hlavní téma |
|---|---|---|
| 1 | Principy Green Software Foundation | GSF, SCI, 8 základních principů |
| 2 | Měření vaší uhlíkové stopy pomocí CodeCarbon | Integrace CodeCarbon, CCF, CI/CD |
| 3 | Climatiq API a uhlíkové účetnictví | REST API, LCA, Rozsah 1-2-3 |
| 4 | Carbon-Aware SDK a časové/prostorové posuny | Přesuňte pracovní zátěž na zelenou energii |
| 5 | Modelování rozsahu a implementace SCI | Praktický výpočet SCI, Impact Framework |
| 6 | GreenOps: FinOps pro udržitelnost | Náklady na cloud a uhlík, Kubernetes |
| 7 | Rozsah 3 v softwarovém kanálu | Nepřímé emise, digitální dodavatelský řetězec |
| 8 | ESG, CSRD a digitální výkaznictví | Evropská shoda, ESRS E1, zveřejnění |
| 9 | Udržitelné architektonické vzory | Ukládání, ukládání do mezipaměti, dávka s ohledem na uhlík |
| 10 | AI a Carbon: ML Training Footprint | Tento článek – poslední článek v seriálu |
Skutečná uhlíková stopa základních modelů
Pochopení rozsahu problému vyžaduje tvrdá data. Stanfordští výzkumníci Hugging Face a MLCommons začaly zveřejňovat metriky emisí pro velké společnosti lingvistické modely. Následující tabulka shrnuje dostupné údaje, přičemž je třeba mít na paměti, že mnoho společností – zejména OpenAI – tyto informace stále nezveřejňuje.
Emise CO₂ekv základních modelů během školení
| Model | Parametry | energie (MWh) | CO₂ekv (t) | Region/Mix | Zdroj |
|---|---|---|---|---|---|
| GPT-3 | 175B | 1,287 | 502 | USA (střední mix) | Patterson a kol. 2021 |
| GPT-4 | ~1,8T (odhad) | ~50 000 | ~14 000 | USA (odhad) | Nezávislé odhady 2023 |
| KVĚT | 176B | 433 | 25 | Francie (jaderná + obnovitelná) | Luccioni a kol. 2022 |
| Lama 2 (70B) | 70B | ~700 | 539 | USA/Azure | Meta FW 2023 |
| Dlaň | 540B | ~3 400 | ~507 | USA (TPU v4) | Chowdhery a kol. 2022 |
| Mistral 7B | 7B | ~35 | ~12 | Evropa (mix) | Mistral FW 2023 |
| Falcon 180B | 180B | ~600 | ~117 | SAE (směs) | TII 2023 |
| Drahokam 7B | 7B | ~32 | ~6 | USA/TPU (RE100) | Google DeepMind 2024 |
Tato data odhalují tři základní vzorce. První je geografická mezera: BLOOM, vyškolený ve Francii s převážně jadernou energií, emitoval 20krát méně lamy 2 ve stejném řádu velikosti. Druhým jestupnicový efekt: přechod z parametrů 7B na 176B neznamená jednoduše 25x více emisí – náklady na distribuovanou komunikaci a délka školení rostou nelineárně. Třetí je průhlednost mezera: Většina společností ne tato data stále zveřejňuje, což ztěžuje srovnání a srovnávání není možné bez nezávislých měření.
Paradox inference: Větší než trénink
Kontraintuitivně, kumulativní emiseodvození často překračují školení v životním cyklu modelu. Model jako ChatGPT s miliony požadavků za den, může spotřebovat více energie za měsíc výroby celého původního tréninku. Patterson a kol. odhadnout, že závěr GPT-3 na měřítku ChatGPT produkuje cca 11 000 tun CO₂ekv ročně. Toto přesouvá zaměření od optimalizace školení k optimalizaci odvození hlavní prioritou je snížení celkového dopadu na životní prostředí.
Ztělesněné emise a úplný životní cyklus
Analýza uhlíkové stopy AI nemůže být omezena na energii spotřebovanou během školení. The vtělené emise hardwaru – emitovaného CO₂ vyrábět GPU, servery, chladicí sítě a infrastrukturu – představují a významný podíl. Výroba jednoho čipu H100 emituje cca 150 kg CO₂ekv, a cluster s 1 000 GPU vede ke ztělesněným emisím kolem 150 tun pro samotný hardware, ještě před zahájením jednoho tréninku.
# Formula Carbon Footprint Completo per ML
# Basato su Luccioni et al. "Counting Carbon" (2023)
Total_CO2eq = Training_CO2eq + Inference_CO2eq + Embodied_CO2eq
Training_CO2eq = Energy_training (kWh) x Carbon_Intensity (kgCO2eq/kWh) x PUE
Inference_CO2eq = (Requests x Latency x GPU_Power / 3600000) x Carbon_Intensity x PUE
Embodied_CO2eq = (Hardware_Production_CO2eq / Lifespan_hours) x Training_hours
# Esempio: modello NLP medio (BERT-Large fine-tuning su task classificazione)
Energy_training = 120 kWh # 4x A100, 6 ore
Carbon_Intensity = 0.420 kg/kWh # mix europeo medio
PUE = 1.3 # data center tipico
Training_CO2eq = 120 x 0.420 x 1.3 = 65.5 kgCO2eq
# Inferenza: 10M richieste/mese, 50ms each, 1x A100 (300W)
Inference_monthly = (10_000_000 x 0.05 x 300 / 3_600_000) x 0.420 x 1.3
= 41.7 kWh x 0.420 x 1.3 = 22.7 kgCO2eq/mese
# Dopo 12 mesi: 272 kgCO2eq inferenza vs 65 kgCO2eq training
# L'inferenza domina del 77% nel ciclo di vita annuale
Nástroje pro měření: od CodeCarbon po zelené algoritmy
Measuring ML emissions requires tools designed specifically for ML workloads školení a vyvozování. Four tools dominate the space: CodeCarbon, CarbonTracker, Kalkulačka dopadu ML CO₂ a zelené algoritmy. Každý má specifické silné stránky a optimální případy použití.
CodeCarbon: Přímá integrace do kódu Pythonu
CodeCarbon je nejoblíbenější nástroj pro měření emisí během ML trénink. Jeho integrace s nejběžnějšími frameworky (PyTorch, TensorFlow, Hugging Face Transformers) je přirozenou volbou pro většinu týmů.
# pip install codecarbon
from codecarbon import EmissionsTracker, track_emissions
import torch
from transformers import Trainer, TrainingArguments
# Metodo 1: Context manager
tracker = EmissionsTracker(
project_name="bert-finetuning-sentiment",
country_iso_code="ITA",
region="lombardy",
cloud_provider="gcp",
cloud_region="europe-west8",
output_dir="./carbon_reports",
output_file="emissions.csv",
log_level="warning",
save_to_file=True,
tracking_mode="machine", # Legge sensori hardware reali
measure_power_secs=15 # Campionamento ogni 15 secondi
)
tracker.start()
try:
# Il tuo training loop qui
model = train_model(dataset, epochs=10)
finally:
emissions = tracker.stop()
print(f"Training completato: {emissions:.4f} kgCO2eq")
print(f"Equivalente a: {emissions * 2.4:.2f} km in auto")
# Metodo 2: Decorator per funzioni singole
@track_emissions(
project_name="bert-inference",
country_iso_code="ITA",
save_to_file=True
)
def run_inference_batch(model, dataloader):
results = []
with torch.no_grad():
for batch in dataloader:
outputs = model(**batch)
results.extend(outputs.logits.argmax(-1).tolist())
return results
# Metodo 3: Integrazione con Hugging Face Trainer
from codecarbon import EmissionsTracker
class CarbonAwareTrainer(Trainer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.carbon_tracker = EmissionsTracker(
project_name=f"hf-training-{self.args.run_name}",
country_iso_code="ITA",
save_to_file=True
)
def train(self, *args, **kwargs):
self.carbon_tracker.start()
result = super().train(*args, **kwargs)
emissions = self.carbon_tracker.stop()
self.log({"carbon_emissions_kgCO2eq": emissions})
return result
CarbonTracker: Projekce a rozpočtování
CarbonTracker, vyvinutý Univerzitou v Kodani, vyniká svou kapacitou z celková spotřeba projektu na základě prvních tréninkových období. Tato funkce je neocenitelná: umožňuje vám odhadnout náklady na uhlík před dokončením školení, které trvá dny nebo týdny.
# pip install carbontracker
from carbontracker.tracker import CarbonTracker
from carbontracker import parser
# Configurazione con proiezione
tracker = CarbonTracker(
epochs=100,
epochs_before_pred=5, # Dopo 5 epoche, proietta le 95 rimanenti
monitor_epochs=10, # Monitora ogni 10 epoche
log_dir="./carbontracker_logs",
update_interval=10,
verbose=2,
components="gpu",
ignore_errors=False
)
for epoch in range(100):
tracker.epoch_start()
# Training epoch
for batch in train_loader:
optimizer.zero_grad()
outputs = model(batch['input_ids'], batch['attention_mask'])
loss = criterion(outputs, batch['labels'])
loss.backward()
optimizer.step()
tracker.epoch_end()
tracker.stop()
# Dopo 5 epoche, CarbonTracker stampa proiezioni come:
# "Predicting training to use 2.34 kWh and emit 0.98 kgCO2eq"
# "Total: actual consumption: 0.12 kWh, 0.05 kgCO2eq (after 5 epochs)"
# Parsing dei log per analisi
logs = parser.parse_all_logs(log_dir="./carbontracker_logs")
for log in logs:
print(f"Energia: {log['actual']['energy (kWh)']:.3f} kWh")
print(f"CO2: {log['actual']['co2eq (g)']:.1f} gCO2eq")
print(f"Proiezione totale: {log['pred']['co2eq (g)']:.1f} gCO2eq")
Kalkulačka dopadu ML CO₂ a zelené algoritmy
Kalkulačka dopadu ML CO₂ (mlco2.github.io) je webový nástroj který odhaduje emise na základě hardwaru, poskytovatele cloudu, regionu a trvání. Nevyžaduje Integrace do kódu: Ideální pro rychlé předtréninkové odhady nebo dokumentaci výcvikové problémy již dokončeny. Podporuje AWS, GCP, Azure a 15+ regionů.
Zelené algoritmy (green-algorithms.org), vyvinutý univerzitou z Cambridge, nabízí více vědecký přístup s modely spotřeby energie ověřeno na skutečných datech datového centra. Podporuje výpočty pro HPC (High Performance Computing), GPU clustery a bioinformatické pracovní postupy.
Porovnání nástrojů pro měření uhlíku ML
| Nástroj | Typ | Zrnitost | Integrace | Pevný bod | Omezení |
|---|---|---|---|---|---|
| KódCarbon | Python lib | Funkce/zaměstnání | PyTorch, T.F., H.F | Skutečné měření hardwaru | Pouze Python, režie <1 % |
| Carbon Tracker | Python lib | Pro éru | Hluboké učební smyčky | Předčasné promítání | Vyžaduje epochální školení |
| ML CO₂ Dopad | Webové nástroje | Úroveň práce | Žádné (webový formulář) | Nulové nastavení, rychlý odhad | Pouze odhad, ne měření |
| Zelené algoritmy | Webové nástroje | Úroveň práce | Žádné (webový formulář) | Vědecky ověřené modely | Ne v reálném čase |
| Sledování dopadu experimentu | Python lib | Experimentovat | ML experimenty | Automatické protokolování MLflow | Nejméně udržované (2021) |
Řídicí panel a automatické hlášení
Měření je hodnotné pouze tehdy, jsou-li data agregována, vizualizována a používána k měření rozhodnutí. Efektivním vzorem je integrace CodeCarbon s MLflow k vytvoření a automatický sledovací systém, který zaznamenává emise spolu s metrikami výkonu.
import mlflow
from codecarbon import EmissionsTracker
import pandas as pd
from pathlib import Path
class GreenMLExperiment:
"""Wrapper che traccia automaticamente emissioni + performance ML."""
def __init__(self, experiment_name: str, country_code: str = "ITA"):
self.experiment_name = experiment_name
self.country_code = country_code
mlflow.set_experiment(experiment_name)
def run(self, model_fn, train_fn, eval_fn, params: dict):
with mlflow.start_run():
mlflow.log_params(params)
# Avvia tracker emissioni
tracker = EmissionsTracker(
project_name=self.experiment_name,
country_iso_code=self.country_code,
save_to_file=True,
output_dir="./emissions_logs"
)
tracker.start()
model = model_fn(**params)
train_metrics = train_fn(model)
emissions_kg = tracker.stop()
# Metriche performance
eval_metrics = eval_fn(model)
# Log tutto su MLflow
mlflow.log_metric("train_loss", train_metrics["loss"])
mlflow.log_metric("eval_accuracy", eval_metrics["accuracy"])
mlflow.log_metric("emissions_kgCO2eq", emissions_kg)
mlflow.log_metric("emissions_grams", emissions_kg * 1000)
mlflow.log_metric(
"accuracy_per_kgCO2",
eval_metrics["accuracy"] / max(emissions_kg, 0.001)
)
# Log artefatti
mlflow.log_artifacts("./emissions_logs")
return {
"model": model,
"emissions": emissions_kg,
"metrics": eval_metrics,
"efficiency_ratio": eval_metrics["accuracy"] / emissions_kg
}
# Utilizzo
experiment = GreenMLExperiment("bert-sentiment-v2", country_code="ITA")
result = experiment.run(
model_fn=create_bert_model,
train_fn=train_epoch,
eval_fn=evaluate_model,
params={"lr": 2e-5, "batch_size": 32, "epochs": 5}
)
Energetická účinnost GPU: FLOPS na watt
Výběr hardwaru je z hlediska uhlíkové stopy tím nejpůsobivějším rozhodnutím školení. GPU nové generace nabízí výrazně vyšší energetickou účinnost ve srovnání s předchůdci a rozdíl mezi tréninkem na A100 vs H200 může znamenat snížení emisí o 40–60 % při stejném pracovním zatížení.
Porovnání GPU pro školení ML: Energetická účinnost (2025)
| GPU | Rok | TDP (W) | FP16 TFLOPS | FLOPS/Watt | Paměť HBM | CO₂ Relativní |
|---|---|---|---|---|---|---|
| A100 SXM4 | 2020 | 400W | 312 | 780 GFLOPS/W | 80 GB HBM2e | Základní linie (1,0x) |
| H100 SXM5 | 2022 | 700W | 989 | 1,413 GFLOPS/W | 80 GB HBM3 | 0,56x (-44 %) |
| H200 SXM5 | 2024 | 700W | 989 | 1,413 GFLOPS/W | 141 GB HBM3e | 0,56x (-44 %) |
| B200 SXM6 | 2025 | 1 000 W | 4 500 | 4 500 GFLOPS/W | 192 GB HBM3e | 0,17x (-83 %) |
| RTX 4090 | 2022 | 450W | 165 | 367 GFLOPS/W | 24GB GDDR6X | 2,12x (+112 %) |
| AMD MI300X | 2024 | 750W | 1,307 | 1,743 GFLOPS/W | 192 GB HBM3 | 0,45x (-55 %) |
H100 a H200 nabízejí přibližně 44% snížení emisí respekt na A100 pro stejnou pracovní zátěž, díky Transformer Engine s FP8 a architektuře Optimalizováno pro NVLink. B200 představuje generační skok s 4,5 PFLOPS a FP16 nativní podpora FP4, čímž došlo ke snížení na 83 %.
Mixed Precision Training: FP16 a BF16
Školení v smíšená přesnost (FP16 nebo BF16 pro výpočty, FP32 pro parametry modelu) snižuje spotřebu energie o 30-50% ve srovnání s tréninkem plný FP32, bez výrazného zhoršení kvality modelu.
import torch
from torch.cuda.amp import autocast, GradScaler
# Training con AMP (Automatic Mixed Precision)
scaler = GradScaler()
def train_epoch_amp(model, dataloader, optimizer, device):
model.train()
total_loss = 0.0
for batch in dataloader:
input_ids = batch['input_ids'].to(device)
labels = batch['labels'].to(device)
optimizer.zero_grad()
# Forward pass in FP16/BF16
with autocast(dtype=torch.bfloat16): # BF16 su A100/H100
outputs = model(input_ids=input_ids, labels=labels)
loss = outputs.loss
# Backward pass con gradient scaling
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
# Gradient clipping per stabilità
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
scaler.step(optimizer)
scaler.update()
total_loss += loss.item()
return total_loss / len(dataloader)
# Con Hugging Face: basta un flag
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./results",
bf16=True, # BF16 per A100/H100 (preferibile a FP16)
fp16=False,
dataloader_num_workers=4,
per_device_train_batch_size=32,
gradient_accumulation_steps=4, # Simula batch da 128
gradient_checkpointing=True, # -40% memoria VRAM, +20% tempo
# Risparmio energetico: meno transfer GPU-CPU
dataloader_pin_memory=True
)
# Benchmark: BERT-Large su 1M esempi
# FP32: 6.2 ore, 148 kWh, 62 kgCO2eq (ITA)
# BF16: 3.4 ore, 81 kWh, 34 kgCO2eq (ITA) -> -45% emissioni
Architektonická optimalizace: Prořezávání, destilace a NAS
Techniky architektonické optimalizace snižují složitost modelu, což vede k rychlejšímu školení, efektivnějšímu vyvozování a uhlíkové stopě celkově snížena. Tři hlavní techniky jsou prořezávání, znalostní destilace a efektivní vyhledávání neuronové architektury.
Prořezávání modelu: Odstraňte nadbytečnost
Prořezávání eliminuje okrajově přispívající parametry nebo struktury modelu to accuracy. Existují dva hlavní přístupy: nestrukturované prořezávání (individuální váhy) e strukturované prořezávání (hlavy pozornosti, neurony, vrstvy). Ten je výhodnější pro skutečnou efektivitu hardwaru, protože je nestrukturovaný prořezávání vyžaduje hardware s řídkou podporou, aby bylo skutečně přínosné.
import torch
import torch.nn.utils.prune as prune
from transformers import BertForSequenceClassification
import numpy as np
def structured_pruning_bert(model, pruning_ratio=0.3):
"""
Pruning strutturato delle teste di attenzione BERT.
Rimuove le teste meno importanti basandosi sulla norma L1.
"""
pruned_heads = {}
for layer_idx, layer in enumerate(model.bert.encoder.layer):
# Calcola importanza di ogni testa (norma L1 dei pesi query)
attention = layer.attention.self
num_heads = attention.num_attention_heads
head_size = attention.attention_head_size
query_weights = attention.query.weight.data # shape: [hidden, hidden]
query_reshaped = query_weights.view(num_heads, head_size, -1)
head_importance = query_reshaped.abs().mean(dim=[1, 2])
# Seleziona le teste da prunable
num_heads_to_prune = int(num_heads * pruning_ratio)
heads_to_prune = head_importance.argsort()[:num_heads_to_prune].tolist()
if heads_to_prune:
pruned_heads[layer_idx] = set(heads_to_prune)
model.prune_heads(pruned_heads)
return model, pruned_heads
# Unstructured pruning con PyTorch
def magnitude_pruning(model, sparsity=0.5):
"""Pruning per magnitudine su tutti i layer Linear."""
parameters_to_prune = [
(module, 'weight')
for module in model.modules()
if isinstance(module, torch.nn.Linear)
]
prune.global_unstructured(
parameters_to_prune,
pruning_method=prune.L1Unstructured,
amount=sparsity
)
# Rende il pruning permanente
for module, param in parameters_to_prune:
prune.remove(module, param)
return model
# Risultati tipici su BERT-Base (110M parametri):
# Pruning 30% teste: -28% latenza inferenza, -1.2% accuracy
# Pruning 50% pesi (magnitude): -45% dimensione, -0.8% accuracy
# Emissioni inferenza: -30% con structured pruning
Destilace znalostí: Malé modely s velkými znalostmi
Destilace znalostí přenáší znalosti od jednoho velkého modelu (učitele) k jednomu malý (student). DistilBERT má například 40 % parametrů BERT-Base ale udržuje 97 % svého výkonu v benchmarku GLUE. Tréninkové emise DistilBERT jsou o 60 % nižší a inferenční o 40–50 %.
import torch
import torch.nn as nn
import torch.nn.functional as F
class DistillationLoss(nn.Module):
"""
Loss combinata per knowledge distillation:
L = alpha * L_CE(student, labels) + (1-alpha) * L_KL(student, teacher)
"""
def __init__(self, alpha=0.5, temperature=4.0):
super().__init__()
self.alpha = alpha
self.temperature = temperature
self.ce_loss = nn.CrossEntropyLoss()
def forward(self, student_logits, teacher_logits, labels):
# Loss classificazione standard
loss_ce = self.ce_loss(student_logits, labels)
# Loss distillazione (KL divergence con temperature scaling)
student_soft = F.log_softmax(student_logits / self.temperature, dim=-1)
teacher_soft = F.softmax(teacher_logits / self.temperature, dim=-1)
loss_kl = F.kl_div(student_soft, teacher_soft, reduction='batchmean')
loss_kl *= self.temperature ** 2 # Scala per compensare la temperature
return self.alpha * loss_ce + (1 - self.alpha) * loss_kl
def distill_model(teacher_model, student_model, train_loader,
optimizer, device, epochs=5):
"""Training loop completo per knowledge distillation."""
distill_loss = DistillationLoss(alpha=0.5, temperature=4.0)
teacher_model.eval()
for epoch in range(epochs):
student_model.train()
total_loss = 0.0
for batch in train_loader:
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
# Teacher inference (no gradient)
with torch.no_grad():
teacher_outputs = teacher_model(
input_ids=input_ids,
attention_mask=attention_mask
)
# Student forward pass
student_outputs = student_model(
input_ids=input_ids,
attention_mask=attention_mask
)
loss = distill_loss(
student_outputs.logits,
teacher_outputs.logits,
labels
)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch+1}: Loss = {total_loss/len(train_loader):.4f}")
# Caso d'uso tipico: distillare BERT-Large (340M) -> BERT-Tiny (14M)
# Training: 8h vs 2.5h -> -69% tempo
# Emissioni training: -71%
# Accuracy GLUE: 84.6 vs 87.2 -> -3% accettabile per la maggior parte dei task
Efektivní vyhledávání neuronové architektury
Traditional NAS is ironically one of the most energy-intensive processes in ML: Searching for the optimal architecture can require thousands of complete training sessions. The Výkonný NAS používá techniky jako jednorázový NAS, sdílení hmotnosti a vyhledávání založené na prediktorech pro snížení nákladů na vyhledávání o 99 %.
# Esempio con Once-for-All Network (OFA) da MIT
# OFA addestra una volta una supernetwork, poi campiona subnetwork efficienti
# Installazione: pip install ofa
from ofa.model_zoo import ofa_net
# Carica supernetwork pre-addestrata (una volta sola)
ofa_network = ofa_net('ofa_resnet50', pretrained=True)
# Campiona subnetwork che rispettano constraint energetici
# senza riaddestrare (zero-cost NAS)
def find_efficient_subnet(ofa_net, target_flops: float = 200e6):
"""
Cerca una subnetwork con FLOPs < target_flops
usando evolutionary search con predictor di accuracy.
"""
from ofa.nas.search_algorithm import EvolutionFinder
finder = EvolutionFinder(
constraint_type='flops',
efficiency_constraint=target_flops,
efficiency_predictor=ofa_net.flops_counter,
accuracy_predictor=None, # Usa validazione reale
population_size=100,
max_time_budget=500,
parent_ratio=0.25,
mutation_ratio=0.5
)
best_valset_acc, best_info = finder.run_evolution_search()
return best_info['net_config']
# Risultato tipico:
# Supernetwork ResNet-50: 4.1 GFLOPs, 25.6M param
# Subnetwork trovata: 200 MFLOPs, 6.2M param
# Accuracy ImageNet: 77.8% vs 79.2% (- 1.4%, - 95% emissioni inferenza)
Data-centrická efektivita: kvalita versus kvantita
Vyšší kvalita datové sady umožňuje dosáhnout stejné přesnosti s méně tréninkovými epochami a méně daty. Jedná se o jednu ze zásad datově orientovaná AI propagoval Andrew Ng: místo zvýšení modelu nebo nezpracovaná data, zlepšit kvalitu stávajících dat.
Učení podle osnov: Školení ve správném pořadí
Učební osnovy seřazují příklady školení se zvyšující se obtížností, jako učitel, který začíná jednoduchými pojmy, než přejde ke složitým. Tento přístup konverguje rychleji as menším počtem celkových epoch, snižuje se uhlíková stopa 20–35 % ve standardních měřítcích.
import numpy as np
from torch.utils.data import DataLoader, SubsetRandomSampler
from sklearn.metrics import pairwise_distances
class CurriculumScheduler:
"""
Curriculum Learning: ordina il dataset dalla difficolta' crescente.
La difficolta' e' calcolata come distanza dalla media della classe.
"""
def __init__(self, dataset, difficulty_metric='loss', num_stages=4):
self.dataset = dataset
self.num_stages = num_stages
self.difficulty_scores = None
def compute_difficulty(self, model, device):
"""Calcola difficolta' come loss su un modello pre-addestrato leggero."""
model.eval()
scores = []
loader = DataLoader(self.dataset, batch_size=256, shuffle=False)
criterion = nn.CrossEntropyLoss(reduction='none')
with torch.no_grad():
for batch in loader:
input_ids = batch['input_ids'].to(device)
labels = batch['labels'].to(device)
outputs = model(input_ids=input_ids)
losses = criterion(outputs.logits, labels)
scores.extend(losses.cpu().numpy())
self.difficulty_scores = np.array(scores)
return self.difficulty_scores
def get_stage_indices(self, stage: int) -> list:
"""Ritorna gli indici degli esempi per lo stage corrente."""
if self.difficulty_scores is None:
raise ValueError("Esegui compute_difficulty prima.")
# Divide il dataset in quartili di difficolta'
sorted_indices = np.argsort(self.difficulty_scores)
stage_size = len(sorted_indices) // self.num_stages
# Stage 0: esempi più' facili, Stage N: tutti gli esempi
max_idx = stage_size * (stage + 1)
return sorted_indices[:max_idx].tolist()
def curriculum_training(model, dataset, optimizer, device, total_epochs=20):
"""Training con curriculum progressivo."""
scheduler = CurriculumScheduler(dataset, num_stages=4)
# Usa un modello leggero per calcolare la difficolta'
tiny_model = load_tiny_model().to(device)
difficulty = scheduler.compute_difficulty(tiny_model, device)
for epoch in range(total_epochs):
# Progressione lineare: da 25% a 100% del dataset
stage = min(3, int(epoch / total_epochs * 4))
indices = scheduler.get_stage_indices(stage)
sampler = SubsetRandomSampler(indices)
loader = DataLoader(dataset, batch_size=32, sampler=sampler)
print(f"Epoch {epoch}: usando {len(indices)}/{len(dataset)} esempi")
train_one_epoch(model, loader, optimizer, device)
# Risultati tipici:
# Training standard BERT-Base: 10 epoche per convergenza
# Training con curriculum: 6.5 epoche -> -35% emissioni
Aktivní učení: Vyberte nejinformativnější data
Aktivní učení iterativně vybírá ty nejinformativnější příklady k označení, místo použití celé datové sady. S anotačním rozpočtem 10-20% je toho dosaženo často 90–95 % přesnosti školení s plnými daty, což se úměrně snižuje uhlíkovou stopu.
from sklearn.cluster import KMeans
import torch.nn.functional as F
class ActiveLearningSelector:
"""Seleziona esempi con massima incertezza (uncertainty sampling)."""
def __init__(self, model, unlabeled_pool, strategy='entropy'):
self.model = model
self.unlabeled_pool = unlabeled_pool
self.strategy = strategy
def compute_uncertainty(self, batch_size=128) -> np.ndarray:
"""Calcola incertezza del modello su ogni esempio non etichettato."""
self.model.eval()
uncertainties = []
loader = DataLoader(self.unlabeled_pool, batch_size=batch_size)
with torch.no_grad():
for batch in loader:
logits = self.model(batch['input_ids']).logits
probs = F.softmax(logits, dim=-1)
if self.strategy == 'entropy':
# Entropia: massima quando la distribuzione e' uniforme
entropy = -(probs * probs.log()).sum(dim=-1)
uncertainties.extend(entropy.cpu().numpy())
elif self.strategy == 'margin':
# Margin: minimo quando le top-2 prob sono simili
top2 = probs.topk(2, dim=-1).values
margin = top2[:, 0] - top2[:, 1]
uncertainties.extend((1 - margin).cpu().numpy())
return np.array(uncertainties)
def select_examples(self, n_select: int) -> list:
"""Seleziona i n_select esempi più' incerti."""
uncertainties = self.compute_uncertainty()
top_indices = np.argsort(uncertainties)[-n_select:]
return top_indices.tolist()
# Workflow Active Learning
def active_learning_loop(
model, labeled_data, unlabeled_pool,
annotation_budget=500, iterations=5
):
per_iteration = annotation_budget // iterations
for iteration in range(iterations):
# Seleziona esempi
selector = ActiveLearningSelector(model, unlabeled_pool)
selected_idx = selector.select_examples(per_iteration)
# Simula annotazione (in produzione: etichettatura umana)
new_labeled = [unlabeled_pool[i] for i in selected_idx]
labeled_data.extend(new_labeled)
# Riaddestra su dati aggiornati
model = fine_tune(model, labeled_data)
acc = evaluate(model)
print(f"Iter {iteration}: {len(labeled_data)} esempi, acc={acc:.3f}")
return model
# Con 500 esempi attivi vs 5000 casuali: stesso livello di accuracy
# Risparmio training: -90% dati -> -85% emissioni
Trénink zaměřený na uhlík: Naplánujte si trénink inteligentně
Školení Carbon Aware je uplatněním principů sady Carbon Aware SDK do světa ML: místo zahájení školení, když inženýr dokončí konfiguraci experimentu naplánujeme práci na čas a v regionu s nejnižší uhlíková náročnost energetického mixu.
Časový posun: Když zelený trénink
Uhlíková náročnost energie se během dne enormně mění a týden, v závislosti na dostupnosti obnovitelných zdrojů. v Itálii, rozdíl mezi nejzelenějšími hodinami (11:00-15:00 v létě) a nejvíce uhlí (19:00–22:00 v zimě) může být 200–300 g CO₂ekv/kWh.
import asyncio
import httpx
from datetime import datetime, timedelta
from typing import Optional
import subprocess
ELECTRICITY_MAPS_TOKEN = "YOUR_TOKEN" # electricitymaps.com/api
async def get_carbon_intensity(zone: str = "IT") -> float:
"""Recupera l'intensità' carbonica attuale dalla Electricity Maps API."""
async with httpx.AsyncClient() as client:
resp = await client.get(
f"https://api.electricitymap.org/v3/carbon-intensity/latest",
params={"zone": zone},
headers={"auth-token": ELECTRICITY_MAPS_TOKEN}
)
data = resp.json()
return data["carbonIntensity"] # gCO2eq/kWh
async def get_forecast(zone: str = "IT", hours: int = 24) -> list[dict]:
"""Recupera le previsioni di intensità' carbonica per le prossime ore."""
async with httpx.AsyncClient() as client:
resp = await client.get(
f"https://api.electricitymap.org/v3/carbon-intensity/forecast",
params={"zone": zone},
headers={"auth-token": ELECTRICITY_MAPS_TOKEN}
)
data = resp.json()
return data["forecast"][:hours]
async def find_optimal_training_window(
job_duration_hours: float,
zone: str = "IT",
max_delay_hours: int = 24
) -> Optional[datetime]:
"""
Trova la finestra temporale ottimale per un training job.
Cerca il window di 'job_duration_hours' con intensità' media minima.
"""
forecast = await get_forecast(zone, hours=max_delay_hours + int(job_duration_hours))
if not forecast:
return None
window_size = max(1, int(job_duration_hours))
best_start = None
best_avg_intensity = float('inf')
for i in range(len(forecast) - window_size + 1):
window = forecast[i:i + window_size]
avg_intensity = sum(h['carbonIntensity'] for h in window) / len(window)
if avg_intensity < best_avg_intensity:
best_avg_intensity = avg_intensity
best_start = datetime.fromisoformat(forecast[i]['datetime'])
print(f"Finestra ottimale: {best_start}")
print(f"Intensità' media: {best_avg_intensity:.1f} gCO2eq/kWh")
return best_start
async def carbon_aware_submit(
training_command: str,
job_duration_hours: float = 6.0,
threshold_gco2_kwh: float = 200.0,
zone: str = "IT"
):
"""
Submette un training job solo quando l'intensità' e' sotto soglia,
altrimenti aspetta la finestra ottimale.
"""
current = await get_carbon_intensity(zone)
if current <= threshold_gco2_kwh:
print(f"Intensità' attuale {current} gCO2/kWh: avvio immediato")
subprocess.Popen(training_command.split())
return
print(f"Intensità' troppo alta ({current} gCO2/kWh > {threshold_gco2_kwh})")
optimal_window = await find_optimal_training_window(
job_duration_hours, zone
)
if optimal_window:
wait_seconds = (optimal_window - datetime.now()).total_seconds()
print(f"Scheduling per {optimal_window} (attesa: {wait_seconds/3600:.1f}h)")
await asyncio.sleep(max(0, wait_seconds))
subprocess.Popen(training_command.split())
# Utilizzo
asyncio.run(carbon_aware_submit(
training_command="python train_bert.py --epochs 10",
job_duration_hours=8.0,
threshold_gco2_kwh=150.0,
zone="IT"
))
Prostorový posun: Vyberte oblast nejzelenějšího mraku
Různí poskytovatelé cloudu nabízejí regiony s velmi odlišným energetickým mixem. Výběr tréninkového regionu může snížit emise o 70–90 % ve srovnání s náhodným výběrem.
Průměrná uhlíková intenzita podle oblasti cloudu (2024–2025)
| Poskytovatelé | Kraj | Umístění | gCO₂ekv/kWh | Poznámky |
|---|---|---|---|---|
| GCP | Evropa-sever 1 | Finsko | ~35 | Vodní + větrná |
| AWS | eu-sever-1 | Stockholm | ~40 | Téměř 100% obnovitelné |
| GCP | Evropa-západ 1 | Belgie | ~56 | Obnovitelný + jaderný mix |
| Blankyt | franciecentral | Paříž | ~58 | Nukleární dominanta |
| AWS | eu-západ-1 | Irsko | ~250 | Převládá zemní plyn |
| AWS | nás-východ-1 | Virginie | ~296 | Směs Středního východu USA |
| AWS | ap-jihovýchod-1 | Singapur | ~408 | Zemní plyn |
# Spot Instances per training carbon-aware
# Le spot instance non solo riducono i costi del 60-90%,
# ma tendono a essere distribuite su hardware più' recente ed efficiente
import boto3
from botocore.exceptions import ClientError
def submit_spot_training(
image_uri: str,
instance_type: str = "p4d.24xlarge", # 8x A100
region: str = "eu-north-1", # Stoccolma: ~40 gCO2/kWh
max_price_per_hour: float = 15.0
):
"""Submette un training job su spot instances AWS SageMaker."""
sagemaker = boto3.client('sagemaker', region_name=region)
response = sagemaker.create_training_job(
TrainingJobName=f"green-ml-{int(datetime.now().timestamp())}",
AlgorithmSpecification={
'TrainingImage': image_uri,
'TrainingInputMode': 'FastFile'
},
ResourceConfig={
'InstanceType': instance_type,
'InstanceCount': 1,
'VolumeSizeInGB': 100
},
# Managed Spot Training
EnableManagedSpotTraining=True,
StoppingCondition={
'MaxRuntimeInSeconds': 86400, # 24 ore max
'MaxWaitTimeInSeconds': 172800 # Aspetta fino a 48 ore
},
# Checkpointing per riprendere se lo spot viene interrotto
CheckpointConfig={
'S3Uri': f's3://my-bucket/checkpoints/',
'LocalPath': '/opt/ml/checkpoints'
}
)
return response['TrainingJobArn']
# Confronto costi e emissioni:
# p4d.24xlarge on-demand (us-east-1): $32.77/h, 296 gCO2/kWh
# p4d.24xlarge spot (eu-north-1): $9.83/h, 40 gCO2/kWh
# Risparmio economico: -70%
# Risparmio emissioni: -86% (spot + regione verde)
Optimalizace inference: 77 % uhlíkové stopy
Jak se očekávalo, dedukce ve výrobě dominuje emisím v životním cyklu ML modely. U modelu s miliony uživatelů se snížila každá milisekunda latence a každý watt snížené spotřeby se násobí miliardami požadavků ročně. Hlavními technikami jsou kvantizace, kompilace modelu a optimalizované dávkování.
Kvantování: INT8, INT4 a GPTQ
Kvantování snižuje numerickou přesnost modelových závaží z FP32 nebo FP16 na 8 nebo 4 bitová celá čísla. To snižuje požadavky na paměť o 50-75%, urychluje vyvozování 2-4x a úměrně snižuje spotřebu energie.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
# Quantizzazione INT4 con GPTQ (post-training quantization)
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True, # QLoRA: double quantization
bnb_4bit_quant_type="nf4" # Normal Float 4: migliore qualità'
)
model_id = "meta-llama/Llama-2-7b-hf"
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quantization_config,
device_map="auto",
torch_dtype=torch.bfloat16
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Verifica riduzione memoria
original_size_gb = 7 * 2 / 1024 # 7B param x 2 byte (FP16) / 1024
quantized_size_gb = 7 * 0.5 / 1024 # 7B param x 0.5 byte (INT4) / 1024
print(f"FP16: {original_size_gb:.1f} GB")
print(f"INT4: {quantized_size_gb:.1f} GB (-{(1-quantized_size_gb/original_size_gb)*100:.0f}%)")
# Quantizzazione INT8 con ONNX Runtime (per produzione)
from optimum.onnxruntime import ORTModelForSequenceClassification
from optimum.onnxruntime.configuration import AutoQuantizationConfig
# Esporta in ONNX e quantizza
ort_model = ORTModelForSequenceClassification.from_pretrained(
"bert-base-uncased",
export=True
)
quantization_config = AutoQuantizationConfig.avx512_vnni(
is_static=False, # Dynamic quantization (no calibration data needed)
per_channel=False
)
# Salva il modello quantizzato
from optimum.onnxruntime import ORTQuantizer
quantizer = ORTQuantizer.from_pretrained(ort_model)
quantizer.quantize(
save_dir="./bert-int8-onnx",
quantization_config=quantization_config
)
# Benchmark:
# BERT-Base FP32: 23ms latenza, 100% accuracy, 1.6 GB
# BERT-Base INT8: 12ms latenza, 99.2% accuracy, 0.4 GB -> -48% energia
# BERT-Base INT4: 8ms latenza, 97.8% accuracy, 0.2 GB -> -65% energia
vLLM: Efektivní poskytování pro LLM
vLLM je to obslužný rámec pro LLM, který používá PagedAttention pro mnohem efektivnější správu KV cache. Ve srovnání s naivní porcí, vLLM zvyšuje propustnost 15-24x se stejným hardwarem, což se úměrně snižuje spotřeba energie na vygenerovaný token.
from vllm import LLM, SamplingParams
from codecarbon import EmissionsTracker
# Avvia LLM con vLLM (PagedAttention + continuous batching)
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
tensor_parallel_size=1, # GPU count
gpu_memory_utilization=0.90, # Usa il 90% della VRAM per KV cache
max_num_batched_tokens=32768, # Batch maggiori = più' efficiente
quantization="awq" # AWQ quantization integrata
)
sampling_params = SamplingParams(
temperature=0.7,
max_tokens=256
)
# Misura emissioni per 1000 richieste
tracker = EmissionsTracker(project_name="vllm-inference-benchmark")
tracker.start()
prompts = ["Spiega il concetto di machine learning in italiano"] * 1000
outputs = llm.generate(prompts, sampling_params)
emissions = tracker.stop()
tokens_generated = sum(len(o.outputs[0].token_ids) for o in outputs)
print(f"Token generati: {tokens_generated:,}")
print(f"Emissioni: {emissions*1000:.2f} gCO2eq")
print(f"gCO2eq per 1000 token: {emissions*1000/tokens_generated*1000:.4f}")
# Confronto con serving naive HuggingFace:
# HuggingFace Transformers: 1.000 req, 45 min, 890 gCO2eq
# vLLM: 1.000 req, 3 min, 59 gCO2eq (-93%)
# Throughput: 333 req/min vs 22 req/min
SCI Score for ML Models: Standardizing Measurement
Specifikace Software SCI (Carbon Intensity Software) nadace Green Software Foundation, nyní norma ISO/IEC 21031:2024, platí také pro systémy ML. SCI vyjadřuje emise na funkční jednotku, což umožňuje smysluplné srovnání mezi různými modely.
Formule SCI aplikovaná na ML Systems
| Komponent | ML vzorec | BERT Inference příklad |
|---|---|---|
| E (Energie) | Výkon GPU x čas / 1000 | 300W x 0,05s / 1000 = 0,000015 kWh |
| I (Intenzita uhlíku) | gCO₂ekv/kWh regionu | 420 g CO₂ekv/kWh (průměr Itálie) |
| M (vtělený) | Hardware CO₂ / (životnost x využití) | 150 000 g CO₂ / (26 280 h x 0,7) = 8,2 g/h |
| R (funkční jednotka) | Vygenerováno 1 000 odvození nebo 1 token | 1000 klasifikací |
| LYŽE | (E x I + M) / R | (0,015 x 0,420 + 0,00023) / 1 = 0,0065 g CO₂ekv/požadavek |
from dataclasses import dataclass
from typing import Literal
@dataclass
class MLSystemSCI:
"""Calcola SCI Score per sistemi ML."""
model_name: str
gpu_count: int
gpu_tdp_watts: float
avg_latency_ms: float # Per inferenza singola
carbon_intensity_g_kwh: float # gCO2/kWh regione
gpu_lifespan_hours: float = 26_280 # 3 anni
gpu_embodied_gco2: float = 150_000 # ~150 kgCO2 per GPU
utilization: float = 0.70
pue: float = 1.3
functional_unit: Literal['request', 'token'] = 'request'
def operational_energy_kwh(self) -> float:
"""Energia operativa per singola inferenza."""
return (
self.gpu_count
* self.gpu_tdp_watts
* (self.avg_latency_ms / 1000)
/ 1_000 # W -> kW
)
def operational_emissions_g(self) -> float:
"""Emissioni operative per singola inferenza (gCO2eq)."""
return (
self.operational_energy_kwh()
* self.carbon_intensity_g_kwh
* self.pue
)
def embodied_per_request_g(self) -> float:
"""Quota embodied per singola inferenza."""
# Secondi per richiesta / secondi per vita GPU
fraction_of_life = (self.avg_latency_ms / 1000) / (
self.gpu_lifespan_hours * 3600
)
total_embodied = self.gpu_count * self.gpu_embodied_gco2
return total_embodied * fraction_of_life / self.utilization
@property
def sci_score(self) -> float:
"""SCI = (E x I + M) / R per singola richiesta."""
return self.operational_emissions_g() + self.embodied_per_request_g()
# Confronto modelli
models = [
MLSystemSCI("BERT-Base INT8/CPU", 0, 100, 45, 420, gpu_count=0,
gpu_embodied_gco2=0),
MLSystemSCI("BERT-Base FP32/A100", 1, 400, 12, 420),
MLSystemSCI("BERT-Base INT8/A100", 1, 280, 6, 420),
MLSystemSCI("DistilBERT FP16/A100", 1, 240, 5, 420),
MLSystemSCI("BERT-Base INT8/eu-north-1", 1, 280, 6, 40), # Stoccolma
]
print(f"{'Modello':<35} {'SCI (gCO2/req)':<18} {'vs Baseline'}")
baseline = models[0].sci_score
for m in models:
sci = m.sci_score
ratio = sci / baseline
print(f"{m.model_name:<35} {sci:.6f} gCO2 {ratio:.2f}x")
Zelený žebříček AI: Účinnost nad přesností
Tradiční výsledkové tabulky jako GLUE, SuperGLUE a MMLU měří pouze přesnost. Koncept Zelený žebříček AI, navržený Schwartzem et al. (2020) a formalizované GSF v roce 2024, zavádí složené metriky, které vyvažují výkon a uhlíková účinnost.
Zelené metriky umělé inteligence: Kompromis přesnosti a emisí (srovnávací test GLUE)
| Model | GLUE Skóre | Vlak CO₂eq (t) | CO₂eq odvodit (mg/req) | Zelené skóre* |
|---|---|---|---|---|
| BERT-Base | 82,1 | 0,9 | 0,62 | 132 |
| RoBERTa-Base | 86,4 | 4.1 | 0,62 | 139 |
| DistilBERT | 77,0 | 0,35 | 0,31 | 248 |
| BERT-Base INT8 | 81,3 | 0,9 | 0,28 | 290 |
| MobileBERT | 78,2 | 0,6 | 0,18 | 434 |
| ALBERT-Base v2 | 82,3 | 0,5 | 0,42 | 196 |
* Zelené skóre = (skóre GLUE / odvození ekv. CO₂) x 1000. Vyšší hodnoty = efektivnější.
Všimněte si, jak DistilBERT, navzdory skóre GLUE o 6 % nižším než BERT-Base, má téměř dvojnásobné zelené skóre. MobileBERT nabízí nejlepší zelené skóre na seznamu, což z něj činí optimální volbu pro rozsáhlá nasazení s omezenými uhlíkovými rozpočty.
Případová studie: 60% snížení emisí u modelu NLP
Tato případová studie popisuje cestu optimalizace v reálném světě aplikovanou na model sentimentové klasifikace pro italský trh, vyvinuté pro společnost e-commerce s 2 miliony měsíčních recenzí ke zpracování.
Výchozí stav: Výchozí stav
# STATO INIZIALE (Baseline)
# Modello: bert-base-multilingual-cased (177M parametri)
# Hardware: 1x NVIDIA A100 80GB SXM4 (on-demand AWS us-east-1)
# Task: classificazione sentiment 5 classi (1-5 stelle)
# Dataset: 500.000 recensioni in italiano
# Metriche baseline:
Training_time_hours = 18.5
Energy_training_kWh = 130.0 # A100 SXM4: ~400W TDP, PUE=1.5
CO2_training_kgCO2eq = 38.5 # 130 kWh x 0.296 kgCO2/kWh (us-east-1)
Inference_latency_ms = 35.0 # Per singola recensione
Inference_throughput_req_s = 28.6
CO2_inference_per_1M_req = 2.85 # kgCO2eq
Monthly_inference_requests = 2_000_000
Monthly_inference_CO2_kg = 5.70
Annual_training_runs = 4 # Re-training trimestrale
Annual_total_CO2_kg = (4 * 38.5) + (12 * 5.70) = 222.4
Accuracy_f1_macro = 0.847
Optimalizace krok za krokem
# STEP 1: Cambio regione cloud (us-east-1 -> eu-north-1)
# Carbon intensity: 296 -> 40 gCO2/kWh (-86%)
# Nessun cambiamento al codice, solo flag AWS Region
CO2_training_kgCO2eq_step1 = 130.0 * 0.040 * 1.5 = 7.8 # -80%
Monthly_inference_CO2_step1 = 2.85 * (40/296) = 0.38 # -87%
Annual_CO2_step1 = (4 * 7.8) + (12 * 0.38) = 35.7 kg # -84%
# STEP 2: Cambio modello base (multilingual -> umberto italiano)
# umberto-commoncrawl-cased (bert-base size ma solo italiano)
# Dataset training ridotto del 30% (solo dati italiani puliti)
# Curriculum learning: 15 epoche vs 20 -> -25% training time
CO2_training_kgCO2eq_step2 = 7.8 * 0.75 * 0.70 = 4.1 # -47% su step1
Accuracy_f1_macro_step2 = 0.861 # +1.4% grazie a modello specializzato
# STEP 3: Quantizzazione INT8 (ONNX Runtime)
# Latenza inferenza: 35ms -> 18ms (-49%)
# Throughput: 28.6 -> 55.5 req/s (+94%)
Inference_latency_ms_step3 = 18.0
Monthly_inference_CO2_step3 = 0.38 * 0.50 = 0.19 # -50%
Accuracy_f1_macro_step3 = 0.856 # -0.5% accettabile
# STEP 4: Carbon-aware scheduling del re-training
# Spot instances + finestre energetiche verdi
# Costo spot eu-north-1: -70% vs on-demand
# Timing training nelle ore di massima rinnovabile
CO2_training_kgCO2eq_step4 = 4.1 * 0.85 = 3.5 # Spot: stesso hardware, timing migliore
# RIEPILOGO OTTIMIZZAZIONI
print("=" * 60)
print(f"Baseline: {222.4:.1f} kgCO2eq/anno | F1: 0.847")
print(f"Step 1: {35.7:.1f} kgCO2eq/anno | -84% (solo regione)")
print(f"Step 2: {26.9:.1f} kgCO2eq/anno | -87% (modello+data)")
print(f"Step 3: {21.7:.1f} kgCO2eq/anno | -90% (quantizzazione)")
print(f"Step 4: {18.6:.1f} kgCO2eq/anno | -92% (carbon-aware)")
print(f"F1 finale: 0.856 vs 0.847 baseline (+1.1%)")
print("=" * 60)
print(f"Riduzione CO2: -203.8 kgCO2eq/anno (-91.6%)")
print(f"Risparmio costi: -74% (spot + regione + efficienza)")
Výsledky případové studie: Shrnutí
| Metrický | Základní linie | Optimalizováno | Variace |
|---|---|---|---|
| Celkový roční CO₂ekv | 222 kg CO₂ekv | 19 kg CO₂ekv | -91 % |
| Makro F1 skóre | 0,847 | 0,856 | +1,1 % |
| Inferenční latence | 35 ms | 18 ms | -49 % |
| Propustnost | 28 požadavků/s | 55 požadavků/s | +96 % |
| Měsíční náklady na cloud | ~2 400 EUR | ~620 EUR | -74 % |
Klíčová lekce: 90 % emisí je sníženo bez obětování přesnosti
V této případové studii má každý krok optimalizace zlepšila nebo zachovat přesnost modelu. Výběr uložené oblasti cloudu 84 % emisí bez dotyku řádku kódu. Specializace na šablona pro italský jazyk má zlepšenou kvalitu. Kvantování snížilo to latenci na polovinu. Zpráva je jasná: optimalizujte pro uhlík stopa a optimalizace kvality nejsou protichůdné cíle.
Zelený plán umělé inteligence pro organizace
Přijetí zelené umělé inteligence nevyžaduje okamžitou revoluci ve všem. Cestovní mapa ve třech fázích vám umožňuje zavádět postupy postupně, počínaje optimalizace s větším dopadem a menším úsilím.
Zelený plán přijetí umělé inteligence ve 3 fázích
| Fáze | Časová osa | Akce | Očekává se snížení CO₂ |
|---|---|---|---|
| Krok 1: Změřte | Týden 1-4 |
Nainstalujte CodeCarbon na všechny tréninkové úlohy; definovat základní hodnoty emisí pro každý model; zvolte zelenější cloudové oblasti |
50–85 % (pouze region) |
| Krok 2: Optimalizujte | Měsíc 2-4 |
Použijte smíšenou přesnost (BF16) na všechny tréninky; kvantovat modely ve výrobě (INT8); přijmout spotové instance pro dávkové školení |
Dalších 30–50 % |
| Fáze 3: Integrace | Měsíc 5-12 |
Automatické plánování s ohledem na uhlík; Interní zelený žebříček AI; SCI skóre v kritériích nasazení; ESG hlásí ML emise |
Dalších 10–20 % |
Zelený kontrolní seznam AI pro každou školicí práci
# Checklist Green AI da seguire prima di ogni training
# Copia in: .github/PULL_REQUEST_TEMPLATE.md o come commento training script
CHECKLIST_GREEN_AI = """
Green AI Pre-Training Checklist
================================
[ ] 1. REGIONE: Training schedulato in regione con CI < 150 gCO2/kWh?
Verifica: https://app.electricitymaps.com/zone/IT
Preferisci: GCP europe-north1, AWS eu-north-1, Azure swedencentral
[ ] 2. TIMING: Carbon-aware scheduling attivato?
Tool: Carbon Aware SDK o script custom
Finestra ottimale: verificata nelle ultime 24h
[ ] 3. HARDWARE: GPU di ultima generazione disponibile?
H100 >> A100 (44% più' efficiente)
Spot/preemptible instances preferite
[ ] 4. PRECISION: Mixed precision attivata (BF16/FP16)?
HuggingFace: bf16=True in TrainingArguments
PyTorch: torch.autocast('cuda', dtype=torch.bfloat16)
[ ] 5. EARLY STOPPING: Configurato con CarbonTracker per proiezione?
Stima emissioni dopo 5 epoche e confronta con budget CO2
[ ] 6. TRACKING: CodeCarbon configurato?
Country_iso_code, cloud_provider, cloud_region impostati
Output in: ./carbon_reports/
[ ] 7. DATI: Dataset ottimizzato con deduplication e qualità'?
Almeno 10% redundancy rimossa
Active learning per ridurre dimensione se possibile
[ ] 8. BASELINE: Esiste una run precedente da confrontare?
Registra su MLflow: accuracy, emissioni, ratio
[ ] 9. INFERENZA: Quantizzazione pianificata per produzione?
Target: INT8 con ONNX Runtime o INT4 per LLM
[ ] 10. REPORTING: Emissioni saranno incluse nel model card?
Usa: SCI Score, kgCO2eq training, gCO2eq/1000 req inferenza
"""
print(CHECKLIST_GREEN_AI)
Závěry: Shrnutí série Green Software Engineering
Tento článek uzavírá sérii Zelené softwarové inženýrství, cesta v 10 článcích, která překročila celé spektrum praktik udržitelný vývoj softwaru. Od teorie principů GSF k implementacím praktiky s CodeCarbon, Carbon Aware SDK, Climatiq API, až po techniky pokročilá optimalizace ML: vytvořili jsme komplexní sadu nástrojů pro vývojáři a organizace, které chtějí snížit svůj digitální dopad na životní prostředí.
10 klíčových poselství série
| # | Položka | Klíčová zpráva |
|---|---|---|
| 1 | Principy GSF | Uhlíková účinnost je měřítkem kvality softwaru |
| 2 | KódCarbon | Nemůžete snížit to, co neměříte: začněte ode dne 1 |
| 3 | Climatiq API | CO₂ má API: integrujte uhlíkové účtování do vašeho backendu |
| 4 | Carbon Aware SDK | Přesunutí pracovní zátěže v čase nebo prostoru může snížit o 90 % |
| 5 | Modelování rozsahu | SCI je norma ISO pro porovnávání uhlíkové účinnosti softwaru |
| 6 | GreenOps | Zelená a FinOps jsou v souladu: optimalizace CO₂ snižuje náklady na cloud |
| 7 | Rozsah 3 Potrubí | Nepřímé emise jsou často větší než přímé emise |
| 8 | ESG a CSRD | Od roku 2025 je digitální reporting ESG pro mnoho společností zákonnou povinností |
| 9 | Udržitelné vzory | Cache, batch a async nejsou jen výkon: jsou to zelené vzory |
| 10 | AI Carbon | Výběr oblasti cloudu snižuje emise ML více než jakýkoli jiný algoritmus |
Moment je nyní
Generativní AI bude nadále růst. Modely budou větší, čím častější trénink, tím pronikavější nasazení. Otázka není pokud se emise AI zvýší – stejně se zvýší – ale o kolik. Techniky v tomto článku ukazují, že je možné snížit o 60–90 % emise systému ML bez obětování přesnosti a často dokonce snížení náklady. To není kompromis: je to vítězství na všech frontách.
Green Software Foundation odhaduje, že pokud by každý tým ML přijal postupy školení zaměřené na uhlík a kvantování závěrů, globálních emisí tohoto sektoru AI by mohla být snížena o 40–60 % do roku 2030 ve srovnání se scénářem jako obvykle. Nepotřebujeme technologické průlomy: potřebujeme popsané postupy v těchto deseti článcích aplikujte systematicky.
Další krok je váš. Nainstalujte si CodeCarbon na další tréninkovou práci. Zkontrolujte uhlíkovou intenzitu vašeho regionu AWS nebo GCP. Kvantitovat model před jeho nasazením. Změřte skóre SCI. a když to uděláš, uděláte nejdůležitější krok: začnete.
Užitečné odkazy a nástroje
- KódCarbon: mlco2.github.io/codecarbon
- Kalkulačka dopadu ML CO₂: mlco2.github.io/impact
- Kalkulačka zelených algoritmů: green-algorithms.org
- Electricity Maps API: electricmaps.com/api
- Specifikace GSF SCI: sci.greensoftware.nadace
- Sledování emisí na obličeji: HuggingFace Hub Carbon Tracking
- Služba vLLM: docs.vllm.ai
- ONNX Runtime Optimization: onnxruntime.ai
Pokračujte v cestě: Související série
- MLOps for Business: Další informace o nasazení modelů ML pomocí Potrubí MLflow, DVC a CI/CD – včetně bran kvality uhlíkové stopy.
- AI inženýrství a RAG: Prozkoumejte, jak vytvořit systémy RAG efektivní, které minimalizují počet volání do modelů LLM a snižují obojí náklady na emise.
- Obchod s daty a AI: Zjistěte, jak AI Act EU a předpisy ESG se prolínají s praktikami zelené umělé inteligence a jak sestavit cestovní mapu udržitelné údaje založené na malých a středních podnicích.







