Lezione 7 di 7 · 25 min di lettura
Sfida finale
Un ripasso di tutto il modulo e una sfida da risolvere da solo, collegata al motivo per cui Mojo esiste - quanta energia costa addestrare un modello, e quanta se ne risparmia con un kernel più veloce.
Guarda quanta strada
In sei lezioni hai installato Mojo, capito come passa dal sorgente al codice macchina e imparato la grammatica di base del linguaggio. Prima della sfida, un ripasso compatto: se una riga non ti torna, torna alla lezione indicata.
La pagina da tenere accanto
| Cosa | Come si scrive | Lezione |
|---|---|---|
| Laboratorio | uv init --bare learn-mojo, uv add mojo, source .venv/bin/activate | Perché Mojo |
| Eseguire / compilare | mojo file.mojo, mojo build file.mojo -o nome | Hello, World! |
| Formattare | mojo format . | Il laboratorio |
| Punto d’ingresso | def main(): (o def main() raises:) | Hello, World! |
| Stampa | print(a, b, sep=", ", end="") | Hello, World! |
| Variabile | var x = 1, var y: Float32 = 2.5, var z: Int | Variabili e tipi |
| Costante | comptime NAME = 42 (anche fuori da main) | Variabili e tipi |
| Conversioni | Float64(n), Int(x), String(n), Int("42") | Variabili e tipi |
Divisioni tra Int | con a = -7 e b = 2: a / b fa -3, a // b fa -4, a % b fa 1 | Operatori |
| Letterali | 7 / 2 fa 3.5, 0.1 + 0.2 fa 0.3 (calcolati esatti in compilazione) | Operatori |
| Logica | and, or, not, a if cond else b, 1 < x < 9 | Operatori |
| Aggiornare | x += 1, x //= 2, x **= 2 | Operatori |
| Testo | t"{x} + 1 = {x + 1}", String("a", 1) | Stampare e formattare |
| Arrotondare | round(x, 2) | Stampare e formattare |
| Allineare | s.ascii_ljust(10, "."), s.ascii_rjust(2, "0") | Stampare e formattare |
| Lunghezze | s.byte_length(), s.count_codepoints(), s.count_graphemes() | Stampare e formattare |
E tre regole che ti eviteranno la maggior parte degli errori di compilazione:
- Il codice sta dentro le funzioni; fuori, solo
comptime,importe dichiarazioni. - Una variabile nasce con
vare non cambia mai tipo. - I tipi non si mescolano da soli:
IntconInt,Float64conFloat64, e le conversioni si scrivono.
Quiz di controllo
Quiz
Con var a = 10 e var b = 4, cosa stampa print(Float64(a / b))?
Quiz
Quale di queste righe, dentro main, compila?
Quiz
Con var word = "città", cosa succede con print(len(word))?
La sfida: l’impronta di un addestramento
Nella prima lezione abbiamo detto che la velocità è anche energia. Mettiamolo in numeri. Un gruppo di ricerca addestra un modello su 64 GPU, ognuna delle quali assorbe 700 W, per 240 ore. Il data center ha un PUE di 1,2 e l’elettricità che usa emette 300 g di CO₂ per kWh. Poi qualcuno riscrive in Mojo il kernel che domina il calcolo, e l’addestramento diventa 1,6 volte più veloce.
I numeri sono plausibili (700 W è il consumo massimo di una GPU da data center di fascia alta) ma inventati: non descrivono un modello reale.
Dettagli nerd Cos'è il PUE di un data center?
Il PUE (Power Usage Effectiveness) è il rapporto tra l’energia consumata dall’intero data center e quella consumata dai soli computer. Un PUE di 1,2 significa che per ogni kWh assorbito dai server se ne spendono altri 0,2 in raffreddamento, conversione della corrente, illuminazione e rete. Il valore ideale è 1,0; i data center più efficienti si avvicinano a 1,1, quelli più vecchi superano 1,5. Moltiplicare il consumo dei server per il PUE dà il consumo reale.
Allo stesso modo, i grammi di CO₂ per kWh (l’intensità carbonica della rete elettrica) dipendono da come è prodotta l’elettricità: pochi grammi con idroelettrico e nucleare, centinaia con il gas, quasi mille con il carbone. Lo stesso calcolo, in un paese diverso, può avere un’impronta dieci volte diversa.
Esercizio · sul tuo computer
L'impronta di un addestramento
Crea footprint.mojo che stampi esattamente:
TRAINING RUN
GPUs ............... 64
Hours .............. 240
Energy (kWh) ....... 12902.4
CO2 (t) ............ 3.87
---------------------------
WITH A 1.6x FASTER KERNEL
Hours .............. 150
Energy saved (kWh) . 4838.4
CO2 saved (kg) ..... 1451.5
Saved .............. 37.5%Requisiti:
- tutti i dati di partenza (64, 700, 240, 1.2, 300, 1.6) sono costanti
comptimein cima al file; - tutto il resto è calcolato: energia in kWh = GPU × watt × ore ÷ 1000 × PUE; CO₂ in kg = kWh × grammi per kWh ÷ 1000;
- con il kernel più veloce le ore e l’energia si dividono per 1,6; “saved” è la differenza rispetto al caso originale, e la percentuale è l’energia risparmiata sul totale;
- le etichette, con uno spazio finale, sono allineate a 20 caratteri con
ascii_ljust(20, "."), seguite dal valore (lascia che siaprinta mettere lo spazio in mezzo); - energia e CO₂ in kg arrotondate a 1 decimale, le tonnellate a 2, la percentuale a 1; le ore stampate come interi;
- la riga di separazione è fatta di 27 trattini, e si scrive senza contarli a mano:
"-" * 27ripete una stringa; - il titolo della seconda sezione usa una t-string con la costante del fattore di velocità.
Suggerimenti: le costanti intere e quelle decimali non si mescolano da sole, quindi converti con Float64(...) dove serve; Int(...) trasforma le ore in intero per la stampa.
Mostra una soluzione (prima prova da solo!)
comptime GPUS = 64
comptime WATTS_PER_GPU = 700
comptime HOURS = 240
comptime PUE = 1.2 # data centre overhead: cooling, power supplies, network
comptime GRAMS_CO2_PER_KWH = 300
comptime SPEEDUP = 1.6
def main():
var hours = Float64(HOURS)
var kwh = Float64(GPUS * WATTS_PER_GPU) * hours / 1000.0 * PUE
var co2_kg = kwh * Float64(GRAMS_CO2_PER_KWH) / 1000.0
var fast_hours = hours / SPEEDUP
var fast_kwh = kwh / SPEEDUP
var saved_kwh = kwh - fast_kwh
var saved_co2_kg = saved_kwh * Float64(GRAMS_CO2_PER_KWH) / 1000.0
var saved_percent = saved_kwh / kwh * 100.0
print("TRAINING RUN")
print("GPUs ".ascii_ljust(20, "."), GPUS)
print("Hours ".ascii_ljust(20, "."), Int(hours))
print("Energy (kWh) ".ascii_ljust(20, "."), round(kwh, 1))
print("CO2 (t) ".ascii_ljust(20, "."), round(co2_kg / 1000.0, 2))
print("-" * 27)
print(t"WITH A {SPEEDUP}x FASTER KERNEL")
print("Hours ".ascii_ljust(20, "."), Int(fast_hours))
print("Energy saved (kWh) ".ascii_ljust(20, "."), round(saved_kwh, 1))
print("CO2 saved (kg) ".ascii_ljust(20, "."), round(saved_co2_kg, 1))
print("Saved ".ascii_ljust(20, "."), t"{round(saved_percent, 1)}%")Nota l’ultima riga: print accetta anche una t-string come argomento, accanto a una stringa normale.
Cosa succede nel Modulo 2
Il tuo scontrino e la tua impronta di CO₂ ripetevano lo stesso codice più volte, e non potevano prendere decisioni. Nel prossimo modulo arrivano gli strumenti per farlo:
- funzioni con argomenti e tipi di ritorno,
return, argomenti con nome e valori di default; - decisioni con
if,elif,else; - cicli con
forewhile,range,breakecontinue; - le prime regole su come Mojo passa i valori alle funzioni, che sono il cuore della sua velocità.