# EvoX Sistema di Evoluzione Intelligente e Pratica di Ricerca Scientifica AI Native — Dispense del Corso

Durata: 1 · Pagine della presentazione: 16

## Guida alla Lettura

- [Lezione 4 | Tema: Infrastruttura di Calcolo Moderna ed Evoluzione Parallela Tensorizzata](#lecture-lesson-1)

---

<a id="lecture-lesson-1"></a>

## Lezione 4 | Tema: Infrastruttura di Calcolo Moderna ed Evoluzione Parallela Tensorizzata

<a id="lecture-page-1"></a>

### Infrastruttura di Calcolo Moderna ed Evoluzione Parallela Tensorizzata

*Pagina 1*

> **Obiettivo della pagina:** Apprendere come EvoX organizzi popolazione, valutazione e stato in tensori calcolabili nel loro insieme, superando il collo di bottiglia seriale tradizionale per ottenere un'accelerazione su larga scala.

> **Obiettivo della pagina**
>
> Questa pagina, come apertura della quarta lezione, individua il problema centrale che la lezione intende risolvere: quando la dimensione della popolazione, il numero di valutazioni e i passi iterativi degli algoritmi evolutivi crescono continuamente, l'elaborazione seriale tradizionale individuo per individuo e passo per passo diventa un collo di bottiglia evidente. Il filo conduttore di questa lezione è vedere come EvoX riorganizzi popolazione, valutazione e stato in tensori che partecipano al calcolo nel loro insieme, ottenendo così un'accelerazione sostanziale in scenari su larga scala.

> **Ordine di esposizione**
>
> Si può iniziare con una domanda intuitiva: "Se nella popolazione ci sono centomila individui, cosa succede se dobbiamo elaborarli uno per uno in un ciclo?" per guidare gli studenti a rendersi conto del doppio spreco del ciclo seriale in termini di tempo e utilizzo hardware. Poi si indica la direzione della risposta di questa lezione: considerare l'intera popolazione come un batch di dati e l'aggiornamento di una generazione come un'operazione batch, facendo sì che il calcolo ricada complessivamente su hardware parallelo. Infine si introduce il ruolo del livello Runtime, spiegando che è responsabile di schedulare potenza di calcolo eterogenea mantenendo la componibilità degli algoritmi.

**Punti chiave della lezione**

- 1. Espressione tensorizzata — popolazione, valutazione della fitness e stato interno dell'algoritmo non sono più oggetti sparsi, ma sono organizzati in tensori con forma unificata, permettendo di esprimere una generazione evolutiva come una serie di operazioni batch. Il vantaggio è che il pattern di calcolo è regolare, facilmente vettorizzabile e la stessa descrizione algoritmica può adattarsi a popolazioni di dimensioni diverse. 2. Superamento del collo di bottiglia seriale — nelle implementazioni tradizionali, valutazione e aggiornamento dello stato avvengono spesso individuo per individuo; quando la scala cresce, il costo del ciclo e le attese di sincronizzazione dominano il tempo di esecuzione
- dopo la batchizzazione, questi costi vengono ammortizzati e il throughput aumenta significativamente. 3. Ruolo di scheduling del Runtime — il Runtime si colloca tra la descrizione algoritmica e l'hardware sottostante, incaricato di distribuire le operazioni batch su potenza di calcolo eterogenea come CPU e GPU, in modo che l'autore dell'algoritmo non debba riscrivere la logica per ogni dispositivo. Allo stesso tempo, mantiene la componibilità dei componenti algoritmici, permettendo a operatori e strategie diverse di combinarsi liberamente senza compromettere la capacità parallela.

**Copertura delle parole chiave**

- Tensorizzazione, calcolo batch, collo di bottiglia seriale, accelerazione su larga scala, scheduling di potenza di calcolo eterogenea, componibilità degli algoritmi.

**Verifica della comprensione**

Chiedere agli studenti di spiegare con parole proprie cosa cambia realmente "trasformare la popolazione in un tensore" — la risposta attesa dovrebbe ricadere sul livello "passare da un ciclo individuo per individuo a un'operazione batch complessiva, permettendo all'hardware parallelo di essere realmente utilizzato"; se si limitano a ripetere la terminologia senza spiegare il nesso causale, si può suggerire di riorganizzare l'esposizione dal punto di vista del numero di calcoli e dell'utilizzo hardware.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti hanno stabilito la catena causale di base "tensorizzazione → calcolo batch → accelerazione parallela", passare alle pagine successive per vedere concretamente come popolazione e stato vengono organizzati in tensori e come il Runtime completa lo scheduling.

<a id="lecture-page-2"></a>

### Infrastruttura di Calcolo Moderna ed Evoluzione Parallela Tensorizzata

*Pagina 2*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere la contraddizione tra la domanda di potenza di calcolo su larga scala del calcolo evolutivo moderno e l'architettura tradizionale.

> **Obiettivo della pagina**
>
> Comprendere la contraddizione tra la domanda di potenza di calcolo su larga scala del calcolo evolutivo moderno e l'architettura seriale tradizionale; padroneggiare l'approccio di organizzare popolazione, valutazione e stato in tensori per portare avanti l'evoluzione in modo batch e parallelo; riconoscere l'espansione della generazione di candidati da parte dei grandi modelli e i compromessi architetturali a livello di sistema che ne derivano.

> **Ordine di esposizione**
>
> Indicare prima la contraddizione centrale "diversità → numero di valutazioni → gestione dello stato e costi di scheduling", poi spiegare perché il ciclo seriale raggiunge per primo il limite; successivamente sviluppare i tre livelli della tensorizzazione — tensore della popolazione, tensore della valutazione, tensore dello stato — e riassumere il termine chiave "parallelismo batch"; poi spiegare come i grandi modelli spingono la generazione di candidati verso nuovi confini; infine arrivare agli esempi di scenario EvoX e ai compromessi a livello di sistema, gestendo esercizi e casi di studio.

**Punti chiave della lezione**

- L'evoluzione dipende dalla diversità della popolazione, e la diversità si traduce direttamente in numero di valutazioni, gestione dello stato e costi di scheduling. Nel ciclo tradizionale CPU individuo per individuo, ogni individuo deve chiamare separatamente la funzione obiettivo, aggiornare separatamente lo stato, registrare separatamente il log
- quando la popolazione cresce da decine a migliaia, il numero di valutazioni e il tempo di wall-clock crescono quasi linearmente; una volta che una singola simulazione è costosa, il throughput complessivo viene bloccato sul "ritmo single-core". Più alta è la diversità e più costosa è la valutazione, più evidente è il collo di bottiglia seriale. L'approccio della tensorizzazione consiste nel riorganizzare popolazione, valutazione e stato in tensori calcolabili nel loro insieme. Il tensore della popolazione impila tutti i parametri dei candidati in un tensore bidimensionale "numero di individui × dimensione", e una singola chiamata all'operatore completa la mutazione e l'aggiornamento dell'intera popolazione
- il tensore della valutazione impacchetta le richieste di valutazione batch e le invia, eseguite in parallelo dalla GPU o da un servizio batch, per poi unire i valori di ritorno
- il tensore dello stato mantiene fitness, violazioni dei vincoli, ranking e altri stati intermedi in forma tensoriale, permettendo che selezione, ordinamento e aggiornamento siano calcolati nel loro insieme. I tre insieme costituiscono il "parallelismo batch", che trasforma il carico computazionale portato dalla diversità da un onere in una scala assorbibile dal throughput; non è quindi un dettaglio di ottimizzazione, ma una questione infrastrutturale del calcolo evolutivo moderno. Una volta aperta la scala di calcolo, la questione chiave si sposta da "si può calcolare" a "da dove vengono i candidati". I grandi modelli possono comprendere linguaggio naturale, codice, conoscenza di dominio e contesto del progetto, e su questa base costruire candidati strutturalmente complessi, espandendo l'oggetto dell'evoluzione da parametri numerici a programmi, algoritmi e persino stati di sistema completi
- i modi di codifica e mutazione che prima dipendevano dalla progettazione umana possono ora essere generati con la partecipazione del modello. Due forze si incontrano: la GPU permette di esplorare simultaneamente molte possibilità, il grande modello permette al sistema di produrre possibilità più ricche, e il meccanismo evolutivo si occupa di inviare i candidati a compiti reali, decidendo attraverso esecuzione e valutazione quali cambiamenti meritano di essere conservati. Per gli ingegneri di algoritmi e gli sviluppatori di sistemi, non si tratta di ottimizzazione locale, ma di un compromesso architetturale: è necessario bilanciare a livello di sistema la ricchezza della generazione di candidati, il throughput del calcolo batch e la complessità ingegneristica. La diversità è il prerequisito dell'efficacia evolutiva, ma deve essere digerita dal throughput. Nello scenario EvoX, se si continua a usare un ciclo CPU seriale per valutare individuo per individuo, la dimensione della popolazione sarà limitata dal throughput
- passando al parallelismo batch tensorizzato, nello stesso round si possono organizzare simultaneamente i parametri, gli stati di valutazione e gli aggiornamenti di un gran numero di candidati, rendendo "mantenere la diversità" e "esplorazione su larga scala" simultaneamente fattibili a livello ingegneristico.

**Copertura delle parole chiave**

- Parallelismo batch, tensorizzazione, tensore della popolazione, tensore della valutazione, tensore dello stato, collo di bottiglia seriale, generazione di candidati, compromessi a livello di sistema.

**Gestione degli esercizi**

Questa pagina contiene 5 domande a scelta multipla e 1 caso di studio, per un totale di 2 domande. Le domande a scelta multipla verificano rispettivamente la contraddizione centrale, il modo di implementazione del parallelismo batch, il ruolo dei grandi modelli, i compromessi a livello di sistema dopo la migrazione, e i cambiamenti diretti nello scenario EvoX. Nel rispondere, aggrapparsi a due fili conduttori: primo, la catena causale "diversità → carico computazionale → collo di bottiglia seriale → parallelismo batch"; secondo, la divisione dei compiti "il grande modello si occupa di generare candidati più ricchi, il meccanismo di valutazione si occupa di giudicare quali candidati meritano di essere conservati". La prima domanda del caso di studio richiede di diagnosticare il collo di bottiglia seriale e spiegare come la tensorizzazione cambi l'organizzazione da tre punti: popolazione, valutazione, stato; la seconda domanda richiede di fornire un giudizio di compromesso dal punto di vista di ricchezza dei candidati vs throughput batch, benefici dell'esplorazione vs complessità ingegneristica, throughput batch vs fedeltà della valutazione.

Una risposta corretta dovrebbe collegarsi ai concetti di questa pagina e spiegarne le motivazioni; se il giudizio è errato, tornare alla catena causale "diversità → numero di valutazioni → gestione dello stato e costi di scheduling" e distinguere "accelerare lo stesso ciclo seriale" da "cambiare il modo di organizzare il calcolo".

**Verifica della comprensione**

Chiedere a uno studente a caso di riassumere con parole proprie i punti chiave di questa pagina, in particolare come la diversità si traduca in carico computazionale, perché il seriale raggiunga il limite, e come il parallelismo batch tensorizzato organizzi popolazione, valutazione e stato. Se lo studente riesce solo a ripetere la terminologia senza spiegare il nesso causale, guidarlo a tornare al confronto delle pendenze nel grafico e al punto marcato "collo di bottiglia seriale: throughput al limite".

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno esprimere la relazione centrale di questa pagina — la diversità porta carico computazionale, l'esecuzione seriale raggiunge il limite, il parallelismo batch tensorizzato digerisce la scala con il calcolo complessivo — passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-3"></a>

### Diversità Evolutiva e Sfide della Scala Computazionale

*Pagina 3*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere la pressione computazionale derivante dai compromessi multi-obiettivo e dalla diversità dei candidati in problemi reali.

> **Obiettivo della pagina**
>
> Comprendere la pressione computazionale derivante dai compromessi multi-obiettivo e dalla diversità dei candidati, padroneggiare il fronte di Pareto, le relazioni di dominanza e la tensione tra mantenimento della diversità e costo di valutazione.

**Punti chiave della lezione**

- Solo quando il problema ha un unico obiettivo esiste una soluzione ottimale unica. I problemi ingegneristici reali hanno tipicamente molteplici obiettivi in conflitto tra loro (portanza e resistenza, precisione e latenza, prestazioni e costo); in questo caso la "buona risposta" è un insieme di soluzioni di compromesso non dominate tra loro, cioè il fronte di Pareto. Confronto elemento per elemento: A non è peggiore di B su tutti gli obiettivi → A è strettamente migliore su almeno un obiettivo → solo se entrambe le condizioni sono soddisfatte A domina B. Se anche solo un obiettivo di A è peggiore, i due non si dominano e entrambi possono rimanere sul fronte. Asse orizzontale f1, asse verticale f2, entrambi minori è meglio
- il cluster A tende a f1 basso, il cluster B è intermedio, il cluster C tende a f2 basso
- i punti grigi sono soluzioni dominate. Il decisore ha bisogno dello spazio di compromesso rappresentato dall'intero fronte, non di un singolo punto scelto dall'algoritmo. Si riferisce a differenze strutturate distribuite lungo diverse direzioni di compromesso sul fronte di Pareto. Copertura delle direzioni — riempire l'estremità superiore sinistra, il segmento centrale, l'estremità inferiore destra del fronte
- conservazione delle differenze — candidati quasi identici equivalgono a uno solo
- valore decisionale — le preferenze spesso si chiariscono a posteriori, conservare candidati differenziati permette di riscegliere a costo zero. Più forte è la diversità, più ampio è lo spazio di ricerca, più grande è la popolazione, più numerose sono le valutazioni. Quando la valutazione dipende da simulazioni ad alta fedeltà (come il calcolo aerodinamico di un profilo alare supercritico che richiede ore), il costo di una singola valutazione viene amplificato fino a diventare il collo di bottiglia principale. Risposte comuni: modelli surrogati che sostituiscono la maggior parte delle valutazioni ad alta fedeltà
- assegnare il budget limitato ad alta fedeltà con priorità ai candidati che possono maggiormente estendere la copertura del fronte
- ridistribuire il budget tra dimensione della popolazione e numero di generazioni. Equiparare la diversità a rumore casuale o a eseguire più volte. La vera diversità è differenza strutturata di direzione
- la semplice perturbazione casuale non estende la copertura del fronte né riduce la difficoltà decisionale. Spunti per gli esercizi (5 domande a scelta multipla + 1 caso di analisi): Il fronte di Pareto è un insieme di soluzioni di compromesso non dominate, dove due soluzioni qualsiasi hanno vantaggi e svantaggi su obiettivi diversi. A è migliore su f1, B è migliore su f2, i due non si dominano e entrambi possono rimanere sul fronte. La diversità è differenza strutturata distribuita lungo diverse direzioni di compromesso sul fronte di Pareto, che serve direttamente alla decisione. Una copertura più ampia delle direzioni di compromesso richiede un maggiore spazio di ricerca, dimensione della popolazione e numero di valutazioni degli obiettivi, quindi più forte è la diversità, maggiore è la sfida della scala computazionale. Usare modelli surrogati per sostenere la maggior parte delle valutazioni e concentrare il budget limitato ad alta fedeltà sull'estensione della copertura del fronte può alleviare la tensione tra scala e diversità. Progettazione di profili alari supercritici. Il risultato dovrebbe essere un insieme di soluzioni candidate situate sul fronte di Pareto che coprono diverse direzioni di compromesso, non una singola soluzione
- le misure per alleviare la tensione includono modelli surrogati, assegnazione prioritaria del budget, aggiustamento del rapporto tra popolazione e generazioni, selezione multi-fedeltà a fasi, ecc.

**Verifica della comprensione**

Chiedere agli studenti di spiegare con parole proprie la relazione di dominanza e il fronte di Pareto, e di fare esempi di perché la diversità porta pressione computazionale. Se gli studenti confondono la diversità con la perturbazione casuale, tornare al "promemoria di autoverifica" — per quanti candidati ci siano, se si affollano nello stesso angolo del fronte, non c'è comunque diversità.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere l'ottimo singolo punto dall'insieme di soluzioni di compromesso e comprendono il costo della diversità, passare alla pagina successiva sul contenuto dell'evoluzione parallela tensorizzata.

<a id="lecture-page-4"></a>

### Collo di Bottiglia di Efficienza del Ciclo CPU Seriale Tradizionale

*Pagina 4*

> **Obiettivo della pagina:** Lo studente dovrebbe riconoscere i limiti prestazionali del ciclo CPU seriale tradizionale nell'elaborare decine di migliaia di valutazioni di candidati.

**Punti chiave della lezione**

- Numero totale di valutazioni ≈ dimensione della popolazione × numero di generazioni; tempo di valutazione seriale ≈ numero totale di valutazioni × tempo di singola valutazione. Calcolare prima queste due quantità, poi giudicare se il collo di bottiglia merita un intervento di ristrutturazione.
- Ciclo a livello di interprete, controllo dei limiti e dispatch dei tipi individuo per individuo, accesso non contiguo alla memoria, sincronizzazione e trasferimento dati frequenti si sommano in un costo costante seriale. Ottimizzare solo l'operatore stesso può eliminare solo una piccola parte.
- Tracciare il tempo di wall-clock per diverse dimensioni di popolazione: una linea approssimativamente retta indica che l'esecuzione è ancora seriale, una forma a gradini indica che è già organizzata in batch. La forma della curva spiega l'attribuzione del collo di bottiglia meglio di un singolo numero.

> **Obiettivo della pagina**
>
> Questa pagina deve far riconoscere agli studenti che quando le valutazioni dei candidati raggiungono l'ordine delle decine di migliaia, il ciclo CPU seriale tradizionale diventa il segmento più stretto dell'intera pipeline evolutiva; questo collo di bottiglia appartiene al livello del modello di esecuzione, non alla scrittura di un singolo operatore o a difetti nel codice. La successiva elaborazione batch, tensorizzazione e scheduling parallelo sono proprio le direzioni di ristrutturazione mirate a questo collo di bottiglia strutturale.
>
> Ordine di esposizione e punti chiave:
>
> L'evoluzione dipende dalla diversità, e la diversità porta a una crescita moltiplicata della dimensione della popolazione e del numero di valutazioni. Numero totale di valutazioni ≈ dimensione della popolazione × numero di generazioni; tempo di valutazione seriale ≈ numero totale di valutazioni × tempo di singola valutazione. Quando il numero di valutazioni raggiunge l'ordine di 10⁵, il tempo di wall-clock seriale cresce approssimativamente in modo lineare.
>
> Il grafico confronta l'elaborazione seriale individuo per individuo con l'elaborazione parallela batch. L'asse orizzontale è il numero di valutazioni dei candidati 10³, 10⁴, 10⁵, l'asse verticale è il tempo di wall-clock normalizzato. La curva seriale cresce approssimativamente in modo lineare; la curva parallela cresce a gradini. I segmenti scuri rappresentano i costi di scheduling e trasferimento dati. La conclusione chiave è: a parità di carico di lavoro, la crescita del tempo parallelo è determinata principalmente dal numero di batch, non dal numero di individui. Usare la forma della curva spiega l'attribuzione del collo di bottiglia meglio di un singolo numero.
>
> L'implementazione più ingenua tratta l'intera popolazione come una lista, estrae gli individui uno per uno in un ciclo → decodifica in parametri concreti → chiama la funzione di valutazione → riscrive la fitness. Tra iterazioni adiacenti non c'è quasi sovrapposizione: se il risultato della valutazione non ritorna, la scrittura non può procedere; se la scrittura non è completata, il prossimo individuo non ha posto dove mettere il risultato. Così le unità parallele come multi-core, SIMD, GPU rimangono inattive per la maggior parte del tempo.
>
> Il numero di valutazioni che si gonfia linearmente; l'esecuzione individuo per individuo a livello di interprete, incluso il ciclo per individuo, il controllo dei limiti e il dispatch dei tipi, porta un costo costante fisso ma elevato; l'accesso non contiguo alla memoria e il trasferimento dati, gli individui estratti uno per uno sono spesso non contigui in memoria, con un tasso di hit della cache basso; sincronizzazione e scheduling, per ottenere il prossimo individuo, il flusso di esecuzione si ferma e riprende ripetutamente. Ottimizzare solo l'interno dell'operatore può eliminare solo una piccola parte.
>
> Prendendo come esempio una popolazione di 1000 e 100 generazioni, il numero totale di valutazioni è circa 1000 × 100 = 10⁵. Se una singola valutazione richiede in media 1 ms, solo la fase di valutazione seriale richiede circa 100 secondi, senza contare i costi di calcolo degli operatori e di scheduling; se per mantenere la diversità si aumenta il numero di riavvii da 1 a 5, il costo sale approssimativamente in modo lineare a circa 500 secondi. A parità di carico di lavoro, se organizzato in batch e affidato a hardware parallelo, il tempo di wall-clock è determinato principalmente dal numero di batch e dal tempo per batch.
>
> Quando una singola valutazione è estremamente economica (livello microsecondi) o la popolazione è molto piccola (sotto il centinaio), i costi di scheduling e memoria possono superare i costi di calcolo, il divario tra seriale e parallelo si riduce notevolmente, il beneficio marginale della tensorizzazione diminuisce, e il collo di bottiglia si sposta sulla granularità di scheduling e sulla larghezza di banda della memoria. Quindi se valga la pena ristrutturare il modello di esecuzione va valutato congiuntamente al costo di valutazione e alla scala.
>
> Il collo di bottiglia di efficienza del ciclo CPU seriale è strutturale. Per risolverlo veramente, bisogna ristrutturare da individuo per individuo a batch per batch, cioè elaborazione batch, tensorizzazione e scheduling parallelo, che costituisce la motivazione diretta per la progettazione del grafo computazionale tensorizzato successivo.

**Copertura delle parole chiave**

- Ciclo CPU seriale, parallelismo batch, tempo di wall-clock, numero di valutazioni dei candidati, numero di batch, costi a livello di interprete, accesso non contiguo alla memoria, sincronizzazione e scheduling, collo di bottiglia strutturale, tensorizzazione.

**Gestione degli esercizi**

Questa pagina contiene 5 domande a scelta multipla. Si consiglia di far prima esprimere agli studenti le motivazioni del giudizio per ogni domanda, poi fornire il feedback.

La domanda 1 chiede il limite principale del modello di esecuzione del ciclo seriale. La risposta è "tra iterazioni adiacenti è difficile sovrapporsi, le unità parallele come multi-core, SIMD, GPU rimangono inattive per la maggior parte del tempo". Punto di feedback: il flusso individuo per individuo estrai individuo → decodifica → valuta → riscrivi rende ogni individuo un passo seriale indipendente, l'hardware manca di lavoro indipendente eseguibile simultaneamente; il collo di bottiglia non è che non si riesca a calcolare la fitness, ma che in un dato momento solo un individuo viene elaborato.

La domanda 2 chiede il tempo di wall-clock seriale della sola fase di valutazione con popolazione 1000, 100 generazioni, singola valutazione 1 ms. La risposta è circa 100 secondi. Guida al calcolo: numero totale di valutazioni ≈ 1000 × 100 = 10⁵, poi moltiplicare per 1 ms.

La domanda 3 chiede quale elemento non è un fattore che amplifica il costo costante del ciclo seriale. La risposta è "scheduling batch tensorizzato". Punto di feedback: lo scheduling batch tensorizzato è una direzione di ristrutturazione per alleviare il collo di bottiglia, non una fonte di amplificazione dei costi del ciclo seriale stesso; i costi seriali derivano da accesso non contiguo alla memoria, controllo dei limiti e dispatch dei tipi individuo per individuo, ciclo a livello di interprete, ecc.

La domanda 4 chiede da cosa è determinato principalmente il tempo di wall-clock nel parallelismo batch a parità di carico di lavoro totale. La risposta è "numero di batch e tempo per batch". Punto di feedback: l'elaborazione batch trasforma individuo per individuo in batch per batch, il tempo di wall-clock cresce a gradini con il numero di batch, non più approssimativamente in modo lineare con il numero di individui.

La domanda 5 chiede in quale situazione è più probabile che il ciclo seriale non sia un collo di bottiglia strutturale. La risposta è "singola valutazione ridotta al livello microsecondi e dimensione della popolazione solo dell'ordine del centinaio". Punto di feedback: in questo caso i costi di scheduling e memoria possono superare i costi di calcolo, il divario tra seriale e parallelo si riduce; giudicare il collo di bottiglia va fatto valutando congiuntamente costo di valutazione e scala.

**Attività in classe**

Si può usare il caso di questa pagina "Scelta del modello di esecuzione con centomila valutazioni". Far prima stimare agli studenti, poi discutere i confini della ristrutturazione.

Stimare il tempo di wall-clock della sola fase di valutazione dell'implementazione seriale attuale, spiegare il cambiamento dopo l'aumento del numero di riavvii da 1 a 5, e su questa base giudicare la priorità di ottimizzazione. Risposta di riferimento: 1000 × 100 = 10⁵ valutazioni, moltiplicato per 1 ms dà circa 100 secondi; con 5 riavvii si hanno circa 5 × 10⁵ valutazioni, cioè circa 500 secondi, il tempo di wall-clock si gonfia approssimativamente in modo lineare. Questo mostra che le micro-ottimizzazioni a livello costante all'interno dell'operatore danno benefici limitati, la priorità di ottimizzazione dovrebbe essere a livello del modello di esecuzione, cioè elaborazione batch, tensorizzazione e scheduling parallelo, facendo sì che il tempo di wall-clock sia determinato dal numero di batch anziché dal numero di individui.

Se si passa a un modello di esecuzione parallelo batch, quali condizioni al contorno considerare per giudicare se la ristrutturazione vale la pena. Risposta di riferimento: primo, costo di valutazione e scala, se la singola valutazione scende al livello microsecondi, o la popolazione si riduce sotto il centinaio, i costi di scheduling e trasferimento in memoria possono superare i costi di calcolo, il beneficio parallelo diminuisce; secondo, vincoli su numero e dimensione dei batch, la dimensione del batch è limitata da memoria video, larghezza di banda della memoria, tempo di calcolo per batch, batch troppo grandi aumentano il tempo per batch e i costi di sincronizzazione; terzo, layout dei dati e accesso alla memoria, se i candidati non possono essere organizzati in tensori contigui e vettorizzabili, l'elaborazione batch sarà comunque penalizzata dall'accesso non contiguo. Nel complesso, solo quando il numero di valutazioni e il costo della singola valutazione sono entrambi sufficientemente grandi, il beneficio della ristrutturazione del modello di esecuzione è significativo.

**Verifica della comprensione**

Chiedere a uno studente a caso di riassumere con parole proprie i punti chiave di questa pagina, ad esempio "perché il ciclo seriale è un collo di bottiglia strutturale" e "da cosa è determinato il tempo di wall-clock dopo il parallelismo". Se lo studente dice solo "lento", chiedere di specificare le due dimensioni: ordine di grandezza e numero di batch. Si può aggiungere il promemoria di calcolo rapido: numero totale di valutazioni ≈ dimensione della popolazione × numero di generazioni; tempo di valutazione seriale ≈ numero totale di valutazioni × tempo di singola valutazione. Ricordare di non fissarsi solo sull'interno dell'operatore, e usare la forma della curva per l'autoverifica: approssimativamente retta indica esecuzione ancora seriale, a gradini indica organizzazione già in batch.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno dire "il seriale è un collo di bottiglia del modello di esecuzione, dopo l'organizzazione parallela in batch il wall-clock è determinato dal numero di batch", passare al contenuto successivo sulla progettazione del grafo computazionale tensorizzato e dello scheduling parallelo.

**Fondamenti dei materiali**

L'evoluzione dipende dalla diversità, e la diversità implica un enorme carico computazionale. Il ciclo CPU seriale tradizionale è inefficiente nell'elaborare decine di migliaia di valutazioni di candidati.

<a id="lecture-page-5"></a>

### Dalla Lista di Candidati al Grafo Computazionale Tensorizzato

*Pagina 5*

> **Obiettivo della pagina:** Lo studente dovrebbe padroneggiare la transizione centrale dalla rappresentazione a lista del processo evolutivo al grafo computazionale tensorizzato.

> **Obiettivo della pagina**
>
> Lo studente dovrebbe padroneggiare la transizione centrale dalla rappresentazione a lista del processo evolutivo al grafo computazionale tensorizzato, e saper spiegare perché l'evoluzione richiede calcolo tensoriale batch e come la tensorizzazione cambi il modo di esprimere il processo evolutivo.

**Punti chiave della lezione**

- L'evoluzione dipende dalla diversità e richiede di valutare decine di migliaia o persino milioni di soluzioni candidate. Se i candidati sono scritti come array di oggetti comuni e valutati con un ciclo elemento per elemento, la maggior parte del tempo viene consumata nello scheduling elemento per elemento e nel flusso di controllo del linguaggio host, non nelle vere operazioni numeriche. Qui sta la causa principale dell'inefficienza del ciclo CPU seriale tradizionale. L'insieme dei candidati, i risultati delle valutazioni e lo stato dell'algoritmo sono organizzati in modo unificato come tensori. L'intera generazione di candidati è scritta come un tensore dei candidati di forma [dimensione della popolazione, dimensione della soluzione]
- un candidato non è più un oggetto indipendente, ma una fetta o una riga nel tensore. Anche la figura della pagina si sviluppa in questo ordine: a sinistra la lista dei candidati elaborata elemento per elemento, al centro il tensore dei candidati, a destra nel grafo computazionale in sequenza mutazione, valutazione, selezione, aggiornamento dello stato. Operazioni come la mutazione agiscono direttamente sull'intera popolazione, una singola chiamata completa l'aggiornamento di tutti i candidati
- la valutazione è scritta come evaluate(tensore_dei_candidati), ottenendo in una volta i risultati dell'intera generazione, l'unità di valutazione passa da "individuo" a "batch". Selezione e aggiornamento dello stato non sono più solo logica di controllo seriale, ma nodi nel grafo, ottenendo così opportunità di ottimizzazione del compilatore come fusione di operatori e scheduling parallelo. La logica dell'algoritmo, come la distribuzione della mutazione e la pressione selettiva, non è stata riscritta
- ciò che è stato riscritto è il modo di esprimere. Non si tratta semplicemente di spostare il ciclo su un dispositivo più veloce, ma di organizzare dati e operatori prendendo il tensore come unità minima di elaborazione. Se si continua a insistere che "un candidato equivale a un oggetto indipendente", anche l'hardware parallelo più ampio può solo ricevere dati in modo seriale. La transizione chiave di questa pagina può essere riassunta come "dalla lista di candidati al grafo computazionale tensorizzato"
- vedere un operatore batch, pensare "calcolare l'intero gruppo insieme".

**Copertura delle parole chiave**

- Calcolo tensorizzato, tensore dei candidati, operatori batch, valutazione batch, grafo computazionale, ottimizzazione del compilatore, dimensione della popolazione, dimensione della soluzione.

**Gestione degli esercizi**

La risposta alla domanda 1 a scelta multipla dovrebbe indicare i costi fissi dello scheduling elemento per elemento e del flusso di controllo del linguaggio host, non l'insufficienza di potenza di calcolo o di diversità. Nel feedback, sottolineare che più numerosi sono i candidati, maggiore è la quota di questi costi.

Una soluzione candidata corrisponde a una fetta nel tensore dei candidati, ad esempio una riga; non è più vincolata come oggetto indipendente del linguaggio host.

Selezione e aggiornamento dello stato, entrando nel grafo computazionale, possono ottenere opportunità di ottimizzazione del compilatore come fusione di operatori e scheduling parallelo, riducendo tensori intermedi e costi di sincronizzazione.

L'output della valutazione è più probabilmente [dimensione della popolazione] o [dimensione della popolazione, numero di obiettivi]; la valutazione produce lungo la dimensione della popolazione uno o un gruppo di indicatori per ogni candidato.

EvoX a livello espressivo trasforma l'elaborazione a lista candidato per candidato in un grafo computazionale batch che tratta il tensore come cittadino di prima classe.

Ricerca di 50000 profili alari candidati. Il collo di bottiglia dell'implementazione originale è principalmente a livello di organizzazione dei dati e scheduling: accesso oggetto per candidato, chiamata di funzione elemento per elemento, confronto e aggiornamento manuale dello stato uno per uno, e l'elaborazione di un solo candidato alla volta, impossibile da saturare la larghezza del parallelismo hardware. La ristrutturazione tensorizzata non cambia la pressione selettiva e la distribuzione della mutazione, ma unifica candidati, risultati delle valutazioni e stato dell'algoritmo in tensori, facendo sì che mutazione e valutazione agiscano in una volta sull'intera popolazione. Se si desidera che anche selezione e aggiornamento dello stato ottengano l'ottimizzazione del compilatore, si dovrebbe impostare il tensore dei candidati come [50000, 48]; l'output della valutazione come [50000] o [50000, numero di obiettivi]; la mutazione agisce sull'intero tensore dei candidati; la selezione usa indici o maschere tensoriali;

l'aggiornamento dello stato è scritto come nodo di riduzione lungo la dimensione della popolazione, come prendere il minimo o calcolare la media.

**Verifica della comprensione**

Qual è la forma del tensore dei candidati? Qual è la forma dell'output di una valutazione? Quali due fasi sono passate da logica di controllo seriale a nodi del grafo computazionale? Se si risponde a tutti e tre i punti, significa che si è padroneggiata la transizione chiave di questa pagina.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno spiegare con parole proprie il cambiamento "dalla lista di candidati al grafo computazionale tensorizzato", passare all'applicazione, esempi o riepilogo della pagina successiva.

<a id="lecture-page-6"></a>

### Organizzazione Tensorizzata di Popolazione, Valutazione e Stato

*Pagina 6*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere come mappare in modo unificato dati della popolazione, valutazione della fitness e variabili di stato in strutture tensoriali.

> **Obiettivo della pagina**
>
> Comprendere come mappare in modo unificato dati della popolazione, valutazione della fitness e stato di esecuzione dell'algoritmo in strutture tensoriali, formando un contratto dati unificato calcolabile in batch, residente sul dispositivo e riproducibile.

> **Ordine di esposizione**
>
> Iniziare con tre domande — cos'è la popolazione, come viene valutata, a che passo è l'esecuzione; poi corrispondere tre tipi di contenitori — tensore della popolazione [N, D], matrici di valutazione e vincoli [N, M] e [N, K], contenitore di stato unificato; infine spiegare come la valutazione batch e la residenza dello stato trasformino il ciclo individuo per individuo in operazioni sull'intero batch.

**Punti chiave della lezione**

- Organizzare N soluzioni candidate come tensore di codifica [N, D]. N è la dimensione batch, D è la dimensione delle caratteristiche; di solito N è posto all'esterno, in modo che lo stesso operatore possa agire sull'intero batch in una volta. Se un individuo è composto da più segmenti di parametri, si può dividere in blocchi di campo come [N, D1] + [N, D2] + …
- individui a lunghezza variabile sono gestiti con padding più maschera o bucketing, evitando che strutture eterogenee rompano il calcolo sull'intero batch. Una valutazione batch produce una matrice di fitness [N, M]
- obiettivi multipli, vincoli multipli e indicatori aggiuntivi possono essere affiancati come [N, M+K] o memorizzati in tabelle separate; la chiave è evitare di chiamare la funzione di valutazione in un ciclo individuo per individuo. Anche generazione, stato del generatore di numeri casuali, iperparametri della strategia, soluzione ottimale, cache storica, ranking o stato di campionamento entrano in tensori o contenitori di stato strutturati, garantendo riproducibilità, tracciabilità e aggiornamento batch. Il tensore unificato riduce i viaggi tra host e dispositivo, abbassa i costi del ciclo e fornisce la base dati per il parallelismo degli operatori successivi
- ma attenzione alla validità delle maschere, allo spreco del padding, all'allargamento della matrice di valutazione dovuto alla crescita del numero di obiettivi, e ai costi di sincronizzazione dello stato.

> **Spunti dai materiali**
>
> - La figura del layout di memoria colloca il tensore della popolazione, la matrice di valutazione, la matrice dei vincoli e il contenitore di stato unificato sotto la stessa semantica di memoria del dispositivo. Si può ricordare agli studenti di notare che la freccia "valutazione batch" indica che una singola chiamata elabora l'intero batch, non una chiamata per individuo. Quando N=1024, D=50, M=2, la popolazione è [1024, 50], i valori di valutazione sono [1024, 2], i vincoli sono [1024, K]. generation può essere memorizzato come scalare, best_x può essere memorizzato come tensore monodimensionale [D], rng_state può essere rappresentato con un tensore di interi di lunghezza appropriata. Ogni aggiornamento generazionale può essere completato interamente sulla stessa dimensione batch.

**Gestione degli esercizi**

La comprensione centrale è "popolazione, valutazione e stato mappati in modo unificato in strutture tensoriali". Se la scelta è corretta, significa che la comprensione è in linea con il filo conduttore di questa pagina; se errata, tornare all'inizio della pagina per rivedere il contratto dati unificato.

Un'affermazione ragionevole dovrebbe sottolineare che la valutazione batch genera [N, M] e [N, K], non un ciclo individuo per individuo. Nel giudizio, è sufficiente collegarsi alla forma della matrice e alle motivazioni della valutazione batch.

Un'affermazione ragionevole dovrebbe spiegare che generazione, stato del generatore di numeri casuali, soluzione ottimale, ecc. sono anch'essi inclusi nel contenitore di stato unificato, facilitando checkpoint e riproduzione. Se la risposta si ferma a "mettere i dati nel tensore", ricordare di prestare attenzione anche alla gestione dello stato e alla riproduzione.

Per lo scenario N=2048, D=100, M=3, K=5, si consiglia popolazione [2048, 100], valutazione [2048, 3], vincoli [2048, 5]; variabili di stato come generation come tensore scalare, best_x come [100], rng_state come tensore di interi, cache storica come [T, 2048, 100] o memorizzazione compressa. Nella valutazione batch, vettorizzare la funzione di valutazione in modo che accetti [N, D] e restituisca [N, M] e [N, K]; individui a lunghezza variabile utilizzano padding più maschera o bucketing, ignorando le parti non valide secondo la maschera dopo il calcolo.

**Verifica della comprensione**

Chiedere a uno studente di spiegare in una frase perché N dovrebbe essere la dimensione batch più esterna, e di indicare almeno una variabile di stato e perché dovrebbe essere tensorizzata. Se la risposta si ferma a "mettere i dati nel tensore", aggiungere: la chiave è il contratto dati unificato e l'esecuzione di operatori sull'intero batch.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere i quattro tipi di contenitori — popolazione, valutazione, vincoli e stato — passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-7"></a>

### Parallelismo degli Operatori e Ottimizzazione del Compilatore

*Pagina 7*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere i meccanismi di ottimizzazione del compilatore sottostanti quando operazioni come mutazione e crossover agiscono sull'intera popolazione.

> **Obiettivo della pagina**
>
> Comprendere che nell'infrastruttura di calcolo moderna di EvoX, l'unità minima di esecuzione degli operatori evolutivi passa da "individuo" a "tensore della popolazione"; padroneggiare come gli operatori tensorizzati e la compilazione del grafo computazionale migliorino il throughput dell'evoluzione batch, mantenendo invariata la semantica dell'algoritmo.

> **Ordine di esposizione**
>
> Stabilire prima il giudizio "su chi agisce l'operatore", poi confrontare le differenze di esecuzione tra ciclo individuo per individuo e operatore a livello tensoriale, quindi spiegare come la compilazione del grafo computazionale ottimizzi dalla sequenza di operatori al piano di esecuzione, e infine consolidare con casi ed esercizi il principio "l'efficienza cambia, la semantica no".

**Punti chiave della lezione**

- 1. La forma del tensore della popolazione è [N, D], N è la dimensione della popolazione, D è la dimensione delle variabili decisionali. Operatori come mutazione, crossover e selezione possono agire direttamente sull'intero tensore della popolazione, una singola chiamata copre tutti gli N individui
- la dimensione degli individui funge da dimensione batch, il dispositivo può eseguire in parallelo su larga scala, il throughput si amplifica con la dimensione della popolazione. 2. La scrittura individuo per individuo come for ind in population: ind = mutate(ind) scompone ogni operatore in N piccole chiamate, portando frequenti scheduling del framework e avvii di kernel
- ogni batch è solo di dimensione 1, le unità parallele del dispositivo difficilmente si saturano, e la creazione e distruzione ripetuta di risultati intermedi aumenta anche i costi di allocazione della memoria video e trasferimento dati. La chiave della ristrutturazione è population = mutate(population_tensor), facendo eseguire l'operatore prendendo come unità il tensore della popolazione. 3. La compilazione del grafo computazionale organizza "mutazione → crossover → selezione" in un grafo computazionale, facendo ottimizzazioni globali sull'intero grafo: la fusione di operatori può combinare più operazioni elemento per elemento in meno kernel, riducendo tensori intermedi e letture/scritture
- generazione e scheduling dei kernel completano l'intera generazione evolutiva con un minor numero di avvii di kernel
- il riuso della memoria pre-pianifica buffer per i risultati intermedi, riducendo i costi di allocazione e trasferimento. L'ottimizzazione cambia solo "come calcolare", non "cosa calcolare". Il numero di kernel, la dimensione dei tensori intermedi, la memoria e le strategie di scheduling possono cambiare, ma il significato logico di mutazione, crossover e selezione, l'ordine di composizione degli operatori e il modo di utilizzo dei numeri casuali dovrebbero rimanere coerenti
- con lo stesso seme casuale, le traiettorie generazionali e i risultati prima e dopo l'ottimizzazione dovrebbero essere coerenti. Scambiare la tensorizzazione per un cambio di algoritmo evolutivo, o ritenere che l'ottimizzazione del compilatore renda l'algoritmo "più intelligente". La tensorizzazione applica solo lo stesso operatore all'intero tensore della popolazione
- anche l'ottimizzazione del compilatore ricade solo a livello di esecuzione. Se dopo l'ottimizzazione non si fa una verifica di regressione, è facile scambiare le differenze di implementazione per miglioramenti dell'algoritmo.

> **Spunti dai materiali**
>
> - Nella figura, a sinistra c'è il tensore della popolazione [N, D] con tutti gli individui, al centro il grafo computazionale degli operatori evolutivi "mutazione → crossover → selezione", a destra il confronto tra prima della compilazione "ciclo individuo per individuo, molteplici avvii di kernel, dimensione batch pari a 1" e dopo la compilazione "grafo computazionale fuso, pochi kernel GPU efficienti, un singolo forward batch completa l'intera generazione evolutiva". Si può usare questo flusso per aiutare gli studenti a collegare tensorizzazione e ottimizzazione del compilatore.

**Gestione degli esercizi**

Gli esercizi di questa pagina ruotano attorno alla granularità di esecuzione e al mantenimento della semantica.

L'operatore di mutazione in una singola chiamata agisce tipicamente sull'intero tensore della popolazione [N, D]; non è il vettore dei valori della funzione obiettivo, né il vettore decisionale di un singolo individuo.

Il ciclo Python/CPU individuo per individuo è lento perché un gran numero di chiamate su piccola scala porta costi di scheduling e framework, e la dimensione batch è 1, con basso utilizzo del dispositivo.

Il beneficio principale della fusione di operatori è combinare più operazioni elemento per elemento in meno kernel, riducendo tensori intermedi e numero di avvii di kernel; non cambia la distribuzione di probabilità o il significato dell'operatore.

Cambia solo il modo di esecuzione, non il significato logico e l'ordine di composizione di mutazione, crossover e selezione.

La ristrutturazione di population[i] = mutate(ind) dovrebbe diventare population = mutate(population_tensor), affidando la sequenza di operatori all'ottimizzazione del compilatore del grafo computazionale; ridurre N, cambiare la sintassi del ciclo o usare solo il multi-threading CPU non risolve il problema della granularità di esecuzione.

Prendendo come esempio una strategia evolutiva con dimensione della popolazione N = 4096 e dimensione D = 128, l'implementazione iniziale ha un utilizzo del dispositivo inferiore al 30%, il tempo per generazione cresce approssimativamente in modo lineare con N, e l'occupazione della memoria video è elevata. La diagnosi dovrebbe cadere sulla granularità di esecuzione: il ciclo individuo per individuo amplifica i costi fissi di N volte, la dimensione batch degenera a 1, le unità parallele non si saturano, i risultati intermedi vengono creati e distrutti ripetutamente. La ristrutturazione si divide in tre passi: primo, tensorizzare gli operatori, facendo agire direttamente mutazione, crossover e selezione sul tensore [N, D]; secondo, abilitare la compilazione del grafo computazionale, con fusione di operatori, generazione di kernel, riuso della memoria e ottimizzazione dello scheduling; terzo, fissare il seme casuale per la verifica di regressione, confrontando le curve della migliore fitness per generazione e le statistiche della popolazione prima e dopo l'ottimizzazione.

Se le curve sono sostanzialmente sovrapposte, significa che è cambiato solo il modo di esecuzione; se divergono, verificare prima se è stato cambiato l'ordine degli operatori, il numero di utilizzi dei numeri casuali o le regole di selezione.

**Verifica della comprensione**

Un operatore evolutivo dovrebbe agire su un singolo individuo o sull'intero tensore della popolazione? Qual è la catena di equivalenza dalla fusione di operatori all'utilizzo del dispositivo? Come verificare che l'ottimizzazione non abbia cambiato la semantica dell'algoritmo? Risposta attesa: agisce sul tensore della popolazione [N, D]; più fusione, meno avvii di kernel, meno letture/scritture di tensori intermedi, maggiore utilizzo del dispositivo; confrontare con lo stesso seme casuale le curve della migliore fitness per generazione e le statistiche della popolazione prima e dopo l'ottimizzazione.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere tensorizzazione e compilazione del grafo computazionale, e sanno verificare con lo stesso seme che la semantica è invariata, passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-8"></a>

### Progettazione dell'Architettura Aperta e Disaccoppiata dell'Infrastruttura

*Pagina 8*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere i principi di progettazione disaccoppiata dell'architettura dell'infrastruttura EvoX e la divisione dei componenti principali.

> **Obiettivo della pagina**
>
> Comprendere i principi di progettazione dell'infrastruttura aperta e disaccoppiata di EvoX e la divisione delle responsabilità dei cinque moduli principali, sapendo usare i "confini dei moduli" per determinare dove ricade un requisito.

> **Ordine di esposizione**
>
> Fornire prima il giudizio centrale — i ricercatori non dovrebbero spendere tempo su comunicazione parallela, allocazione dei dispositivi e tolleranza ai guasti distribuita; poi introdurre i cinque moduli di primo livello, e infine usare il diagramma architetturale per spiegare la relazione a livelli tra la logica evolutiva superiore e lo scheduling unificato inferiore.

**Punti chiave della lezione**

- Il modulo degli algoritmi definisce "come evolvere"
- il modulo dei problemi fornisce un'interfaccia di valutazione unificata
- il workflow organizza l'evoluzione per fasi
- il modulo di monitoraggio osserva il processo evolutivo
- lo scheduler Runtime come livello di esecuzione unificato risponde a "dove calcolare, come calcolare in modo efficiente". Promemoria: "la logica evolutiva in alto, lo scheduling della potenza di calcolo in basso", nell'ordine algoritmo → modulo dei problemi → workflow → modulo di monitoraggio → scheduler Runtime. Il modulo degli algoritmi descrive solo logica di ricerca come selezione, crossover, mutazione, aggiornamento, non è vincolato a un problema specifico, né percepisce su quale scheda si trovi il tensore
- il modulo dei problemi incapsula simulazione, funzione obiettivo o ambiente in un'interfaccia di valutazione unificata
- il workflow determina l'ordine delle fasi di inizializzazione, evoluzione iterativa, determinazione della convergenza
- il modulo di monitoraggio raccoglie indicatori, registra lo stato della popolazione e le curve di convergenza
- lo scheduler Runtime nasconde le differenze tra GPU, dispositivi acceleratori e cluster distribuiti, prendendo in carico calcolo batch, parallelismo e dettagli di comunicazione. Algoritmo e problema sono indipendenti l'uno dall'altro, problema e potenza di calcolo sono indipendenti l'uno dall'altro. Quando si aggiunge un operatore di mutazione, basta modificare il modulo degli algoritmi
- il modulo dei problemi continua a fornire l'interfaccia di valutazione unificata, il workflow e il modulo di monitoraggio mantengono l'organizzazione originale, lo scheduler Runtime completa automaticamente il calcolo tensoriale batch e l'allocazione dei dispositivi, il codice di esecuzione sottostante non necessita di modifiche. Pertanto la stessa infrastruttura può sostenere scenari come apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria, evitando la costruzione ripetuta di infrastrutture ingegneristiche per parallelismo, scheduling e distribuzione. Disaccoppiamento non significa necessariamente prestazioni peggiori. Ciò che influisce realmente sulle prestazioni è il modo in cui lo scheduler Runtime gestisce il calcolo batch e l'utilizzo dei dispositivi, non il numero di moduli. Per giudicare se la stratificazione è efficiente, confrontare tempo end-to-end, utilizzo del dispositivo e quota di comunicazione
- se i costi di scheduling aumentano, si dovrebbe ottimizzare la strategia di calcolo batch e utilizzo dei dispositivi dello scheduler Runtime, non riscrivere il codice parallelo nel modulo degli algoritmi. Usare "cosa bisogna cambiare" per verificare il disaccoppiamento. Cambiare hardware o scala del cluster dovrebbe modificare solo lo scheduler Runtime
- cambiare problema dovrebbe modificare solo il modulo dei problemi
- cambiare operatore dovrebbe modificare solo il modulo degli algoritmi. Se una piccola modifica coinvolge più di tre livelli, significa che l'implementazione è già troppo accoppiata. Il disaccoppiamento fa risparmiare ingegneria ripetuta, non tempo di calcolo; rimane comunque necessaria una verifica sperimentale di benchmark per stabilire se i costi di scheduling sono accettabili.

**Gestione degli esercizi**

I cinque moduli principali: l'esclusione (la risposta è "ricercatore di iperparametri", che appartiene alla configurazione sperimentale o alla strategia algoritmica, non è un modulo di primo livello dell'infrastruttura); la manifestazione accurata di alta coesione e basso accoppiamento (la risposta è che la logica interna del modulo degli algoritmi è coerente e non vincolata a un problema specifico, e il modulo dei problemi non percepisce la potenza di calcolo sottostante); la responsabilità centrale dello scheduler Runtime (la risposta è nascondere le differenze tra GPU, dispositivi acceleratori e cluster distribuiti e schedulare l'esecuzione in modo unificato); l'ambito di modifica quando si aggiunge un operatore di mutazione (la risposta è implementare solo la nuova logica nel modulo degli algoritmi, mentre problema, workflow, monitoraggio e scheduling Runtime rimangono invariati); il significato più diretto dell'accesso aperto unificato (la risposta è che vari domini riutilizzano la stessa infrastruttura ingegneristica).

Nel feedback, far prima tornare gli studenti ai "confini di responsabilità dei cinque moduli" per trovare le prove, poi spiegare perché le altre opzioni rompono i confini o confondono le responsabilità.

Nell'espansione su cluster GPU multi-nodo, il modulo degli algoritmi, il modulo dei problemi, il workflow e il modulo di monitoraggio dovrebbero rimanere invariati, perché le loro responsabilità sono indipendenti dalla forma della potenza di calcolo; ciò che deve essere modificato o riconfigurato è lo scheduler Runtime. Se si dibatte tra "scrivere a mano l'allocazione dei dispositivi e la comunicazione all'interno dell'operatore" e "affidarsi completamente allo scheduler Runtime", la chiave di valutazione è su quale livello cade la modifica: allocazione dei dispositivi e comunicazione appartengono al livello di esecuzione, scriverle nell'operatore accoppierebbe i dettagli della potenza di calcolo nel modulo degli algoritmi. La soluzione di verifica è confrontare sullo stesso problema di ottimizzazione combinatoria il tempo end-to-end, l'utilizzo del dispositivo e la quota di costi di comunicazione tra scheduling puro via Runtime e scheduling scritto a mano, e registrare il costo di migrazione a un altro tipo di hardware o a un compito di apprendimento per rinforzo;

solo quando un beneficio significativo e riproducibile può compensare i costi di accoppiamento e migrazione, si può considerare una discesa locale.

**Verifica della comprensione**

Chiedere agli studenti di ripetere con parole proprie i cinque moduli e le domande a cui ciascuno risponde, e scegliere un requisito per determinare quale livello dovrebbe essere modificato. Suggerimento di transizione: dopo aver confermato che gli studenti sanno distinguere "logica evolutiva" e "scheduling della potenza di calcolo", passare ai dettagli implementativi dell'evoluzione parallela tensorizzata successiva.

<a id="lecture-page-9"></a>

### Divisione tra Modulo degli Algoritmi e Modulo dei Problemi

*Pagina 9*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere le responsabilità e le modalità di interazione tra modulo degli algoritmi e modulo dei problemi nell'architettura dell'infrastruttura.

> **Obiettivo della pagina**
>
> Comprendere i confini di responsabilità, il contratto di interfaccia tra modulo degli algoritmi e modulo dei problemi nell'infrastruttura aperta e disaccoppiata di EvoX, e il significato di questa divisione per problemi multi-obiettivo, con vincoli e con feedback costoso.

> **Ordine di esposizione**
>
> Ancorare prima la divisione dei compiti in una frase — il modulo degli algoritmi risponde a "come cercare", il modulo dei problemi risponde a "cosa valutare, come l'ambiente fornisce feedback". Poi sviluppare input e output dei due, e infine arrivare a espansione indipendente, componibilità e trasferibilità portate dalla stabilità del contratto di interfaccia.

**Punti chiave della lezione**

- 1. Il modulo degli algoritmi incapsula la strategia di ricerca e il meccanismo evolutivo. Si occupa di generazione delle soluzioni candidate, inizializzazione della popolazione, mutazione, crossover, selezione, conservazione degli elite, oltre a controllo della ricerca come numero di iterazioni, dimensione della popolazione, riavvio e criteri di convergenza, scheduling dei parametri degli operatori. Il punto chiave è che dipende solo dal presupposto astratto "le soluzioni candidate saranno valutate", non si interessa del significato fisico e della forma concreta della funzione obiettivo. 2. Il modulo dei problemi definisce i criteri di valutazione e il feedback dell'ambiente. Trasforma le soluzioni candidate in feedback comparabili, come valori obiettivo, fitness, quantità di violazione dei vincoli o un risultato di interazione con l'ambiente
- allo stesso tempo dichiara la dimensione delle variabili, l'intervallo di valori e le regole del dominio fattibile, facendo sapere all'algoritmo dove generare le soluzioni candidate. Il modulo dei problemi fornisce una valutazione coerente per lo stesso batch di soluzioni candidate, permettendo il confronto orizzontale tra individui diversi, generazioni diverse o persino algoritmi diversi. Il modulo degli algoritmi invia un batch di soluzioni candidate, il modulo dei problemi restituisce risultati di valutazione strutturati (vettore degli obiettivi, quantità di violazione dei vincoli e informazioni diagnostiche opzionali), il modulo degli algoritmi su questa base aggiorna la popolazione e porta avanti la generazione successiva. Un ciclo "invio-restituzione" è una generazione evolutiva. La correttezza della direzione è importante: il lato algoritmo invia le soluzioni candidate da valutare, il lato problema restituisce i risultati della valutazione. Espansione indipendente — aggiungere o sostituire un algoritmo non influisce sulla definizione del problema, modificare o aggiungere un problema non richiede di riscrivere il modulo degli algoritmi
- componibilità — lo stesso modulo dei problemi può essere collegato a diversi algoritmi evolutivi, lo stesso modulo degli algoritmi può essere commutato su diversi moduli dei problemi
- trasferibilità — finché il contratto è stabile, i due lati possono essere riutilizzati, sostituiti e trasferiti tra compiti. I problemi ingegneristici reali come la progettazione di profili alari supercritici hanno spesso simultaneamente molteplici obiettivi in conflitto tra loro, vincoli annidati e feedback costoso e sparso. Il modulo dei problemi converte in modo unificato obiettivi multipli e vincoli in risultati di valutazione comparabili, ricorrendo a modelli surrogati per ridurre i costi quando necessario
- il modulo degli algoritmi mantiene un insieme di soluzioni candidate diversificate, supportando gli esperti nella scelta di preferenze tra portanza, resistenza e margine di sicurezza. Pertanto il contratto non può trasportare solo una singola fitness scalare, ma deve anche trasportare vettore degli obiettivi e quantità di violazione dei vincoli, altrimenti le informazioni multi-obiettivo e sui vincoli andrebbero perse definitivamente all'interfaccia.

**Copertura delle parole chiave**

- Modulo degli algoritmi, modulo dei problemi, batch di soluzioni candidate, risultati di valutazione, vettore degli obiettivi, quantità di violazione dei vincoli, contratto di interfaccia, espansione indipendente, componibilità, trasferibilità, modelli surrogati. Scrivere la funzione obiettivo, la gestione dei vincoli o regole euristiche specifiche del problema nel modulo degli algoritmi, o implementare selezione e aggiornamento della popolazione nel modulo dei problemi, riaccoppia i due lati. La domanda di autoverifica è: "Se modifico solo il modello fisico, devo solo sostituire il modulo dei problemi?" La risposta deve essere affermativa. L'interfaccia deve essere "stretta e completa": stretta significa pochi campi e stabili, trasmettendo solo due tipi di informazioni, batch di soluzioni candidate e risultati di valutazione
- completa significa che le informazioni chiave non devono essere incomplete, vettore degli obiettivi, quantità di violazione dei vincoli, dimensione delle variabili e limiti devono essere conservati. Restituire solo una singola fitness scalare è il difetto di progettazione più difficile da rimediare a posteriori.

> **Spunti per gli esercizi**
>
> - Cinque domande a scelta multipla verificano rispettivamente — chi si occupa della ricerca, la responsabilità centrale del modulo dei problemi, la direzione del flusso dati del contratto, l'espansione indipendente dopo il disaccoppiamento, le conseguenze della fitness scalare singola. Le risposte corrette indicano in sequenza: il modulo degli algoritmi genera soluzioni candidate e aggiorna la popolazione
> - il modulo dei problemi trasforma le soluzioni candidate in valori obiettivo, quantità di violazione dei vincoli o risultati di interazione con l'ambiente
> - il modulo degli algoritmi produce batch di soluzioni candidate, il modulo dei problemi restituisce risultati di valutazione
> - finché il contratto è invariato, sostituendo uno dei due lati l'altro non necessita di riscrittura
> - scartare le informazioni sui vincoli impedisce all'algoritmo di ottenere feedback sui vincoli, rendendo difficile gestire correttamente problemi con vincoli. Nel feedback, se lo studente risponde correttamente, chiedere di spiegarne le motivazioni
> - se sbaglia, guidarlo a tornare ai due punti "chi cerca, chi valuta" e "il contratto è completo" per un nuovo giudizio. Nel passaggio dall'ottimizzazione aerodinamica del profilo alare alla riduzione di peso della struttura alare, sostituire l'algoritmo evolutivo non richiede di riscrivere il modulo dei problemi, perché il modulo dei problemi promette solo "input batch di soluzioni candidate, output risultati di valutazione", indipendentemente dal meccanismo interno di selezione, aggiornamento o ordinamento dell'algoritmo. Quando si riutilizza lo stesso algoritmo per la minimizzazione del peso strutturale, il modulo dei problemi deve restituire almeno tre tipi di informazioni: valori obiettivo (peso strutturale, o vettore degli obiettivi se ci sono indicatori di rigidità), quantità di violazione dei vincoli (grado di superamento dei vincoli di rigidità e fattibilità geometrica), dimensione e intervallo di valori delle variabili dello spazio di ricerca. Nessuno può mancare, perché l'algoritmo si occupa solo della ricerca, ha bisogno del valore obiettivo per giudicare il meglio/peggio, ha bisogno della quantità di violazione dei vincoli per distinguere fattibile e non fattibile, ha bisogno di limiti coerenti per generare soluzioni candidate valide.

**Attività in classe**

Far ripetere agli studenti con ancoraggi mnemonici — modulo degli algoritmi = come cercare (generazione, mutazione, crossover, selezione, controllo delle iterazioni); modulo dei problemi = cosa valutare (valori obiettivo, quantità di violazione dei vincoli, feedback dell'ambiente). Poi chiedere a uno studente di rispondere: "Se si modifica solo il modello fisico, quale lato dovrebbe essere sostituito?"

**Verifica della comprensione**

Chiedere a uno studente a caso di esprimere con parole proprie il flusso dati "batch di soluzioni candidate ⇄ risultati di valutazione", e di spiegare perché restituire solo una singola fitness scalare romperebbe la gestione di problemi con vincoli.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere ricerca e valutazione, e sanno spiegare che il contratto deve essere "stretto e completo", passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-10"></a>

### Gestione del Workflow e del Modulo di Monitoraggio

*Pagina 10*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere il ruolo del controllo del workflow e del modulo di monitoraggio nella gestione del processo evolutivo.

> **Obiettivo della pagina**
>
> Al termine di questa pagina, lo studente dovrebbe saper distinguere le responsabilità del modulo del workflow e del modulo di monitoraggio, e spiegare come i due trasformino il ciclo evolutivo da "scatola nera sconosciuta" in un processo controllato, osservabile, determinabile, intervenibile e riproducibile.

> **Ordine di esposizione**
>
> Stabilire prima la divisione in una frase — il workflow risponde a "in che ordine eseguire", il monitoraggio risponde a "a che punto siamo, va bene, serve intervenire". Poi sviluppare l'ordine del workflow, i bordi di ritorno e i confini di fase, quindi spiegare come il monitoraggio raccolga stato, esponga indicatori e guidi le decisioni. Infine convergere sui tre confini di responsabilità e sul costo dell'osservabilità, e usare l'esempio di evoluzione tensorizzata su GPU per collegare l'intera logica.

**Punti chiave della lezione**

- 1. Il modulo del workflow orchestra passi e dipendenze, non la logica dell'algoritmo stesso. Definisce l'ordine, i bordi di ritorno e i confini di fase di "inizializzazione → valutazione (batch) → selezione → mutazione/crossover → aggiornamento dello stato → determinazione della terminazione", e collega modulo degli algoritmi e modulo dei problemi tramite un'interfaccia unificata. La chiave dell'orchestrazione sta nella granularità e nei confini: considerare "una valutazione batch" come una fase schedulabile nel suo insieme, non avanzare individuo per individuo
- i confini di fase sono allo stesso tempo punti di campionamento del monitoraggio e punti di commutazione dello scheduling. 2. Il modulo di monitoraggio è il livello di raccolta ed esposizione dello stato di esecuzione, traccia continuamente indicatori come dimensione della popolazione, numero di valutazioni, distribuzione della fitness, convergenza e diversità, tempo per generazione, memoria video e throughput. Ma lo scopo dell'osservazione non è registrare, bensì decidere: gli indicatori sono usati per attivare terminazione, early stopping, riavvio, commutazione di parametri o strategie, formando così il ciclo chiuso "monitoraggio → determinazione → intervento". 3. La controllabilità richiede anche che lo stato sia serializzabile. Il salvataggio e il ripristino dei checkpoint rendono l'evoluzione di lunga durata interrompibile e riprendibile, i guasti localizzabili, gli esperimenti riproducibili. Allo stesso tempo, il disaccoppiamento richiede che il monitoraggio sia montato tramite callback o hook, senza invadere il modulo degli algoritmi e dei problemi, permettendo di scambiare backend di monitoraggio diversi come console, log, pannelli di curve, senza modificare l'algoritmo principale. Il workflow gestisce "ordine e fasi", il monitoraggio gestisce "stato e indicatori", lo scheduler runtime gestisce "risorse e mappatura parallela". L'errore comune è infilare la mappatura delle risorse o la logica dell'algoritmo nel workflow, o il controllo dell'ordine nel monitoraggio, causando accoppiamento e non riproducibilità. Anche l'osservabilità ha un costo: campionamento ad alta frequenza e rimbalzo sincrono possono interrompere la pipeline parallela, quindi frequenza di campionamento, modalità di aggregazione degli indicatori e strategia di scrittura asincrona su disco devono essere bilanciate secondo gli scopi sperimentali. Il workflow schedula "valutazione batch" come una fase intera
- il modulo di monitoraggio registra per generazione, nella stessa fase, la migliore e la media della fitness, la diversità della popolazione e il tempo per generazione
- quando gli indicatori stagnano per N generazioni consecutive, attiva la determinazione di terminazione o la commutazione a una strategia con perturbazione maggiore, e salva sincronicamente il checkpoint, rendendo questa evoluzione riproducibile e riprendibile dal punto di interruzione.

**Copertura delle parole chiave**

- Modulo del workflow, modulo di monitoraggio, passi e dipendenze, confini di fase, bordi di ritorno, valutazione batch, osservabilità, monitoraggio→determinazione→intervento, checkpoint, callback/hook, confini di responsabilità, costo del campionamento.

> **Spunti per gli esercizi**
>
> - Gli esercizi di questa pagina ruotano attorno a cinque giudizi. L'oggetto diretto dell'orchestrazione del workflow sono passi e dipendenze, non formule di operatori, mappatura della memoria video o codifica della funzione obiettivo
> - considerare la valutazione batch come una fase intera perché la granularità e i confini sono più appropriati, i confini di fase assumono simultaneamente il campionamento del monitoraggio e la commutazione dello scheduling
> - lo scopo fondamentale del monitoraggio è decidere, non archiviare a posteriori
> - il montaggio tramite callback o hook serve al disaccoppiamento, permettendo di scambiare i backend di monitoraggio
> - l'osservabilità richiede di bilanciare frequenza di campionamento, aggregazione degli indicatori e strategia di scrittura su disco, perché campionamenti ad alta frequenza possono interferire con la pipeline parallela. In caso di risposta corretta, sottolineare che le motivazioni vengono dalle due linee "ordine e fasi" e "monitoraggio→determinazione→intervento"
> - in caso di errore, tornare ai confini di responsabilità, distinguendo le quattro categorie di responsabilità: logica dell'algoritmo, mappatura delle risorse, controllo dell'ordine e raccolta dello stato.

**Verifica della comprensione**

Si può usare il caso "pausa sospetta nell'evoluzione tensorizzata di lunga durata" per verificare il livello di padronanza. Prima usare i confini di fase per separare i tempi di valutazione batch, selezione, mutazione, aggiornamento dello stato, e determinare da quale fase derivi l'aumento del tempo per generazione; poi sovrapporre le due curve di stagnazione della fitness media e calo della diversità, per giudicare se si tratta di convergenza verso la stabilità o di intrappolamento in un ottimo locale. Il piano di intervento si organizza secondo "monitoraggio → determinazione → intervento": il livello di monitoraggio raccoglie generazioni di stagnazione della fitness, diversità e tempo per generazione; il livello di determinazione imposta "miglioramento inferiore alla soglia per N generazioni consecutive e diversità sotto il limite inferiore" come stagnazione, "tempo per generazione oltre la soglia" come anomalia di risorse; il livello di intervento attiva commutazione di strategia, early stopping o riavvio, e per l'anomalia di tempo aggiusta la dimensione del batch o la mappatura parallela.

Prima dell'intervento, salvare il checkpoint, garantendo la riproducibilità dell'esperimento, la localizzabilità dei guasti e la riprendibilità dell'evoluzione di lunga durata.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno dire "il workflow gestisce ordine e fasi, il monitoraggio gestisce stato e indicatori, lo scheduler gestisce risorse e mappatura parallela", passare alla pagina successiva.

<a id="lecture-page-11"></a>

### Scheduler Runtime e Gestione della Potenza di Calcolo Eterogenea

*Pagina 11*

> **Obiettivo della pagina:** Lo studente dovrebbe padroneggiare il ruolo centrale dello scheduler Runtime nell'allocazione di hardware eterogeneo e nella componibilità degli algoritmi.

> **Obiettivo della pagina**
>
> Padroneggiare la posizione dello scheduler Runtime in EvoX — è il centro di esecuzione che collega la logica dell'algoritmo all'hardware fisico, responsabile di mappare algoritmi evolutivi, definizioni dei problemi e workflow di livello superiore su risorse di calcolo eterogenee come GPU, dispositivi acceleratori (TPU/NPU) e cluster distribuiti, e di mantenere l'elevata componibilità del modulo degli algoritmi nascondendo le differenze hardware.

> **Ordine di esposizione**
>
> 1. Distinguere prima il livello dell'algoritmo dal livello di esecuzione. Il livello dell'algoritmo si concentra su "cosa fare", il Runtime su "dove farlo, come farlo". Questa separazione è la chiave per comprendere l'architettura EvoX.
>
> Scheduling di potenza di calcolo eterogenea, gestione unificata di GPU, dispositivi acceleratori e cluster distribuiti, distribuzione di compiti, operatori e grafi computazionali tensoriali sui backend appropriati; coordinamento di dipendenze e stato, garantendo la corretta sincronizzazione delle relazioni di dipendenza dei compiti e dello stato di esecuzione; interfaccia di scheduling unificata, in modo che il livello dell'algoritmo non debba vincolarsi a un dispositivo o forma di cluster specifici al momento dell'invio dei compiti; componibilità dei moduli, supportando la combinazione, sostituzione e riuso modulare di algoritmi, problemi, operatori e backend di esecuzione.
>
> Quando lo stesso algoritmo evolutivo passa da GPU singola a cluster multi-macchina, il codice del livello dell'algoritmo rimane invariato, e il Runtime rimappa compiti di calcolo e backend di esecuzione. I ricercatori possono quindi concentrarsi sull'innovazione algoritmica senza riscrivere il codice per ogni tipo di hardware.
>
> In alto c'è il livello di algoritmi e workflow (modulo degli algoritmi, definizione dei problemi, workflow), al centro lo scheduler Runtime e l'interfaccia di scheduling unificata, in basso il livello di potenza di calcolo eterogenea (GPU, TPU/NPU, cluster distribuiti); verso il basso passano compiti, operatori e grafi computazionali, verso l'alto tornano stato e risultati.

**Punti chiave della lezione**

- Il Runtime non implementa la logica dell'algoritmo evolutivo, né definisce la funzione obiettivo del problema
- la sua responsabilità è scheduling e mappatura. Le risorse di esecuzione che gestisce sono risorse hardware, come GPU, dispositivi acceleratori e cluster distribuiti
- il codice sorgente del modulo degli algoritmi appartiene al livello dell'algoritmo, non è un oggetto dello scheduling Runtime. Il livello dell'algoritmo deve solo descrivere cosa fare, senza preoccuparsi su quale hardware farlo, quindi lo stesso algoritmo può migrare su singola macchina, multi-GPU o ambiente cross-cluster. La componibilità significa che algoritmi, problemi, operatori e backend di esecuzione possono combinarsi, sostituirsi e riutilizzarsi liberamente, senza essere vincolati a un singolo backend hardware.

**Copertura delle parole chiave**

- Scheduler Runtime, scheduling di potenza di calcolo eterogenea, coordinamento di dipendenze e stato, interfaccia di scheduling unificata, componibilità dei moduli, GPU, dispositivi acceleratori, TPU/NPU, cluster distribuiti, livello dell'algoritmo, livello di esecuzione.

> **Spunti dai materiali**
>
> - Questa pagina è corredata dal diagramma architetturale dello scheduler Runtime che collega dispositivi hardware e algoritmi di livello superiore. Nella figura, in alto il livello di algoritmi e workflow, al centro lo scheduler Runtime e l'interfaccia di scheduling unificata, in basso il livello di potenza di calcolo eterogenea
> - le frecce indicano la distribuzione verso il basso di compiti/operatori/grafi computazionali, e il ritorno verso l'alto di stato/risultati. Nel commentare la figura, si può chiedere agli studenti di ripetere lungo le frecce "cosa invia il livello superiore, cosa fa il Runtime, cosa restituisce il livello inferiore".

**Gestione degli esercizi**

La risposta corretta alla domanda 1 a scelta multipla è mappare algoritmi e workflow su risorse di calcolo eterogenee e nascondere le differenze hardware. Punto di feedback: il Runtime è il centro di esecuzione, non implementa la logica dell'algoritmo, né definisce il problema.

Il Runtime gestisce le risorse di esecuzione hardware, il codice sorgente appartiene al contenuto del livello dell'algoritmo.

La risposta corretta alla domanda 3 a scelta multipla è che tramite l'interfaccia di scheduling unificata, il livello dell'algoritmo non deve vincolarsi a un dispositivo o forma di cluster specifici. Punto di feedback: ridurre l'accoppiamento significa che il livello dell'algoritmo non ha bisogno di scrivere codice diverso per ogni tipo di hardware.

La risposta corretta alla domanda 4 a scelta multipla è che algoritmi, problemi, operatori e backend di esecuzione si combinano, sostituiscono e riutilizzano in modo modulare. Punto di feedback: la componibilità si manifesta nella libertà di combinare e sostituire i componenti.

La risposta corretta alla domanda 5 a scelta multipla è rimappare compiti di calcolo e backend di esecuzione, con il codice del livello dell'algoritmo invariato. Punto di feedback: il Runtime regola dinamicamente la mappatura dei compiti, il livello dell'algoritmo non necessita di modifiche.

Nello scenario di progettazione multi-obiettivo di profili alari, il team ottimizza simultaneamente coefficiente di portanza e rapporto portanza/resistenza in crociera, e migra lo stesso codice algoritmico tra GPU singola e cluster distribuito. Nel rispondere, aggrapparsi a due punti: primo, il Runtime tramite l'interfaccia di scheduling unificata mappa compiti, operatori e grafi computazionali sul backend hardware specifico; al cambio di hardware il codice del livello dell'algoritmo rimane invariato, e il Runtime rimappa e suddivide il grafo computazionale, coordinando dipendenze dei compiti e sincronizzazione dello stato. Secondo, nello scheduling si devono considerare le caratteristiche di calcolo e le relazioni di dipendenza dei compiti, le capacità hardware (come il grado di parallelismo della GPU, i costi di comunicazione del cluster), l'esecuzione parallela della valutazione multi-obiettivo e la sincronizzazione con feedback sparso, e il ritorno dello stato, garantendo un atterraggio efficiente cross-hardware senza rompere la componibilità.

**Verifica della comprensione**

Chiedere agli studenti di spiegare con parole proprie "il livello dell'algoritmo si concentra su cosa fare, il Runtime su dove farlo e come farlo", e di fare un esempio di quale livello cambia e quale rimane invariato passando da GPU a cluster. Se lo studente ricorda solo i nomi dell'hardware senza spiegare le relazioni di scheduling e mappatura, guidarlo a tornare alle relazioni delle frecce del diagramma architetturale.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno esprimere il ruolo di scheduling e mappatura del Runtime, e sanno spiegare la migrazione cross-hardware con interfaccia unificata e componibilità, passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-12"></a>

### Applicazioni Multi-Dominio Supportate dall'Infrastruttura Unificata

*Pagina 12*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere come questa infrastruttura unificata supporti compiti ampi come apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria.

> **Ordine di esposizione**
>
> Iniziare con una frase che chiarisca "infrastruttura unificata = accesso aperto + esecuzione tensorizzata + scheduling Runtime. Quando si vede 'applicazioni multi-dominio', autoverificare con queste tre domande: come si accede al compito? Come si valutano in batch le soluzioni candidate? Chi gestisce in modo unificato potenza di calcolo e stato?", poi spiegare perché è importante combinando esempi, figure o parole chiave della pagina.

**Punti chiave della lezione**

- Infrastruttura unificata = accesso aperto + esecuzione tensorizzata + scheduling Runtime. Quando si vede "applicazioni multi-dominio", autoverificare con queste tre domande: come si accede al compito? Come si valutano in batch le soluzioni candidate? Chi gestisce in modo unificato potenza di calcolo e stato?
- Parallelismo del passo ambientale, evoluzione della struttura ad albero del programma, mappatura tensoriale discreta appartengono al livello di adattamento
- flusso di valutazione, gestione dello stato, organizzazione degli operatori e scheduling appartengono al livello condiviso. Se si scrive direttamente la struttura proprietaria di un dominio nella logica di scheduling condivisa, significa che il livello di astrazione scelto è sbagliato.
- Questa pagina risponde solo a "cosa può supportare l'infrastruttura unificata". Questioni come throughput, costi di scheduling, dettagli implementativi del calcolo tensoriale batch vanno rimandate al successivo ambito di studio su efficienza di calcolo e metodi tensoriali batch, senza soffermarsi qui.

Applicazioni multi-dominio supportate dall'infrastruttura unificata

11

AI999

Infrastruttura di calcolo moderna ed evoluzione parallela tensorizzata

I compiti di controllo e decisione richiedono interazione continua con un ambiente in evoluzione, i compiti di progettazione strutturale richiedono ricerca in uno spazio di programmi ed espressioni a lunghezza variabile, e i compiti di allocazione delle risorse e pianificazione dei percorsi richiedono di risolvere in permutazioni e vincoli discreti. Se per ogni tipo di problema si dovesse ricostruire un sistema separato, interfacce di valutazione, archiviazione dello stato, librerie di operatori e scheduling della potenza di calcolo dovrebbero essere reimplementati, con costi di migrazione ingegneristica estremamente elevati. L'idea centrale dell'infrastruttura unificata è usare la stessa infrastruttura evolutiva per sostenere questi compiti eterogenei, facendo condividere alle applicazioni multi-dominio valutazione, stato, operatori e gestione della potenza di calcolo.

Accesso aperto (accedere ai compiti con specifiche di registrazione e interfaccia unificate), esecuzione tensorizzata (organizzare le soluzioni candidate in batch e valutarle in parallelo in batch), scheduling Runtime (allocare compiti su potenza di calcolo eterogenea e mantenere lo stato). I tre insieme garantiscono il riuso cross-dominio, e spiegano anche perché la capacità "fornire un'infrastruttura di accesso aperto unificata per apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria" meriti una discussione separata.

Applicazioni multi-dominio supportate dall'infrastruttura unificata — Stessa infrastruttura di accesso aperto · Flusso di valutazione, gestione dello stato, organizzazione degli operatori e scheduling della potenza di calcolo condivisi — Capacità dell'infrastruttura / Dominio del compito — Apprendimento per rinforzo — Programmazione genetica — Ottimizzazione combinatoria — Accesso aperto — Interfaccia di accesso all'ambiente — Accesso alla struttura del programma — Accesso a soluzioni e vincoli — Interazione ambientale parallela — Campionamento batch multi-ambiente — — — Evoluzione della struttura ad albero del programma — — Mutazione/crossover — — Risoluzione tensorizzata — Valutazione batch delle strategie — Tensorizzazione della struttura — Batch di candidati e vincoli — Scheduling Runtime e gestione dello stato — Scheduling e stato condivisi — Scheduling e stato condivisi — Scheduling e stato condivisi — Livello di adattamento: assorbe le differenze di dominio — Parallelismo del passo ambientale · Evoluzione della struttura ad albero del programma · Mappatura tensoriale discreta — Infrastruttura unificata: accesso aperto · esecuzione tensorizzata · scheduling Runtime e gestione dello stato — Come tre tipi tipici di compiti ricadono sulla stessa infrastruttura — Apprendimento per rinforzo: l'infrastruttura fornisce capacità di interazione ambientale parallela, supporta campionamento batch di istanze multi-ambiente, valutazione parallela di un batch di strategie candidate, e forma un ciclo chiuso con l'ottimizzazione evolutiva.

L'infrastruttura supporta l'evoluzione di strutture a lunghezza variabile e gerarchiche come alberi di programma, potendo gestire rappresentazione strutturale e relative mutazioni e crossover nello stesso flusso di popolazione e valutazione. Ottimizzazione combinatoria: adatta decisioni discrete, scelte, permutazioni e obiettivi con vincoli a risoluzione tensorizzata, migliorando il throughput di ricerca tramite candidati batch e valutazione parallela. Cosa condividere, cosa adattare — Le differenze di dominio sono assorbite dal livello di adattamento: l'apprendimento per rinforzo si concentra sul parallelismo del passo ambientale, la programmazione genetica sull'evoluzione della struttura ad albero del programma, l'ottimizzazione combinatoria sulla mappatura da decisioni discrete a tensori. I tre condividono lo scheduling Runtime e la gestione dello stato sottostanti — flusso di valutazione condiviso, contenitore di stato, modalità di organizzazione degli operatori e gestione della potenza di calcolo, invece di ricostruire il sistema per ogni tipo di problema.

Se si scrive direttamente la struttura proprietaria di un dominio nella logica di scheduling condivisa, significa che il livello di astrazione scelto è sbagliato. Ambito di questa pagina — Questa pagina si concentra su "cosa può supportare l'infrastruttura unificata", senza sviluppare confronti prestazionali specifici e dettagli implementativi dello scheduler; questi sono rimandati alla successiva parte su efficienza di calcolo e metodi tensoriali batch.

Qual è il valore principale di un'infrastruttura di accesso aperto unificata?

Permettere a domini diversi di riutilizzare valutazione, stato, operatori e gestione della potenza di calcolo, riducendo significativamente i costi di migrazione ingegneristica

Sostituire apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria con un unico algoritmo unificato

Comprimere tutti i compiti in un'unica rappresentazione vettoriale a lunghezza fissa

Ricostruire sistemi e toolchain indipendenti per ogni nuova classe di problemi

Le forme dei compiti sono diverse, ma specifiche di accesso, valutazione batch, gestione dello stato e scheduling della potenza di calcolo possono essere condivisi, i nuovi problemi richiedono solo di descrivere le differenze nel livello di adattamento.

"Ricostruire il sistema per ogni classe di problemi" è proprio il problema che l'infrastruttura vuole risolvere; allo stesso tempo l'infrastruttura non richiede che tutti i compiti condividano lo stesso algoritmo o la stessa rappresentazione, le differenze sono assorbite dal livello di adattamento.

Corretto. Questa risposta si collega ai concetti di questa pagina e ne spiega le motivazioni.

Tornare alla spiegazione di questa pagina, trovare prove chiave o esempi prima di giudicare.

Nello scenario di apprendimento per rinforzo, quale capacità chiave fornisce principalmente l'infrastruttura unificata?

Operatori di mutazione e crossover di alberi di programma

Passo seriale supportato solo per un singolo ambiente

Campionamento batch di istanze multi-ambiente e raccolta di traiettorie, valutazione parallela di un batch di strategie candidate

Interfaccia di modellazione per permutazioni discrete e vincoli

Avanzamento simultaneo di istanze multi-ambiente, raccolta batch di traiettorie, valutazione parallela di strategie candidate, formando un ciclo chiuso con l'ottimizzazione evolutiva.

L'evoluzione della struttura ad albero del programma è un punto di adattamento della programmazione genetica, la modellazione di vincoli discreti è un punto di adattamento dell'ottimizzazione combinatoria; la chiave dell'apprendimento per rinforzo è il parallelismo batch dell'interazione ambientale, non il seriale su singola istanza.

Quando un compito di programmazione genetica accede all'infrastruttura unificata, quale caratteristica chiave deve supportare l'infrastruttura?

Gestire solo vettori di numeri reali a lunghezza fissa

Rappresentazione ed evoluzione di strutture a lunghezza variabile e gerarchiche come alberi di programma, incluse mutazione e crossover strutturali

Obbligare a codificare l'albero di programma in stringhe binarie a lunghezza fissa prima dell'evoluzione

Gestire solo funzioni obiettivo continue senza vincoli

Le soluzioni candidate della programmazione genetica sono strutture di programma a lunghezza variabile e gerarchiche; l'infrastruttura deve accogliere questa rappresentazione nello stesso flusso di popolazione e valutazione, e supportare mutazione e crossover corrispondenti.

I vettori a lunghezza fissa sono una rappresentazione tipica dell'ottimizzazione continua; la caratteristica centrale della programmazione genetica è proprio la struttura ad albero di programma a lunghezza variabile e gerarchica, e le operazioni evolutive su di essa.

Quando un compito di ottimizzazione combinatoria accede all'infrastruttura unificata, qual è il lavoro di adattamento più critico?

Eliminare tutti i vincoli e mantenere solo un singolo obiettivo

Riscrivere il problema come un compito di addestramento di rete neurale continuo e differenziabile

Compilare un solver dedicato separato per ogni istanza del problema

Adattare decisioni discrete, scelte, permutazioni e obiettivi con vincoli a risoluzione tensorizzata

Soluzioni candidate e vincoli sono organizzati in batch, riutilizzando la capacità di candidati batch e valutazione parallela dell'infrastruttura.

Compilare un solver dedicato per istanza equivale a tornare al vecchio percorso della "ricostruzione del sistema"; anche abbandonare i vincoli cambia il problema stesso, nessuno dei due è l'adattamento richiesto dall'infrastruttura.

Riguardo alla divisione tra livello condiviso e livello di adattamento, quale delle seguenti interpretazioni è corretta?

La logica di scheduling deve essere scritta separatamente per apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria

Il livello di adattamento fa solo presentazione dell'interfaccia, non partecipa a nessuna conversione semantica dei compiti

Il livello condiviso si occupa dell'evoluzione della struttura ad albero del programma, il livello di adattamento del passo ambientale

Le differenze di dominio sono assorbite dal livello di adattamento, i tre tipi di compiti condividono lo scheduling Runtime e la gestione dello stato sottostanti

Parallelismo del passo ambientale, evoluzione della struttura ad albero del programma, mappatura tensoriale discreta appartengono al livello di adattamento; flusso di valutazione, gestione dello stato, organizzazione degli operatori e scheduling appartengono al livello condiviso.

Scrivere la struttura proprietaria di un dominio nella logica di scheduling condivisa, o far gestire al livello condiviso l'evoluzione strutturale specifica di un dominio, sono entrambi errori di divisione dei livelli.

Lo stesso runtime supporta tre tipi di compiti eterogenei

Leggere lo scenario e rispondere alle domande.

Un team di algoritmi sta costruendo una piattaforma di calcolo evolutivo. In precedenza manteneva tre sistemi indipendenti per il controllo in apprendimento per rinforzo, la regressione simbolica (ricerca di struttura di programma) e la pianificazione di percorsi logistici: ciascuno con la propria interfaccia di valutazione, archiviazione dello stato e scheduling della potenza di calcolo, con grave duplicazione del codice, e ogni cambio di compito richiedeva di riscrivere il flusso. La nuova soluzione consiste nell'usare un'infrastruttura unificata per sostenere questi tre tipi di compiti: il compito di apprendimento per rinforzo avanza in parallelo su più istanze ambientali e raccoglie traiettorie; il compito di programmazione genetica valuta in parallelo popolazioni di alberi di programma; il compito di ottimizzazione combinatoria organizza soluzioni candidate e vincoli in batch tensoriali, con scheduling unificato per l'allocazione della potenza di calcolo eterogenea.

1. Perché il team abbandona il mantenimento di sistemi separati per ogni classe di problemi? Spiegare dal punto di vista del riuso e dei costi di migrazione.

Accesso ai compiti, valutazione batch delle soluzioni candidate, gestione dello stato di candidati e popolazione, organizzazione degli operatori e scheduling della potenza di calcolo. Mantenere separatamente significa reimplementare queste capacità tre volte, ogni nuovo compito deve ricostruire il flusso, con costi di migrazione ingegneristica molto elevati. L'infrastruttura unificata fa riutilizzare ai tre tipi di compiti lo stesso flusso di valutazione, contenitore di stato, modalità di organizzazione degli operatori e gestione della potenza di calcolo, i nuovi compiti richiedono solo di descrivere le proprie differenze nel livello di adattamento per essere accessibili.

2. Indicare le differenze che i tre tipi di compiti assorbono rispettivamente nel livello di adattamento, e spiegare cosa riutilizzano nel livello condiviso.

L'apprendimento per rinforzo si concentra sul parallelismo del passo ambientale (campionamento batch di istanze multi-ambiente, raccolta di traiettorie e valutazione batch di strategie); la programmazione genetica si concentra sulla rappresentazione ed evoluzione di strutture a lunghezza variabile e gerarchiche come alberi di programma (mutazione e crossover strutturali); l'ottimizzazione combinatoria si concentra sulla mappatura di decisioni discrete, scelte, permutazioni e obiettivi con vincoli a risoluzione tensorizzata. Il livello condiviso riutilizza: specifiche di accesso aperto, esecuzione batch tensorizzata, scheduling Runtime e gestione dello stato, e allocazione unificata di potenza di calcolo eterogenea. Proprio perché le differenze sono raccolte nel livello di adattamento e gli elementi comuni sono immersi nel livello condiviso, non è necessario ricostruire il sistema per ogni classe di problemi.

Ricordare prima i tre pilastri

Infrastruttura unificata = accesso aperto + esecuzione tensorizzata + scheduling Runtime. Quando si vede "applicazioni multi-dominio", autoverificare con queste tre domande: come si accede al compito? Come si valutano in batch le soluzioni candidate? Chi gestisce in modo unificato potenza di calcolo e stato?

Distinguere livello condiviso e livello di adattamento

Parallelismo del passo ambientale, evoluzione della struttura ad albero del programma, mappatura tensoriale discreta appartengono al livello di adattamento; flusso di valutazione, gestione dello stato, organizzazione degli operatori e scheduling appartengono al livello condiviso. Se si scrive direttamente la struttura proprietaria di un dominio nella logica di scheduling condivisa, significa che il livello di astrazione scelto è sbagliato.

I confini di questa pagina

Questa pagina risponde solo a "cosa può supportare l'infrastruttura unificata". Questioni come throughput, costi di scheduling, dettagli implementativi del calcolo tensoriale batch vanno rimandate al successivo ambito di studio su efficienza di calcolo e metodi tensoriali batch, senza soffermarsi qui.

step-1

Lo studente dovrebbe comprendere come questa infrastruttura unificata supporti compiti ampi come apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria.

lesson_4

lesson_4_slide_11

Da bozza EvoClass

Fornisce un'infrastruttura di accesso aperto unificata per apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria

lesson_id_distribution

67ee25ab22558e4ae0e13f24b7c34c2da1218107cceb1cd331b38fc3521a9743

**Fondamenti dei materiali**

Da bozza EvoClass (pagina 4-4)

> **Spunti dai materiali**
>
> - Fornisce un'infrastruttura di accesso aperto unificata per apprendimento per rinforzo, programmazione genetica e ottimizzazione combinatoria

**Attività in classe**

Chiedere di ripetere il contenuto di questa pagina con un esempio vicino all'esperienza degli studenti, e far loro spiegare la relazione tra questo esempio e "infrastruttura unificata = accesso aperto + esecuzione tensorizzata + scheduling Runtime. Quando si vede 'applicazioni multi-dominio', autoverificare con queste tre domande: come si accede al compito? Come si valutano in batch le soluzioni candidate? Chi gestisce in modo unificato potenza di calcolo e stato?"

> **Obiettivi corrispondenti**
>
> - Padroneggiare il metodo di esprimere il processo evolutivo come calcolo tensoriale batch
> - Comprendere il ruolo del Runtime nello scheduling di potenza di calcolo eterogenea e nel mantenimento della componibilità degli algoritmi

**Verifica della comprensione**

Chiedere a uno studente a caso di riassumere con parole proprie i punti chiave di questa pagina, e il docente integra le parole chiave mancanti in base alla risposta.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno esprimere la relazione centrale di questa pagina, passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-13"></a>

### Pratica di Analisi Comparativa dell'Efficienza di Calcolo

*Pagina 13*

> **Obiettivo della pagina:** Lo studente dovrebbe comprendere attraverso il confronto pratico le differenze di efficienza tra la traversata seriale su CPU e l'elaborazione batch tensorizzata su GPU.

> **Obiettivo della pagina**
>
> Portare il confronto dell'efficienza di calcolo su una pratica riproducibile, comprendere la differenza di efficienza end-to-end tra la traversata seriale individuo per individuo su CPU e l'elaborazione batch tensorizzata su GPU, chiarendo da dove viene l'accelerazione, qual è il costo e dove sono i confini.

> **Ordine di esposizione**
>
> Fornire prima le due baseline sullo stesso compito evolutivo, poi guardare il grafico a barre del confronto di efficienza, quindi spiegare il protocollo di misurazione riproducibile, e infine riassumere le fonti del beneficio, le condizioni al contorno e le conclusioni pratiche.

**Punti chiave della lezione**

- Usare un ciclo per chiamare la funzione di valutazione individuo per individuo, ogni generazione richiede N scheduling indipendenti, aggiornamenti di stato e aggregazione dei risultati. Controllo del ciclo, costi dell'interprete e accesso sparso alla memoria diluiscono la potenza di calcolo effettiva
- più numerosi sono gli individui, maggiore è la quota di questi costi non computazionali. Organizzare popolazione, input di valutazione e stato di esecuzione in tensori, eseguire in batch valutazione e operatori su GPU, una singola chiamata copre l'intero insieme di candidati, riducendo notevolmente cicli seriali e numero di scheduling. A parità di problema, popolazione, seme casuale, e con timing dopo warm-up e sincronizzazione del dispositivo, il ciclo seriale CPU è baseline 1.0×, l'elaborazione batch GPU b=64 è circa 2.2×, b=256 circa 4.5×, b=1024 circa 7.1×. Il grafico mostra valori relativi del tempo per generazione; più grande è la dimensione del batch, più facile è ammortizzare i costi fissi. Fissare problema, dimensione della popolazione, numero di generazioni e seme casuale
- registrare tempo effettivo per generazione, tempo totale, throughput (valutazioni/secondo), speedup, utilizzo GPU e occupazione memoria video. Prima del timing fare warm-up, escludendo l'influenza della prima compilazione e dell'allocazione della memoria video
- i punti di timing devono fare sincronizzazione del dispositivo
- contare separatamente il tempo di calcolo e il tempo di trasferimento dati host-dispositivo. Se manca uno qualsiasi di questi passaggi, lo speedup può essere distorto. Il beneficio viene dal parallelismo batch, dagli operatori tensorizzati e dal parallelismo interno al dispositivo, facendo sì che una singola chiamata elabori l'intero insieme di candidati
- i vincoli includono dimensione del batch, dimensione del problema, grado di vettorizzabilità della funzione di valutazione, costi di copia host-dispositivo e costi di avvio dei kernel. Batch troppo piccoli vedono i benefici mangiati dai costi di avvio
- se la funzione di valutazione non è vettorizzabile, l'elaborazione batch non può quasi esprimersi. L'ordine corretto è verificare prima se la funzione di valutazione può essere batchizzata, poi confrontare implementazioni CPU e GPU. Il vantaggio di efficienza dovrebbe alla fine ricadere su "ottenere più generazioni o più soluzioni candidate a parità di budget di calcolo", e su questa base decidere modalità di deployment e progettazione sperimentale, non inseguire semplicemente il numero di speedup.

**Gestione degli esercizi**

La risposta corretta alla domanda 1 è "i costi di scheduling, interprete e accesso sparso alla memoria portati dalla chiamata indipendente della funzione di valutazione per ogni individuo". La baseline seriale produce N scheduling e aggiornamenti di stato indipendenti per generazione, controllo del ciclo, costi dell'interprete e accessi sparsi diluiscono la potenza di calcolo effettiva; a questo punto non ci sono ancora avvii di kernel GPU e copie.

La risposta corretta alla domanda 2 è organizzare popolazione, input di valutazione e stato di esecuzione in tensori, con una singola chiamata che copre l'intero insieme di candidati. Il nucleo dell'accelerazione è parallelismo batch e tensorizzazione, non cambiare precisione, dimensione della popolazione o numero di semi.

Il protocollo standard della domanda 3 è fissare problema, dimensione della popolazione, generazioni e seme, fare warm-up e sincronizzazione del dispositivo prima del timing, e distinguere tempo di calcolo e trasferimento dati.

La GPU esegue spesso in modo asincrono; senza sincronizzazione, il timing può perdere calcoli non ancora completati, portando a sottostima del tempo e speedup gonfiato; la sincronizzazione in sé non aumenta la potenza di calcolo, né elimina il trasferimento dati.

Quando la funzione di valutazione ha un basso grado di vettorizzabilità, il vantaggio dell'elaborazione batch GPU si riduce notevolmente, e può persino dare benefici limitati a causa di copie e avvii di kernel; l'accelerazione non è costante, né cresce senza limite con l'aumentare del batch.

Caso pratico:

1. Lo speedup di circa 9× ottenuto senza sincronizzazione del dispositivo è probabilmente inaffidabile. L'host dopo aver inviato il kernel continua l'esecuzione senza aspettarne il completamento; se i punti di timing non sono sincronizzati, il tempo misurato può coprire solo la fase di invio del kernel, perdendo il calcolo effettivo ancora in esecuzione, portando a grave sottostima del tempo GPU e speedup gonfiato. Correzione: chiamare la sincronizzazione del dispositivo a ogni punto di timing, assicurandosi che tutto il lavoro inviato sia realmente completato prima di leggere il timestamp; fare prima iterazioni di warm-up, e contare separatamente tempo di trasferimento dati host-dispositivo e tempo di calcolo puro. Solo il tempo per generazione e il tempo totale misurati con seme fisso, warm-up e sincronizzazione possono essere considerati affidabili.

2. Lo speedup di solo circa 1.2× con batch piccolo b=8 non è contraddittorio. Il beneficio dell'elaborazione batch è vincolato insieme da dimensione del batch, costi di avvio dei kernel e costi di trasferimento dati; con batch troppo piccolo, il lavoro parallelizzabile sul dispositivo è insufficiente, i costi fissi rappresentano una quota maggiore del tempo per generazione, il grado di parallelismo effettivo non può ammortizzare questi costi, e lo speedup si avvicina naturalmente a 1. Si consiglia di aumentare la dimensione del batch entro i limiti della memoria video, vettorizzare il più possibile la funzione di valutazione e la logica di post-elaborazione, e rimisurare secondo il protocollo standard, riportando separatamente tempo per generazione, tempo totale, throughput e speedup, per determinare se il beneficio ricade realmente sull'obiettivo di ottenere più generazioni o più candidati a parità di budget.

**Verifica della comprensione**

Chiedere a uno studente a caso di spiegare con parole proprie perché verificare prima che la funzione di valutazione sia vettorizzabile, e poi confrontare CPU e GPU; e di dire cosa risolvono rispettivamente warm-up e sincronizzazione del dispositivo.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere fonti di beneficio e condizioni al contorno, e sanno convertire l'accelerazione in beneficio di budget, passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-14"></a>

### Metodi Fondamentali del Calcolo Tensoriale Batch

*Pagina 14*

> **Obiettivo della pagina:** Lo studente dovrebbe consolidare i metodi fondamentali per esprimere il processo evolutivo come calcolo tensoriale batch.

> **Obiettivo della pagina**
>
> Consolidare i metodi fondamentali per esprimere il processo evolutivo come calcolo tensoriale batch, comprendere le relazioni tra dimensione batch, operatori batch, ottimizzazione del grafo computazionale e indicatori di throughput, e saper riconoscere la pseudo-batchizzazione.

> **Ordine di esposizione**
>
> Il tensore dei candidati X è [N × D], obiettivi e vincoli F sono [N × M], l'output della valutazione Y è [N × M]; la dimensione batch N è sempre all'esterno, D e M descrivono il numero di variabili e il numero di voci obiettivo di un singolo candidato.
>
> Mappare in modo unificato popolazione, obiettivi/vincoli, output di valutazione e stato evolutivo in tensori con dimensione batch, mantenendo le quantità di stato con scalari o piccoli buffer tensoriali, invece di registrarli individuo per individuo in oggetti Python.
>
> Mutazione X′ = X + σ·randn(X), crossover che si ricombina a coppie lungo la dimensione N, selezione idx = topk(F, k), valutazione Y = fθ(X). Il punto non è la singola espressione, ma che tutti i candidati condividono lo stesso grafo di operazioni tensoriali, una singola chiamata batch sostituisce N chiamate per singolo candidato; vincoli e superamenti possono essere gestiti con maschere tensoriali all'interno della stessa operazione batch.
>
> La fusione di operatori riduce gli avvii di kernel, il parallelismo intra-batch fa eseguire simultaneamente tutti i candidati, l'esecuzione asincrona sovrappone calcolo e trasferimento, il riuso della memoria riduce l'allocazione di tensori intermedi.
>
> Passare dalla latenza per singolo passo a candidati/secondo o generazioni/secondo, perché una singola chiamata batch trasporta l'intero batch di candidati, e solo il throughput complessivo riflette l'efficienza della ricerca.
>
> Incorporare operatori batch in un ciclo Python individuo per individuo reintroduce costi dell'interprete e costi di avvio dei kernel, la dimensione batch diventa vana. Metodo di autoverifica: in un passo evolutivo, il livello di scheduling dovrebbe avere solo "batch", non "individuo".

**Punti chiave della lezione**

- La dimensione batch N è il numero di candidati; quando le forme corrispondono, mutazione, crossover, selezione e valutazione possono eseguire direttamente in batch lungo la dimensione N. Il beneficio diretto della tensorizzazione viene dalla riduzione del numero di chiamate e dei costi di scheduling, non dal cambiare il numero di candidati o migliorare la precisione del singolo punto. randn(X) genera un tensore di perturbazione casuale della stessa forma di X, la perturbazione è elemento per elemento, σ ne controlla l'intensità. topk(F, k) seleziona lungo la dimensione batch N gli indici dei primi k candidati, l'oggetto della selezione è il candidato, non la variabile o la voce obiettivo. L'esecuzione batch cambia la posizione del collo di bottiglia prestazionale, la latenza è ancora misurabile, ma per misurare l'efficienza di scala bisogna guardare quanti candidati o quante generazioni si completano per unità di tempo.

**Copertura delle parole chiave**

- Calcolo tensoriale batch, dimensione batch N, contratto di forma, operatori batch, ottimizzazione del grafo computazionale, throughput, candidati/secondo, generazioni/secondo, pseudo-batchizzazione.

> **Spunti dai materiali**
>
> - Il diagramma di questa pagina ha come tema "processo evolutivo → grafo computazionale tensoriale batch", con tre colonne in sequenza: ① organizzazione tensorizzata, ② operatori batch, ③ ottimizzazione del compilatore e throughput. La lavagna o la mappa mentale può essere sviluppata su queste tre colonne, evidenziando nella terza colonna l'indicatore di throughput "candidati/secondo · generazioni/secondo".

> **Spunti per gli esercizi**
>
> - 5 domande a scelta multipla verificano rispettivamente contratto di forma, beneficio prestazionale della tensorizzazione, significato dell'espressione di mutazione, semantica della selezione topk, motivo del cambio di indicatore. Il feedback può sottolineare: in caso di risposta corretta, collegarsi al contratto di forma o al modo di chiamata per spiegare le motivazioni
> - in caso di errore, tornare alla spiegazione di questa pagina, trovare prove chiave prima di giudicare. Il caso di studio "migrare il ciclo evolutivo individuo per individuo all'esecuzione tensoriale batch" richiede di spiegare come organizzare candidati, obiettivi e stato in tensori e gestirli in batch lungo N, e i compromessi tra ottimizzazione del grafo computazionale e insufficienza di memoria video. I punti chiave della risposta includono X:[N×D], F:[N×M], Y=fθ(X), stato con scalari o piccoli buffer tensoriali
> - mutazione, crossover, selezione e valutazione eseguono tutti in batch lungo la dimensione N
> - l'ottimizzazione può fare fusione di operatori, parallelismo intra-batch, esecuzione asincrona, riuso della memoria
> - in caso di insufficienza di memoria video si può usare esecuzione a blocchi o a piccoli batch, ridurre la precisione numerica, accorciare il ciclo di vita dei tensori intermedi, ma tutti i candidati della stessa generazione dovrebbero mantenere criteri di confronto coerenti.

**Attività in classe**

Far spiegare agli studenti con parole proprie "perché la dimensione batch N dovrebbe essere all'esterno", e fare un semplice esempio, come N=4, D=3, M=2, scrivere le forme di X, F, Y, spiegando come una singola chiamata batch sostituisca molteplici chiamate per singolo candidato.

**Verifica della comprensione**

Chiedere agli studenti di riassumere il contratto di forma, indicare una scrittura pseudo-batch, spiegare perché l'indicatore passa dalla latenza per singolo passo al throughput. Se lo studente riesce solo a ripetere i termini senza spiegare i cambiamenti nel numero di chiamate e nel livello di scheduling, tornare alla parte su operatori batch e errori comuni per integrare la spiegazione.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno esprimere la relazione tra contratto di forma ed esecuzione batch, passare all'applicazione, riepilogo o discussione più complessa sull'ottimizzazione del grafo computazionale della pagina successiva.

<a id="lecture-page-15"></a>

### Scheduling Runtime e Componibilità degli Algoritmi

*Pagina 15*

> **Obiettivo della pagina:** Lo studente dovrebbe consolidare la comprensione centrale del Runtime nello scheduling di potenza di calcolo eterogenea e nella componibilità degli algoritmi.

> **Obiettivo della pagina**
>
> Stabilire la posizione di livello intermedio del Runtime — non è un algoritmo specifico, ma un livello di scheduling e astrazione che collega il sopra e il sotto: verso l'alto supporta la combinazione flessibile di algoritmi, problemi e workflow, verso il basso gestisce potenza di calcolo eterogenea come CPU e GPU, mantenendo così la componibilità degli algoritmi e l'indipendenza dall'hardware.

> **Ordine di esposizione**
>
> Fornire prima il giudizio di "livello intermedio"; poi scomporre oggetti di scheduling, risorse eterogenee e meccanismi di disaccoppiamento; quindi spiegare benefici e costi della componibilità; infine verificare la comprensione con esempi di sostituzione di algoritmi ed esercizi.

**Punti chiave della lezione**

- In base allo stato del workflow e del modulo di monitoraggio, schedula compiti come popolazione, valutazione, operatori sul dispositivo appropriato, gestendo in modo unificato esecuzione parallela e uso delle risorse. Riceve da algoritmo, problema, workflow, e chiama verso il basso CPU, GPU, acceleratori. Algoritmi, problemi e operatori si combinano tramite interfacce modulari, senza vincolarsi direttamente a hardware sottostante, strategie parallele o dettagli di compilazione. Quindi sostituire algoritmi come DE, PSO o cambiare problema di ottimizzazione non richiede di riscrivere il codice parallelo GPU/CPU sottostante. Differenze tra dispositivi, esecuzione tensorizzata e ottimizzazione del compilatore sono assorbite dal Runtime, il livello dell'algoritmo rimane indipendente dal dispositivo, facilitando sostituzione e riuso. L'astrazione porta costi di scheduling e trasferimento dati, richiedendo un bilanciamento tra flessibilità, prestazioni e complessità ingegneristica, ad esempio con elaborazione batch, esecuzione asincrona o cache per ridurre il trasferimento dati. Lo stesso Runtime può sostenere applicazioni multi-dominio, e fornisce un ambiente di esecuzione stabile per l'evoluzione dei metodi e la sostituzione degli algoritmi.

> **Spunti dai materiali**
>
> - Il diagramma di questa pagina può essere letto su tre livelli. In alto il livello dell'algoritmo, che include modulo degli algoritmi, definizione dei problemi, workflow, i tre accedono tramite interfaccia unificata
> - al centro il livello di scheduling Runtime, responsabile di scheduling dei compiti, esecuzione parallela, gestione delle risorse e isolamento delle interfacce
> - in basso la potenza di calcolo eterogenea, che include CPU, GPU, acceleratori. I suggerimenti ai lati sottolineano rispettivamente "algoritmo sostituibile, indipendente dall'hardware" e "compromesso: flessibilità·prestazioni·complessità", in basso il suggerimento "lo stesso Runtime supporta applicazioni multi-dominio". Nel commentare, si può spiegare lungo le frecce dall'alto verso il basso: il livello dell'algoritmo non tocca direttamente l'hardware, ma è il Runtime a schedulare l'esecuzione secondo il workflow.

**Copertura delle parole chiave**

- Scheduling di potenza di calcolo eterogenea, componibilità degli algoritmi, interfaccia unificata, scheduling del workflow, astrazione indipendente dall'hardware, isolamento delle interfacce, costi di scheduling, costi di trasferimento dati.

**Gestione degli esercizi**

Cinque domande a scelta multipla per una verifica rapida. La direzione corretta della domanda 1 è "fornire un livello di scheduling e astrazione, gestire potenza di calcolo eterogenea e mantenere la componibilità degli algoritmi"; se lo studente sceglie erroneamente "implementare direttamente algoritmi di ottimizzazione", sottolineare che il Runtime non implementa algoritmi specifici. La direzione corretta della domanda 2 è "combinarsi tramite interfacce modulari, senza vincolarsi all'hardware sottostante e alle strategie parallele"; se sceglie erroneamente API CUDA o codice parallelo scritto a mano, spiegare che questo rompe il disaccoppiamento. La direzione corretta della domanda 3 è "assorbire differenze tra dispositivi, esecuzione tensorizzata e ottimizzazione del compilatore, rendendo il livello dell'algoritmo indipendente dal dispositivo". La direzione corretta della domanda 4 è "l'astrazione porta costi di scheduling e trasferimento dati, richiedendo un bilanciamento tra flessibilità, prestazioni e complessità ingegneristica".

La direzione corretta della domanda 5 è "lo stesso Runtime può sostenere applicazioni multi-dominio, e fornisce un ambiente di esecuzione stabile per l'evoluzione dei metodi". Nel feedback, ricondurre uniformemente alle tre prove: livello intermedio e non implementazione di algoritmi, la componibilità richiede disaccoppiamento hardware, l'astrazione non è a costo zero.

Il Runtime come livello intermedio combina algoritmo, problema e workflow tramite interfaccia unificata, schedulando compiti come popolazione, valutazione, operatori su CPU o GPU; il livello dell'algoritmo non si vincola direttamente a hardware, strategie parallele o dettagli di compilazione, quindi il team che sostituisce DE, PSO o aggiusta la dimensione della popolazione non deve riscrivere il codice parallelo sottostante. La seconda domanda può essere risposta così: l'astrazione porta costi aggiuntivi di scheduling e trasferimento dati, che possono influire sulle prestazioni end-to-end; allo stesso tempo la manutenzione e il debug del Runtime stesso aumentano la complessità ingegneristica. Il team può ridurre il trasferimento dati tramite elaborazione batch, esecuzione asincrona o cache, raggiungendo un equilibrio tra flessibilità, prestazioni e complessità ingegneristica.

**Verifica della comprensione**

Chiedere agli studenti di spiegare in una frase perché il Runtime permette la sostituzione degli algoritmi senza toccare il codice hardware; poi indicare un oggetto di scheduling e una risorsa eterogenea ciascuno, per confermare di non confondere "popolazione, valutazione, operatori" con "CPU, GPU, acceleratori".

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno distinguere oggetti di scheduling e risorse eterogenee, e sanno esprimere benefici e costi della componibilità, passare agli esempi, applicazioni o riepilogo della pagina successiva.

<a id="lecture-page-16"></a>

### La Pietra Angolare dell'Esplorazione Evolutiva Parallela ad Alta Intensità

*Pagina 16*

> **Obiettivo della pagina:** Lo studente dovrebbe riassumere in modo completo il valore complessivo e il significato pratico dell'infrastruttura di calcolo EvoX e dell'evoluzione parallela tensorizzata.

> **Obiettivo della pagina**
>
> Riassumere in modo completo il valore complessivo e il significato pratico dell'infrastruttura di calcolo EvoX e dell'evoluzione parallela tensorizzata. Lo studente dovrebbe saper spiegare la transizione dalla lista di candidati al grafo computazionale tensorizzato, padroneggiare i tre tipi di oggetti tensorizzati — popolazione, valutazione e stato — e comprendere come il Runtime unificato e l'architettura disaccoppiata supportino l'esplorazione evolutiva parallela ad alta intensità.

> **Ordine di esposizione**
>
> Indicare prima il collo di bottiglia del flusso seriale tradizionale, poi introdurre il grafo computazionale tensorizzato come pietra angolare, quindi sviluppare i tre grandi oggetti tensorizzati, poi parlare della grafo-computazionalizzazione e dell'architettura unificata, e infine arrivare a benefici, significato pratico e caso del profilo alare supercritico.

**Punti chiave della lezione**

- 1. Gli esperimenti evolutivi tradizionali trattano ogni individuo come oggetto Python indipendente, modellando e valutando uno per uno. Quando la scala dei candidati si espande a migliaia o decine di migliaia, il vero collo di bottiglia spesso non è più l'algoritmo stesso, ma i costi di scheduling, sincronizzazione e I/O per candidato. La pietra angolare di EvoX può essere riassunta come: dalla lista di candidati al grafo computazionale tensorizzato. Riorganizza popolazione, valutazione e stato di runtime in tensori calcolabili nel loro insieme, poi lo scheduler Runtime unificato li distribuisce su GPU e potenza di calcolo eterogenea per l'esecuzione batch, sostenendo così la ricerca evolutiva su larga scala, multi-obiettivo e multi-soluzione parallela. 2. I tre grandi oggetti tensorizzati: parametri individuali, geni o strategie non sono più ciclati individuo per individuo su oggetti Python, ma organizzati in tensori lungo la dimensione batch, le differenze tra individui sono portate da una dimensione del tensore. Fitness, vincoli, indicatori multi-obiettivo e risultati di valutazione di simulazioni o modelli possono essere calcolati in batch, i candidati dello stesso batch condividono una singola chiamata al dispositivo, riducendo significativamente i costi di scheduling e I/O per candidato. Generazione evolutiva, seme casuale, cache e indicatori di monitoraggio e altri stati di runtime sono gestiti in modo unificato, rendendo gli esperimenti dopo l'accelerazione parallela ancora riproducibili e tracciabili. La tensorizzazione non è un'ottimizzazione locale in un punto, ma attraversa i tre livelli del ciclo evolutivo. Se un qualsiasi livello torna al ciclo per oggetto, il parallelismo viene bloccato a quel livello. Dopo aver trasformato la lista di candidati in un grafo computazionale tensorizzato, parallelismo degli operatori e ottimizzazione del compilatore hanno spazio per esprimersi, dimensione della popolazione e grado di parallelismo delle valutazioni possono espandersi con la potenza di calcolo, invece di essere bloccati dal ciclo dell'interprete. A questo si accompagna l'architettura unificata — algoritmo, problema, workflow e monitoraggio, scheduler Runtime reciprocamente disaccoppiati, rendendo l'algoritmo componibile, il problema plug-and-play, la potenza di calcolo eterogenea gestita in modo unificato. Chi scrive l'algoritmo non deve preoccuparsi contemporaneamente dello scheduling sottostante. Sostituisce il ciclo CPU seriale tradizionale, realizzando un'accelerazione su larga scala su GPU e potenza di calcolo eterogenea, fornendo una base di throughput stabile per l'esplorazione ad alta intensità
- a parità di tempo di wall-clock, si possono esplorare più candidati, più combinazioni di obiettivi o più ripetizioni casuali. Quando il lavoro di ciclo e scheduling di basso livello è assorbito dall'infrastruttura, i ricercatori possono spostare le energie su modellazione del problema, compromessi tra obiettivi e progettazione di ipotesi sperimentali, senza dover prima sprofondare nell'ingegneria di ciclo e scheduling di basso livello. Questa divisione del lavoro è sia il prerequisito dell'esplorazione evolutiva parallela ad alta intensità, sia la base ingegneristica per l'evoluzione dei metodi successivi e la ricerca scientifica AI Native. Nell'ottimizzazione multi-obiettivo di profili alari supercritici, il rapporto portanza/resistenza in crociera e il coefficiente di portanza critico di buffeting sono in conflitto tra loro, richiedendo di conservare un insieme di soluzioni candidate differenziate per il compromesso degli esperti. Una singola simulazione ad alta precisione è costosa, la scala dei candidati raggiunge migliaia, un esperimento con il primo ciclo CPU seriale richiedeva giorni, e semi casuali e risultati intermedi sparsi erano difficili da verificare. Idea di ristrutturazione: prima tensorizzare la popolazione, organizzando i parametri dei profili alari candidati in tensori lungo la dimensione batch
- poi tensorizzare la valutazione, valutando in batch obiettivi e vincoli come rapporto portanza/resistenza, coefficiente di portanza di buffeting, eventualmente con modelli surrogati che predicono in batch prima, e chiamando la simulazione ad alta precisione solo su pochi candidati
- contemporaneamente tensorizzare lo stato, registrando in modo unificato generazione, seme casuale, cache e indicatori di monitoraggio
- infine grafo-computazionalizzare e far schedulare dallo scheduler Runtime unificato su GPU e potenza di calcolo eterogenea per l'esecuzione batch. I passaggi in cui il throughput migliora includono parallelismo della valutazione batch, parallelismo degli operatori e ottimizzazione del compilatore, eliminazione dei costi di scheduling e sincronizzazione Python per candidato, e l'esplorazione simultanea di più candidati, più combinazioni di obiettivi e più ripetizioni casuali nello stesso tempo di wall-clock. Riguardo alla verificabilità: non conviene produrre presto una soluzione ottimale unica, perché gli obiettivi sono in conflitto tra loro, la convergenza precoce su un singolo punto perde informazioni di compromesso
- conservare candidati differenziati permette agli esperti di scegliere in base a benefici, costi e condizioni di applicabilità. Riguardo alla verificabilità: generazione, seme casuale, cache e indicatori di monitoraggio dovrebbero essere registrati in modo unificato come stato di runtime e gestiti con il grafo computazionale, permettendo la riproduzione completa e la tracciabilità dei risultati dell'esecuzione parallela batch; anche i record di valutazione dei batch di candidati dovrebbero essere riconducibili a parametri e configurazioni di valutazione specifici.

**Gestione degli esercizi**

Questa pagina è corredata da cinque domande a scelta multipla e un caso di studio, utili per verificare comprensione concettuale e applicazione trasversale.

La pietra angolare è il passaggio dalla lista di candidati al grafo computazionale tensorizzato, con esecuzione batch schedulata dal Runtime unificato. Suggerimento: il collo di bottiglia è nel ciclo Python per candidato, nello scheduling e nell'I/O, non nell'algoritmo stesso, né nel comprimere la popolazione o aumentare la frequenza single-core.

La tensorizzazione della popolazione consiste nell'organizzare tensori lungo la dimensione batch, con le differenze tra individui portate da una dimensione del tensore. Suggerimento: il ciclo per oggetto è proprio ciò da cui ci si vuole liberare; la tensorizzazione è indipendente dal numero di obiettivi, né va a scapito della riproducibilità.

Il beneficio principale della tensorizzazione della valutazione è il calcolo in batch di fitness, vincoli e indicatori multi-obiettivo, riducendo i costi di scheduling e I/O per candidato. Suggerimento: non aumenta la precisione numerica di una singola valutazione, non può sostituire il modello di simulazione, né significa rinunciare alla registrazione.

La gestione unificata dello stato di runtime serve a rafforzare la riproducibilità e la tracciabilità dell'esperimento. Suggerimento: la tensorizzazione dello stato gestisce insieme generazione, seme, cache e indicatori di monitoraggio, è indipendente dalla riduzione della memoria video, né elimina il seme casuale o limita il parallelismo.

Il significato del disaccoppiamento è che gli algoritmi sono componibili, i problemi plug-and-play, la potenza di calcolo eterogenea gestita in modo unificato. Suggerimento: il disaccoppiamento libera riuso e capacità parallela, non limita gli algoritmi a implementazioni seriali, né elimina la necessità di ipotesi sperimentali e compromessi tra obiettivi.

Spiegare prima la ristrutturazione in quattro passi — popolazione, valutazione, stato, grafo computazionale e Runtime — poi indicare i passaggi in cui il throughput migliora; la seconda domanda deve spiegare perché conservare candidati diversificati, e come garantire la riproducibilità tramite tensorizzazione dello stato e registrazione unificata.

Se lo studente risponde correttamente, lodarlo per essersi collegato ai concetti di questa pagina e averne spiegato le motivazioni; se sbaglia, guidarlo a tornare alla spiegazione di questa pagina, trovando prove chiave o esempi prima di giudicare.

**Attività in classe**

Si può chiedere agli studenti di trovare uno scenario familiare di calcolo evolutivo o valutazione batch, determinare se esiste un ciclo Python esplicito; se esiste, discutere se tensorizzare prioritariamente a livello di popolazione, valutazione o stato, e spiegarne le motivazioni.

**Verifica della comprensione**

Chiedere a uno studente a caso di riassumere con parole proprie i punti chiave di questa pagina, e il docente integra in base alla risposta le parole chiave: i tre tipi di tensorizzazione, il Runtime unificato, superamento del collo di bottiglia seriale, riproducibilità e architettura disaccoppiata. Si può chiedere: perché la riproducibilità non è una voce aggiuntiva? Se seme casuale, generazione, cache e indicatori di monitoraggio non sono registrati in modo unificato con il grafo computazionale, i benefici dell'accelerazione vengono compensati dalla mancanza di tracciabilità.

> **Suggerimento di transizione**
>
> Dopo aver confermato che gli studenti sanno esprimere la relazione centrale dalla lista di candidati al grafo computazionale tensorizzato, e sanno distinguere i tre tipi di oggetti tensorizzati — popolazione, valutazione e stato — passare agli esempi, applicazioni o riepilogo della pagina successiva.

--- FINE TESTO SORGENTE ---

Lingua di origine: Cinese (Semplificato) 中文 (简体)
Lingua di destinazione: Italiano Italiano
Si prega di tradurre il testo sopra in Italiano Italiano preservando la struttura e la formattazione originali.
Restituire direttamente il testo tradotto senza involucri o spiegazioni aggiuntive.