Sztuczna inteligencja i węgiel: pomiar i zmniejszanie śladu szkoleń ML
Szkolenie GPT-4 pochłonęło ok 50 GWh energii elektrycznej, wystarczające do zasilania ponad 4600 europejskich domów przez cały rok. GPT-3, jego poprzednik, on wyprodukował 502 tony ekwiwalentu CO₂ podczas szkolenia — odpowiednik 112 samochodów benzynowych pokonujących rocznie 20 000 km każdy. BLOOM, model open source zawierający 176 miliardów parametrów, przeszkolony we Francji w zakresie energii mieszane, wydał 25 ton równoważnika CO₂ dzięki powszechnemu użyciu energii jądrowej i odnawialnej.
To nie są ciekawostki statystyczne: to oznaki szybko rozwijającego się problemu strukturalnego przyspieszenie. Generatywna sztuczna inteligencja rośnie w tempie wykładniczym, według wzorców coraz większe, coraz większe zbiory danych i coraz dłuższe cykle szkoleniowe częste. Według badania opublikowanego w Natura w 2024 r. emisje związane z Jeśli nie zostaną podjęte żadne działania, szkolenie w zakresie modeli sztucznej inteligencji może się potroić do 2027 r efektywności systemowej. MAE szacuje, że centra danych dedykowane AI w 2026 r. pochłoną więcej energii niż wiele średnich państw europejskich.
Jednak zdecydowana większość zespołów ML rozpoczyna szkolenia na klastrach GPU, nigdy nie przeprowadzając pomiarów wytworzonych emisji. Nie dlatego, że im to nie przeszkadza, ale dlatego, że brakuje im narzędzi zintegrowane z codziennym przepływem pracy, wspólne standardowe metryki i kultura pomiarów. W ostatnim artykule z tej serii Inżynieria zielonego oprogramowania będziemy odkrywać cały cykl życia śladu węglowego w uczeniu maszynowym: od precyzyjnego pomiaru za pomocą CodeCarbon i CarbonTracker, do optymalizacji architektonicznej poprzez przycinanie i destylację, aż po planowanie szkoleń uwzględniające emisję gazów cieplarnianych i optymalizację wnioskowania w produkcji.
Czego się nauczysz
- Dane rzeczywistej emisji dla modeli podstawowych: GPT-3, GPT-4, Lama 2, BLOOM, PaLM
- Zainstaluj i korzystaj z algorytmów CodeCarbon, CarbonTracker, ML CO₂ Impact i Green Algorithms
- Porównaj procesory graficzne pod kątem wydajności energetycznej: A100, H100, H200, B200 w FLOPS/W
- Techniki optymalizacji architektury: przycinanie, destylacja wiedzy, wydajny NAS
- Efektywność skoncentrowana na danych: jakość danych a ilość, nauczanie zawarte w programie nauczania
- Szkolenia uwzględniające emisję dwutlenku węgla: planuj obciążenia w regionach i godzinach o niskiej intensywności emisji dwutlenku węgla
- Optymalizacja wnioskowania: kwantyzacja INT8/INT4, ONNX Runtime, TensorRT, vLLM
- Oblicz wynik SCI dla modeli ML i zbuduj tabelę liderów ekologicznej sztucznej inteligencji
- Kompletne studium przypadku: redukcja emisji o 60% w prawdziwym modelu NLP
- Praktyczny plan wdrożenia zielonej sztucznej inteligencji w organizacjach
Seria Green Software Engineering — 10 artykułów
| # | Przedmiot | Główny temat |
|---|---|---|
| 1 | Zasady Fundacji Zielonego Oprogramowania | GSF, SCI, 8 podstawowych zasad |
| 2 | Pomiar śladu węglowego za pomocą CodeCarbon | Integracja CodeCarbon, CCF, CI/CD |
| 3 | Climatiq API i rozliczanie emisji dwutlenku węgla | REST API, LCA, Zakres 1-2-3 |
| 4 | SDK uwzględniający emisję dwutlenku węgla i przesunięcie czasowe/przestrzenne | Przenieś obciążenie pracą na zieloną energię |
| 5 | Modelowanie zakresu i wdrażanie SCI | Praktyczne obliczenia SCI, Ramy wpływu |
| 6 | GreenOps: FinOps na rzecz zrównoważonego rozwoju | Koszt chmury i emisja dwutlenku węgla, Kubernetes |
| 7 | Zakres 3 w potoku oprogramowania | Emisje pośrednie, cyfrowy łańcuch dostaw |
| 8 | ESG, CSRD i raportowanie cyfrowe | Zgodność europejska, ESRS E1, ujawnienie |
| 9 | Zrównoważone wzorce architektoniczne | Przechowywanie, buforowanie, partia uwzględniająca węgiel |
| 10 | Sztuczna inteligencja i węgiel: ślad szkoleniowy ML | Ten artykuł — ostatni artykuł z tej serii |
Rzeczywisty ślad węglowy modeli podstawowych
Zrozumienie skali problemu wymaga twardych danych. badacze ze Stanfordu Hugging Face i MLCommons rozpoczęły publikowanie wskaźników emisji dla głównych firm modele językowe. Poniższa tabela agreguje dostępne dane, mając to na uwadze wiele firm — szczególnie OpenAI — nadal nie ujawnia tych informacji.
Emisje CO₂eq modeli podstawowych podczas szkolenia
| Model | Parametry | Energia (MWh) | równoważnik CO₂ (t) | Region/mieszanka | Źródło |
|---|---|---|---|---|---|
| GPT-3 | 175B | 1287 | 502 | USA (średni miks) | Patterson i in. 2021 |
| GPT-4 | ~1,8 T (szac.) | ~ 50 000 | ~ 14 000 | USA (oszacowanie) | Niezależne szacunki 2023 |
| KWIAT | 176B | 433 | 25 | Francja (nuklearna+odnawialna) | Luccioni i in. 2022 |
| Lama 2 (70B) | 70B | ~700 | 539 | USA/Lazur | Meta FW 2023 |
| Palma | 540B | ~3400 | ~507 | USA (TPU v4) | Chowdhery i in. 2022 |
| Mistrala 7B | 7B | ~35 | ~12 | Europa (mieszanka) | Mistral FW 2023 |
| Sokół 180B | 180B | ~600 | ~117 | Zjednoczone Emiraty Arabskie (mieszanka) | TII 2023 |
| Klejnot 7B | 7B | ~32 | ~6 | USA/TPU (RE100) | Google DeepMind 2024 |
Dane te ujawniają trzy podstawowe wzorce. Pierwszym z nich jest przepaść geograficzna: BLOOM, przeszkolony we Francji w zakresie głównie energetyki jądrowej, wyemitował 20 razy mniej Lamy 2 w tym samym rzędzie wielkości. Drugie toefekt skali: przejście z parametrów 7B na 176B nie oznacza po prostu 25 razy większej emisji — rozproszone koszty komunikacji i długość szkolenia rosną nieliniowo. Trzeci to luka w przejrzystości: Większość firm tego nie robi nadal publikuje te dane, co utrudnia porównania i uniemożliwia przeprowadzenie analiz porównawczych bez niezależnych pomiarów.
Paradoks wnioskowania: większy niż trening
Wbrew intuicji, skumulowane emisjewnioskowanie często przekraczają te związane ze szkoleniem w cyklu życia modelu. Model taki jak ChatGPT, z milionami żądań dziennie, może zużyć więcej energii w miesiącu produkcji całego oryginalnego szkolenia. Patterson i in. oszacować, że wnioskowanie GPT-3 na skalę ChatGPT produkuje ok 11 000 ton ekwiwalentu CO₂ rocznie. To przesuwa nacisk z optymalizacji uczenia się na optymalizację wnioskowania jako głównym priorytetem jest zmniejszenie całkowitego wpływu na środowisko.
Ucieleśnione emisje i pełny cykl życia
Analiza śladu węglowego AI nie może ograniczać się do energii zużytej w trakcie szkolenie. The ucieleśnione emisje sprzętu — wyemitowany CO₂ do produkcji procesorów graficznych, serwerów, sieci chłodzących i infrastruktury – reprezentują znaczący udział. Wyprodukowanie pojedynczego chipa H100 emituje ok 150 kg CO₂ekw, a klaster składający się z 1000 procesorów graficznych powoduje emisję zanieczyszczeń o wartości około 150 ton w przypadku samego sprzętu, nawet przed rozpoczęciem pojedynczego szkolenia.
# 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
Narzędzia pomiarowe: od CodeCarbon po zielone algorytmy
Pomiar emisji ML wymaga narzędzi zaprojektowanych specjalnie pod kątem obciążeń ML szkolenie i wnioskowanie. Przestrzeń dominują cztery narzędzia: CodeCarbon, CarbonTracker, Kalkulator wpływu ML CO₂ i zielone algorytmy. Każdy ma określone mocne strony i optymalne przypadki użycia.
CodeCarbon: Bezpośrednia integracja z kodem Pythona
CodeCarbon to najpopularniejsze narzędzie do pomiaru emisji podczas Szkolenie M.L. Jego integracja z najpopularniejszymi frameworkami (PyTorch, TensorFlow, Hugging Face Transformers) sprawia, że jest to naturalny wybór dla większości zespołów.
# 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: Projekcje i budżetowanie
CarbonTracker, opracowany przez Uniwersytet w Kopenhadze, wyróżnia się swoją wydajnością z całkowite zużycie projektu na podstawie pierwszych okresów szkoleniowych. Ta funkcjonalność jest nieoceniona: pozwala oszacować koszt emisji dwutlenku węgla przed ukończeniem szkolenia, które trwa kilka dni lub tygodni.
# 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")
Kalkulator wpływu ML CO₂ i zielone algorytmy
Kalkulator wpływu ML CO₂ (mlco2.github.io) to narzędzie internetowe który szacuje emisję na podstawie sprzętu, dostawcy chmury, regionu i czasu trwania. Nie wymaga Integracja z kodem: Idealny do szybkich szacunków lub dokumentacji przed szkoleniem kwestie szkoleniowe już zakończone. Obsługuje AWS, GCP, Azure i ponad 15 regionów.
Zielone algorytmy (green-algorithms.org), opracowanego przez Uniwersytet z Cambridge oferuje bardziej naukowe podejście do modeli zużycia energii zweryfikowane na rzeczywistych danych z centrum danych. Obsługuje obliczenia dla HPC (High Performance Computing), Klastry GPU i przepływy pracy w bioinformatyce.
Porównanie narzędzi do pomiaru węgla ML
| Instrument | Typ | Szczegółowość | Integracja | Punkt siły | Ograniczenie |
|---|---|---|---|---|---|
| KodWęgiel | Biblioteka Pythona | Funkcja/zawód | PyTorch, TF, H.F | Prawdziwy pomiar sprzętu | Tylko Python, obciążenie <1% |
| Śledzenie węgla | Biblioteka Pythona | Dla epoki | Pętle uczenia się głębokiego | Projekcje z wczesnym przystankiem | Wymaga szkolenia opartego na epokach |
| Wpływ ML CO₂ | Narzędzia internetowe | Poziom pracy | Brak (formularz internetowy) | Zero konfiguracji, szybka wycena | Tylko szacunki, nie pomiary |
| Zielone algorytmy | Narzędzia internetowe | Poziom pracy | Brak (formularz internetowy) | Naukowo potwierdzone modele | Nie w czasie rzeczywistym |
| Śledzenie wpływu eksperymentu | Biblioteka Pythona | Eksperyment | Eksperymenty ML | Automatyczne rejestrowanie MLflow | Najmniej utrzymany (2021) |
Panel kontrolny i automatyczne raportowanie
Pomiar ma wartość tylko wtedy, gdy dane są agregowane, wizualizowane i wykorzystywane decyzje. Skutecznym wzorcem jest integracja CodeCarbon z MLflow w celu utworzenia automatyczny system śledzenia, który rejestruje emisję wraz ze wskaźnikami wydajności.
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}
)
Wydajność energetyczna GPU: FLOPS na wat
Wybór sprzętu to decyzja, która ma największy wpływ na ślad węglowy szkolenia. Procesory graficzne nowej generacji oferują znacznie wyższą efektywność energetyczną w porównaniu do poprzedników i jaka może być różnica pomiędzy treningiem na A100 a H200 redukcję emisji o 40–60% przy tym samym obciążeniu pracą.
Porównanie procesorów graficznych dla szkoleń ML: efektywność energetyczna (2025)
| GPU | Rok | TDP (W) | TFLOPY FP16 | FLOPY/Wat | Pamięć HBM | Względny CO₂ |
|---|---|---|---|---|---|---|
| A100SXM4 | 2020 | 400 W | 312 | 780 GFLOPS/W | 80 GB HBM2e | Linia bazowa (1,0x) |
| H100SXM5 | 2022 | 700 W | 989 | 1,413 GFLOPS/W | 80 GB HBM3 | 0,56x (-44%) |
| H200SXM5 | 2024 | 700 W | 989 | 1,413 GFLOPS/W | HBM3e o pojemności 141 GB | 0,56x (-44%) |
| B200SXM6 | 2025 | 1000 W | 4500 | 4500 GFLOPS/W | HBM3e o pojemności 192 GB | 0,17x (-83%) |
| RTX4090 | 2022 | 450 W | 165 | 367 GFLOPS/W | 24 GB GDDR6X | 2,12x (+112%) |
| AMD MI300X | 2024 | 750 W | 1307 | 1,743 GFLOPS/W | 192 GB HBM3 | 0,45x (-55%) |
H100 i H200 oferują w przybliżeniu Redukcja emisji o 44%. szacunek do A100 przy tym samym obciążeniu, dzięki silnikowi transformatorowemu z 8PR i architekturze Zoptymalizowany NVLink. B200 reprezentuje skok pokoleniowy z 4,5 PFLOPS i 16 FP natywne wsparcie z 4PR, co doprowadzi do redukcji do 83%.
Mieszane szkolenie precyzyjne: FP16 i BF16
Szkolenie w mieszana precyzja (FP16 lub BF16 do obliczeń, FP32 dla parametry modelu) zmniejsza zużycie energii o 30-50% w porównaniu do treningu pełny FP32, bez znaczącego pogorszenia jakości 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
Optymalizacja architektury: przycinanie, destylacja i NAS
Techniki optymalizacji architektury zmniejszają złożoność modelu, co prowadzi do szybszego szkolenia, efektywniejszego wnioskowania i śladu węglowego ogólnie zmniejszona. Trzy główne techniki to przycinanie i destylacja wiedzy i wydajne wyszukiwanie architektury neuronowej.
Przycinanie modelu: Usuń nadmiarowość
Przycinanie eliminuje marginalnie wpływające parametry lub struktury modelu do dokładności. Istnieją dwa główne podejścia: przycinanie niestrukturalne (poszczególne wagi) e przycinanie strukturalne (głowy uwagi, neurony, warstwy). Ten ostatni jest lepszy ze względu na rzeczywistą wydajność sprzętu, ponieważ jest nieustrukturyzowany przycinanie wymaga sprzętu z niewielką obsługą, aby naprawdę przynosiło korzyści.
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
Destylacja wiedzy: małe modele z dużą wiedzą
Destylacja wiedzy przenosi wiedzę z jednego dużego modelu (nauczyciela) do jednego mały (student). Na przykład DistilBERT ma 40% parametrów BERT-Base, ale utrzymuje 97% swoich wyników w benchmarku GLUE. Emisja treningowa DistilBERT są o 60% niższe, a wnioskowane 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
Efektywne wyszukiwanie architektury neuronowej
Tradycyjny serwer NAS jest, jak na ironię, jednym z najbardziej energochłonnych procesów w ML: Poszukiwanie optymalnej architektury może wymagać tysięcy pełnych sesji szkoleniowych. The Wydajny serwer NAS wykorzystuje techniki takie jak jednorazowy NAS, podział wagi oraz wyszukiwanie oparte na predykatorach, co pozwala obniżyć koszty wyszukiwania 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)
Wydajność zorientowana na dane: jakość kontra ilość
Zestaw danych wyższej jakości pozwala osiągnąć tę samą dokładność z mniejszą liczbą epok szkoleniowych i mniejszą ilością danych. To jedna z zasad sztuczna inteligencja zorientowana na dane promowany przez Andrew Ng: zamiast zwiększać model lub surowych danych, poprawić jakość istniejących danych.
Program nauczania: szkolenie we właściwej kolejności
Program nauczania porządkuje przykłady szkoleniowe według rosnącego stopnia trudności, jak nauczyciel, który zaczyna od prostych pojęć, zanim przejdzie do skomplikowanych. Podejście to zapewnia zbieżność szybciej i przy mniejszej liczbie całkowitych epok, redukując ślad węglowy na poziomie 20–35% w przypadku standardowych wskaźników referencyjnych.
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
Aktywne uczenie się: wybierz najbardziej pouczające dane
Aktywne uczenie się iteracyjnie wybiera najbardziej pouczające przykłady, które można oznaczyć, zamiast używać całego zbioru danych. Osiąga się to przy budżecie na adnotacje wynoszącym 10–20%. często 90-95% dokładności uczenia pełnych danych, zmniejszając się proporcjonalnie ślad węglowy.
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
Szkolenia uwzględniające emisję dwutlenku węgla: inteligentnie planuj treningi
Szkolenie świadome emisji dwutlenku węgla polega na zastosowaniu zasad pakietu SDK Carbon Aware do świata ML: zamiast rozpoczynać szkolenie po zakończeniu konfiguracji przez inżyniera eksperymentu, planujemy zadanie w czasie i w regionie o najniższym poziomie intensywność emisji dwutlenku węgla w miksie elektroenergetycznym.
Przesunięcie w czasie: Kiedy zielone szkolenie
Intensywność węgla w energii zmienia się ogromnie w ciągu dnia tygodniowo, w zależności od dostępności odnawialnych źródeł energii. we Włoszech, różnica pomiędzy godzinami najbardziej zielonymi (11:00-15:00 latem) i najbardziej zielonymi węgiel (19:00–22:00 zimą) może wynosić 200–300 gCO₂eq/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"
))
Przesunięcie przestrzenne: wybierz najbardziej zielony region chmur
Różni dostawcy usług w chmurze oferują regiony o bardzo różnych koszykach energetycznych. Wybór regionu szkoleniowego może zmniejszyć emisję o 70-90% w porównaniu z wyborem losowym.
Średnia intensywność emisji dwutlenku węgla według regionu chmur (2024–2025)
| Dostawcy | Region | Lokalizacja | gCO₂eq/kWh | Notatki |
|---|---|---|---|---|
| GCP | Europa-Północ1 | Finlandia | ~35 | Hydroelektrownia + wiatr |
| AWS | eu-północ-1 | Sztokholm | ~40 | Prawie w 100% odnawialne |
| GCP | Europa-Zachód1 | Belgia | ~56 | Mieszanka odnawialna + nuklearna |
| Lazur | francusko-centralny | Paryż | ~58 | Dominacja nuklearna |
| AWS | eu-zachód-1 | Irlandia | ~250 | Dominował gaz ziemny |
| AWS | us-wschód-1 | Wirginia | ~296 | Mieszanka środkowo-wschodnich Stanów Zjednoczonych |
| AWS | ap-południowy wschód-1 | Singapur | ~408 | Gaz ziemny |
# 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)
Optymalizacja wnioskowania: 77% śladu węglowego
Zgodnie z przewidywaniami, wnioskowanie w procesie produkcji dominuje w emisjach w cyklu życia Modele M.L. W przypadku modelu z milionami użytkowników zmniejszono każdą milisekundę opóźnienia a każdy wat zmniejszonego zużycia mnoży się przez miliardy żądań rocznie. Główne techniki to kwantyzacja, kompilacja modelu i zoptymalizowane grupowanie.
Kwantyzacja: INT8, INT4 i GPTQ
Kwantyzacja zmniejsza precyzję numeryczną ciężarów modeli z FP32 lub FP16 do 8 lub 4-bitowych liczb całkowitych. Zmniejsza to zapotrzebowanie na pamięć o 50-75%, przyspiesza wnioskowanie 2-4x i proporcjonalnie zmniejsza zużycie energii.
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: Wydajna obsługa LLM
vLLM jest to platforma obsługująca LLM, która wykorzystuje PagedUwaga aby znacznie efektywniej zarządzać pamięcią podręczną KV. W porównaniu z naiwną porcją, vLLM zwiększa przepustowość 15–24 razy na tym samym sprzęcie, zmniejszając proporcjonalnie zużycie energii na wygenerowany 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
Wynik SCI dla modeli ML: pomiar standaryzacyjny
Specyfikacja SCI (oprogramowanie do pomiaru intensywności emisji dwutlenku węgla) Fundacji Zielonego Oprogramowania, obecnie norma ISO/IEC 21031:2024 ma zastosowanie również do systemów ML. SCI wyraża emisje na jednostkę funkcjonalną, umożliwiając znaczące porównania pomiędzy różnymi modelami.
Formuła SCI stosowana w systemach ML
| Część | Formuła M.L | Przykład wnioskowania BERT |
|---|---|---|
| E (Energia) | Moc GPU x czas / 1000 | 300 W x 0,05 s / 1000 = 0,000015 kWh |
| I (Intensywność emisji dwutlenku węgla) | gCO₂eq/kWh regionu | 420 gCO₂eq/kWh (średnia dla Włoch) |
| M (Wcielony) | Sprzęt CO₂ / (żywotność x zużycie) | 150 000 gCO₂ / (26280h x 0,7) = 8,2 g/h |
| R (jednostka funkcjonalna) | Wygenerowano 1000 wniosków lub 1 token | 1000 klasyfikacji |
| JEŹDZIĆ NA NARTACH | (E x I + M) / R | (0,015 x 0,420 + 0,00023) / 1 = 0,0065 gCO₂eq/req |
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")
Tablica liderów zielonej sztucznej inteligencji: wydajność ponad dokładność
Tradycyjne rankingi, takie jak GLUE, SuperGLUE i MMLU, mierzą jedynie dokładność. Koncepcja Tablica liderów zielonej sztucznej inteligencji, zaproponowany przez Schwartza i in. (2020) i sformalizowany przez GSF w 2024 r., wprowadza złożone wskaźniki, które równoważą wydajność i efektywność węglowa.
Wskaźniki zielonej sztucznej inteligencji: kompromis między dokładnością a emisją (benchmark GLUE)
| Model | Wynik KLEJU | Pociąg CO₂eq (t) | CO₂eq Wnioskowanie (mg/req) | Zielony wynik* |
|---|---|---|---|---|
| Baza BERT | 82.1 | 0,9 | 0,62 | 132 |
| Baza RoBERTa | 86,4 | 4.1 | 0,62 | 139 |
| DestylBERT | 77,0 | 0,35 | 0,31 | 248 |
| BERT-Baza INT8 | 81,3 | 0,9 | 0,28 | 290 |
| MobilBERT | 78.2 | 0,6 | 0,18 | 434 |
| ALBERT-Base v2 | 82.3 | 0,5 | 0,42 | 196 |
* Zielony wynik = (wynik KLEJU / wnioskowanie CO₂eq) x 1000. Wyższe wartości = większa wydajność.
Zwróć uwagę, że DistilBERT, pomimo wyniku GLUE Score o 6% niższego niż BERT-Base, ma prawie dwukrotnie wyższy wynik Green Score. MobileBERT oferuje najlepszy Green Score na liście, co czyni go optymalnym wyborem w przypadku wdrożeń na dużą skalę z ograniczonymi budżetami na emisję dwutlenku węgla.
Studium przypadku: 60% redukcja emisji w modelu NLP
W tym studium przypadku opisano ścieżkę optymalizacji w świecie rzeczywistym zastosowaną do modelu klasyfikacji nastrojów dla rynku włoskiego, opracowanej dla firmy e-commerce z 2 milionami miesięcznych recenzji do przetworzenia.
Linia bazowa: stan początkowy
# 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
Optymalizacja krok po kroku
# 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)")
Wyniki studium przypadku: podsumowanie
| Metryczny | Linie bazowe | Zoptymalizowany | Zmiana |
|---|---|---|---|
| Całkowity roczny równoważnik CO₂ | 222 kg CO₂ekw | 19 kg CO₂ekw | -91% |
| Makro wyniku F1 | 0,847 | 0,856 | +1,1% |
| Opóźnienie wnioskowania | 35 ms | 18 ms | -49% |
| Przepustowość | 28 żądań/s | 55 żądań/s | +96% |
| Miesięczny koszt chmury | ~2400 EUR | ~620 EUR | -74% |
Kluczowa lekcja: redukcja emisji o 90% bez utraty dokładności
W tym studium przypadku każdy etap optymalizacji ma ulepszony lub zachował dokładność modelu. Wybór regionu chmury został zapisany 84% emisji bez dotykania linijki kodu. Specjalizacja szablon dla języka włoskiego poprawił jakość. Kwantyzacja zmniejszyło to o połowę opóźnienie. Przesłanie jest jasne: optymalizuj pod kątem emisji dwutlenku węgla ślad i optymalizacja pod kątem jakości nie są sprzecznymi celami.
Plan działania dotyczący zielonej sztucznej inteligencji dla organizacji
Przyjęcie zielonej sztucznej inteligencji nie wymaga natychmiastowej rewolucjonizacji wszystkiego. Plan działania w trzech fazach pozwala na stopniowe wprowadzanie praktyk, zaczynając od optymalizacje z większym efektem i mniejszym wysiłkiem.
Plan działania na rzecz wdrożenia zielonej sztucznej inteligencji w 3 fazach
| Faza | Oś czasu | Działania | Oczekiwana redukcja CO₂ |
|---|---|---|---|
| Krok 1: Zmierz | Tydzień 1-4 |
Zainstaluj CodeCarbon we wszystkich zadaniach szkoleniowych; zdefiniuj wartości bazowe emisji dla każdego modelu; wybieraj bardziej zielone regiony chmur |
50-85% (tylko region) |
| Krok 2: Optymalizacja | Miesiąc 2-4 |
Stosuj precyzję mieszaną (BF16) we wszystkich treningach; kwantyzacja modeli w produkcji (INT8); przyjąć instancje punktowe do uczenia wsadowego |
Dodatkowe 30-50% |
| Faza 3: Integracja | Miesiąc 5-12 |
Automatyczne planowanie uwzględniające emisję dwutlenku węgla; Wewnętrzna tablica liderów zielonej sztucznej inteligencji; wynik SCI w kryteriach rozmieszczenia; Raportowanie ESG emisji ML |
Dodatkowe 10-20% |
Lista kontrolna zielonej sztucznej inteligencji dla każdego zadania szkoleniowego
# 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)
Wnioski: Podsumowanie serii poświęconej zielonej inżynierii oprogramowania
Artykuł ten kończy serię Inżynieria zielonego oprogramowania, podróż w 10 artykułach, która przecinała całe spektrum praktyk zrównoważony rozwój oprogramowania. Od teorii zasad GSF po wdrożenia praktyki z CodeCarbon, Carbon Aware SDK, Climatiq API, aż do technik zaawansowana optymalizacja ML: zbudowaliśmy kompleksowy zestaw narzędzi do programistów i organizacje, które chcą zmniejszyć swój wpływ na środowisko cyfrowe.
10 kluczowych przesłań serii
| # | Przedmiot | Kluczowe przesłanie |
|---|---|---|
| 1 | Zasady GSF | Efektywność węglowa to miernik jakości oprogramowania |
| 2 | KodWęgiel | Nie możesz zredukować tego, czego nie mierzysz: zacznij od pierwszego dnia |
| 3 | API Climatiqa | CO₂ ma API: zintegruj rozliczanie emisji dwutlenku węgla ze swoim backendem |
| 4 | Pakiet SDK uwzględniający emisję dwutlenku węgla | Przesunięcie obciążenia w czasie lub przestrzeni może zmniejszyć liczbę zadań o 90% |
| 5 | Modelowanie zakresu | SCI to standard ISO służący do porównywania efektywności oprogramowania pod względem emisji dwutlenku węgla |
| 6 | GreenOps | Zgodność ekologii i FinOps: optymalizacja CO₂ zmniejsza koszty chmury |
| 7 | Rurociąg Zakresu 3 | Emisje pośrednie są często większe niż emisje bezpośrednie |
| 8 | ESG i CSRD | Od 2025 roku cyfrowe raportowanie ESG stanie się prawnym obowiązkiem wielu firm |
| 9 | Zrównoważone wzory | Pamięć podręczna, wsadowa i asynchroniczna to nie tylko wydajność: to zielone wzorce |
| 10 | AI Carbon | Wybór regionu chmury zmniejsza emisję ML bardziej niż jakikolwiek algorytm |
Ta chwila jest teraz
Generatywna sztuczna inteligencja będzie nadal się rozwijać. Modelki będą coraz większe, im częstsze szkolenia, tym bardziej powszechne wdrożenie. Pytanie nie czy emisje sztucznej inteligencji wzrosną – i tak wzrosną – ale o ile. Techniki opisane w tym artykule pokazują, że możliwa jest redukcja o 60–90% emisji systemu ML bez utraty dokładności, a często nawet redukcji koszty. To nie jest kompromis: to zwycięstwo na wszystkich frontach.
Fundacja Green Software szacuje, że gdyby każdy zespół ML przyjął praktyki szkolenia uwzględniające emisję dwutlenku węgla i kwantyzacja wnioskowania, globalne emisje z sektora Sztuczną inteligencję można zmniejszyć o 40–60% do 2030 r w porównaniu ze scenariuszem jak zwykle. Nie potrzebujemy przełomów technologicznych: potrzebujemy opisanych praktyk w tych dziesięciu artykułach, stosuj systematycznie.
Następny krok należy do Ciebie. Zainstaluj CodeCarbon podczas następnego szkolenia. Sprawdź intensywność emisji dwutlenku węgla w swoim regionie AWS lub GCP. Kwantyzacja modelu przed jego wdrożeniem. Zmierz wynik SCI. A kiedy to zrobisz, wykonasz najważniejszy krok: zaczniesz.
Przydatne linki i narzędzia
- KodWęgiel: mlco2.github.io/codecarbon
- Kalkulator wpływu ML CO₂: mlco2.github.io/impact
- Kalkulator zielonych algorytmów: green-algorithms.org
- Interfejs API map energii elektrycznej: electricmaps.com/api
- Specyfikacja GSF SCI: sci.greensoftware.fundacja
- Urządzenie śledzące emisję przytulania twarzy: Śledzenie emisji dwutlenku węgla przez piastę HuggingFace
- Obsługa vLLM: docs.vllm.ai
- Optymalizacja środowiska wykonawczego ONNX: onnxruntime.ai
Kontynuuj ścieżkę: powiązane serie
- MLOps dla biznesu: Dowiedz się więcej o wdrażaniu modeli uczenia maszynowego za pomocą Rurociągi MLflow, DVC i CI/CD — w tym bramki jakości śladu węglowego.
- Inżynieria AI i RAG: Dowiedz się, jak budować systemy RAG efektywne, które minimalizują liczbę połączeń do modeli LLM, redukując jedno i drugie koszty tej emisji.
- Biznes danych i sztucznej inteligencji: Dowiedz się, jak działa AI Act UE i przepisy ESG krzyżuje się z praktykami zielonej sztucznej inteligencji i sposobami tworzenia planu działania zrównoważone, oparte na danych, dla MŚP.







