SlideShare a Scribd company logo
Introduzione alla playstation 3
Vincenzo De Maio
matricola 0510200251
Sommario
● PS3: Cluster o console?
● Architettura CELL
● Programmazione usando il CELL
PS3: Cluster o console?
● Specifiche:
– CPU: Processore CELL
– GPU: RSX
– Memoria: 256Mb XDR Ram principale, 256Mb
GDDR3 VRAM
– Hard disk: SATA 2.5'' (dimensioni variabili a
seconda del modello)
– Svariate altre periferiche, a seconda del modello
PS3: Cluster o console?
● Dal sito della IBM: ”Cell combines a general-purpose Power
Architecture core of modest performance with streamlined
coprocessing elements which greatly accelerate multimedia and
vector processing applications, as well as many other forms of
dedicated computation.”
● “ Though sold as a game console, what will in fact enter the
home is a Cell-based computer. ” - Ken Kutaragi, padre della
console playstation
PS3: Cluster o console?
RISPOSTA: CLUSTER E CONSOLE!
● Accontenta i videogiocatori, fornendo loro
una notevole esperienza videoludica...
● Fornisce un cluster di tutto rispetto per
un prezzo relativamente economico
Alcune informazioni
● Cell: abbreviazione di Cell Broadband
Engine Architecture (talvolta si trova anche la
sigla CBEA)
● Progettato in cooperazione da IBM, Sony e
Toshiba espressamente per la PS3
Sommario
● PS3: Cluster o console?
● Architettura CELL
● Programmazione usando il CELL
Architettura CELL
Architettura CELL
● 1 Power Processor Element (PPE)
● 8 Synergistic Processor Element (SPE)
● Accesso alla memoria
PPE: Power Processor Element
● ”A core to rule them all...”
● Architettura PowerPC a 64 bit 4GHZ (3.2 per la PS3)
● Cache L1: 32KB per le istruzioni, 32KB per i dati
● Cache L2: 512 KB
● Si occupa di mappare i tasks alle SPE
● Su di essa viene eseguito il sistema operativo...
● ... il maggior carico computazionale viene sopportato
dalle SPE
● Dual-threaded
● in-order
PPE: Power Processor Element
● Perchè in-order?
– Per poter fornire le capacità di esecuzione out-
of-order, c'è bisogno ovviamente di una
maggiore complessità architetturale
– Lo scheduling delle istruzioni è totale
responsabilità del compilatore...
Architettura CELL
● 1 Power Processor Element (PPE)
● 8 Synergistic Processor Element (SPE)
● Accesso alla memoria
SPE: Synergistic Processor
Element
SPE:Synergistic Processor
Element
● Le SPE rappresentano il ”braccio armato”
della PPE...
● Architettura SIMD
● Si prendono sulle loro spalle il maggior
carico computazionale
● 128 registri a 128 bit
● 4 floating point unit capaci di 32GFLOPS e 4
integer unit capaci di 32 GOPS
● Local store di 256KB... Manca qualcosa?
SPE:Synergistic Processor
Element
● Eh? manca la cache!
● Motivazioni di questa scelta:
– Aggiunge complicazioni, dovute alla natura
stessa della cache
– Possiamo usare il Local Store...
SPE:Synergistic Processor
Element
● LOCAL STORE
– Tramite questo la SPE accede alla memoria
(non può farlo direttamente)
– Possiamo spostare 16byte(128 bit) per ciclo da e
verso la local store... esattamente il carico di
ogni registro!
– A differenza della cache, la local store può
sostenere questo carico per oltre 10000 cicli
SPE:Synergistic Processor
Element
● Un possibile problema: contesa
– Dobbiamo contemporaneamente caricare dati
dalla memoria, scrivere dati in memoria e
scrivere/caricare dati nei/dai registri...
● Soluzione:
– La local store accede alla memoria in blocchi di
almeno 1024bit per ciclo (circa 0.5 tera al
secondo!)
SPE:Synergistic Processor
Element
● Local Store vs CACHE
– Un tipico esempio: audio processing
● Se riesco a caricare all'interno del Local Store l'intero
blocco di audio su cui devo lavorare, annullo gli
accessi alla memoria durante l'esecuzione del
programma...
● Impossibile (o comunque estremamente difficile) farlo
con la cache
SPE: Synergistic Processor
Element
● Ulteriori vantaggi delle SPE
– Possono essere usate efficacemente per stream
programming... (GPU)
Pensandoci su...
● Perchè tutto questo funzioni, c'è bisogno che
le SPU siano sempre riempite di dati...
● Necessità di un sistema di accesso alla
memoria e alle periferiche di I/O altamente
performante...
Architettura CELL
● 1 Power Processor Element (PPE)
● 8 Synergistic Processor Element (SPE)
● Accesso alla memoria
– EIB e MMU
– Memorie e dispositivi di I/O
Element Interconnect Bus
● Unisce tutte le componenti sul chip
● Composto di 4 anelli da 16byte ciascuno e
permettono di effettuare fino a 3 trasferimenti
simultanei.
● Cosa fa?
– Si occupa di spostare dati dalla memoria
principale alle SPE e viceversa
– Smista le istruzioni della PPE alle varie SPE
Element Interconnect Bus
● Prestazioni:
– 96 bytes per ciclo di clock, anche se secondo
l'IBM ne sarebbero disponibili solo 64 nella
pratica
● E la protezione della memoria?
– Gestita dalle MMU contenute nelle SPE
Memory Management Unit
● Utilizzate dalle SPE per l'accesso alla
memoria o per accedere agli altri Local Store
● Forniscono i meccanismi di coerenza e
protezione della memoria
Importanza di EIB e MMU
● Entrambi devono essere performanti...
● Ma sufficientemente complessi da riuscire a
gestire un enorme flusso di dati da distribuire
in diverse destinazioni e una coda di almeno
128 richieste di memoria
Architettura CELL
● 1 Power Processor Element (PPE)
● 8 Synergistic Processor Element (SPE)
● Accesso alla memoria
– EIB e MMU
– Memorie e dispositivi di I/O
Memorie e dispositivi di I/O
● Dati tecnici:
– XDR Rambus 256MB
– Controller FlexIO
– Ampiezza di banda della memoria: 25.6 GB/sec
– Ampiezza di banda dei dispositivi di I/O: 76.8
GB/sec
Intervallo
● Dolorosi incidenti di percorso... (vedi
anche: ”la zappa sui piedi”)
– come ho distrutto la playstation (1)
– come ho distrutto la playstation (2)
Come ho distrutto la playstation
(1)
● Configurazione del sistema: Yellow Dog Linux 5.0
● Necessario installare il cellsdk, ma a ogni tentativo
ricevo un errore ”can't update glibc because of
unresolved dependencies”
● IDEA: rimuovo le dipendenze, tanto ”se tolgo
qualcosa di importante il sistema mi avviserà...”
DON
Come ho distrutto la playstation
(1)
● A fianco vedete il
risultato...
● Soluzione:
formattazione e
installazione di
Fedora 5
Come ho distrutto la playstation
(2)
● Installata fedora 5, ma il cellsdk3.0 richiede fedora
7!
● Piano piano, aggiorno glibc dalla versione della 5
alla versione della 7...
● installo il cellsdk...
● applico varie patch al kernel...
● compilo ed eseguo con successo vari programmi...
● il tutto senza MAI riavviare la playstation 3!
DON
Come ho distrutto la playstation
(2)
● La mia espressione
al successivo riavvio
della playstation
● Soluzione: installata
fedora 7 e il cellsdk
seguendo le
”procedure
standard”
Sommario
● PS3: Cluster o console?
● Architettura CELL
● Programmazione usando il CELL
Una citazione doverosa...
“To put it quite bluntly: as long as there were no
machines, programming was no problem at all;
when we had a few weak computers,
programming became a mild problem, and now
we have gigantic computers, programming has
become an equally gigantic problem."
-- E. Dijkstra, 1972 Turing Award Lecture
Sarà vero??
Programmare con il Cell
● Ingredienti:
– Conoscerne l'architettura
– Tanta pazienza
– Linux (Fedora 7.0 o Red Hat Enterprise 5.0)
– IBM CellSDK 3.0
CellSDK
● Scaricabile dal sito della IBM (www.ibm.com)
● Fornisce un ambiente di sviluppo per la
programmazione con il Cell, compatibile con
qualsiasi architettura (purchè abbia FC 7 o
RHE 5 installato)
CellSDK
● STRUMENTI DI SVILUPPO
– libspe.h, libspe2.h
– ppu-gcc
– spu-gcc
– ppu-embedspu
● STRUMENTI DI DEBUGGING
– ppu-gdb
– spu-gdb
● ALTRO
– systemsim-cell
Altri tools utili non inclusi
nell'sdk
● Eclipse + plugin per il cellsdk (richiede la
JVM della IBM)
● Anjuta o Kdevelop
Hello, Cell!
● Obiettivo: scrivere il classico ”Hello, world”
utilizzando tutti le SPE del cell.
1) Isolare il task che ogni SPE dovrà eseguire (in
questo caso stampare la stringa ”Hello, world da
spe_id” (dove spe_id è l'id della SPE in
esadecimale)
2) Fare in modo che il PPE mappi il task giusto ad
ogni SPE
Hello, Cell!
● Il primo passo è abbastanza banale...
#include <stdio.h>
int main(unsigned long long spe_id, unsigned long long argp,
unsigned long long envp){
printf(”Hello, world! da 0x%xn”,(unsigned int) spe_id);
return 0;
}
#include <stdio.h>
int main(unsigned long long spe_id, unsigned long long argp,
unsigned long long envp){
printf(”Hello, world! da 0x%xn”,(unsigned int) spe_id);
return 0;
}
Hello, Cell!
● Passo 2: iniziano i guai...
– come indichiamo alla PPE il programma da
includere?
– come effettuiamo il mapping ai vari SPE?
Hello, Cell!
● I programmi che vanno eseguiti dalle SPE
sono scritti per lavorare insieme alla PPE,
ma hanno vengono compilati
indipendentemente
● 1 compilatore per i programmi della PPE e 1
per i programmi della SPE, rispettivamente
ppu-gcc e spu-gcc
Hello, Cell!
● spu-gcc produce delle immagini ELF
(Extensible Linking Format) che possono
essere incluse nei programmi della PPE
● Ogni immagine ha la propria sezione di dati
e di codice
● Le funzioni di Input/Output vengono eseguite
richiedendo il servizio alla PPE
Hello, Cell!
extern spe_program_handle
spe_program;
extern spe_program_handle
spe_program;
Ecco come dichiareremo il programma ”esterno” da
inserire nelle SPE all'interno della PPE
Ora... bisogna dire alle SPE di caricare questo
programma!
Hello, Cell!
● Soluzione: potremmo dire a ogni PPE di
eseguire un thread corrispondente al
programma sopra descritto
● In libspe.h, esistono funzioni apposite...
– spe_create_thread() - crea un thread che
esegue al suo interno il programma
– spe_wait() - aspetta la terminazione di un thread
Hello, Cell!
#include <stdio.h>
#include <libspe2.h>
#define NUM_THREAD 6
extern spe_program_handle spe_program;
int main(void){
spe_id_t[NUM_THREAD] spe_id;
int i;
//creiamo i thread...
for(i=0;i<NUM_THREAD;i++){
id[i] = spe_create_thread(0,&spe_program,NULL,NULL,-1,0);
}
//attendiamo la loro terminazione
for(i=0;i<NUM_THREAD;i++){
spe_wait(id[i],NULL,0);
}
}
#include <stdio.h>
#include <libspe2.h>
#define NUM_THREAD 6
extern spe_program_handle spe_program;
int main(void){
spe_id_t[NUM_THREAD] spe_id;
int i;
//creiamo i thread...
for(i=0;i<NUM_THREAD;i++){
id[i] = spe_create_thread(0,&spe_program,NULL,NULL,-1,0);
}
//attendiamo la loro terminazione
for(i=0;i<NUM_THREAD;i++){
spe_wait(id[i],NULL,0);
}
}
Hello, Cell!
● spe_create_thread(thread_group,
program_handle,argp,envp)
● spe_wait()
● TUTTO QUI?
Hello, Cell!
NO!
LIBSPE DEPRECATA!
Bisogna usare libspe2 in combinazione con la ben nota
pthread.h
Hello, Cell!
● Riscriviamo il programma usando la
libspe2...
● A livello concettuale, vale tutto quello che
abbiamo detto finora...
● semplicemente, siamo costretti a usare la
pthread per la gestione dei threads
Hello, Cell!
● Creazione/distruzione dei thread
– pthread_create(id,thread_attr,thread_func,func_arg);
– pthread_join(id,value);
● Più alcuni amici da libspe2...
– spe_context_create(flags,gang_context)
– spe_program_load(spe_context_ptr,program_handle
)
– spe_context_run(spe_context_ptr,entry_point,runflag
s,argp,envp,stopinfo)
– spe_context_destroy(spe_context_ptr)
Amici da libspe2
● spe_context_create(flags,gang_context)
– flags:
● SPE_EVENTS_ENABLE: abilita la gestione degli
eventi
●
– gang_context:
● equivalente al thread group, viene creato usando
spe_gang_context_create
Crea il context in cui viene eseguito il programma esterno
Amici da libspe2
● spe_program_load(spe_context_ptr,progr
am_handle)
– spe_context_ptr: puntatore al context spe
– program_handle: puntatore al programma da
eseguire all'interno del context specificato
Carica il programma all'interno del context specificato
Amici da libspe2
● spe_context_run(spe_context_ptr,entry_p
oint,runflags,argp,envp,stopinfo)
– spe_context_ptr: puntatore allo spe_context da
eseguire
– entry_point: parametro inout
● in: il valore dell'instruction pointer da cui il programma
inizierà la sua esecuzione
● out: il valore dell'instruction pointer al momento della
terminazione del programma
Amici da libspe2
● spe_context_run(spe_context_ptr,entry_p
oint,runflags,argp,envp,stopinfo)
– runflags: or bitwise di più costanti
● 0: comportamento di default
● SPE_NO_CALLBACKS: vieta l'esecuzione
automatica di callbacks
● SPE_RUN_USER_REGS: inizializza i 3 registri della
SPU con i 48bytes puntati da argp
– argp: (OPZIONALE) puntatore a dati del
programma passati come secondo argomento
Amici da libspe2
● spe_context_run(spe_context_ptr,entry_p
oint,runflags,argp,envp,stopinfo)
– envp: (OPZIONALE) puntatore a dati specifici
dell'ambiente di esecuzione, passati come terzo
parametro al programma
– stopinfo: (OPZIONALE) puntatore a una struttura
spe_stop_info_t in cui scriveremo i dati relativi
alla terminazione del programma
Amici da libspe2
● spe_context_destroy(spe_context_ptr)
– libera le risorse associate a uno spe_context
Allora, programmiamo?
typedef struct{
spe_context_ptr_t spe_id;
unsigned long *args;
} thread_arg_t; //wrapping degli argomenti della funzione
void *run_program(void* thread_arg){
unsigned int entry;
entry = SPE_DEFAULT_ENTRY;
spe_stop_info_t stop_info;
ret = spe_context_run(arg->spe,&entry,0,NULL,NULL,&stop_info);
if(ret<0){
perror("Errore di context_run");
return NULL;
}
printf("status %dn",spe_stop_info_read(arg->spe,&stop_info));
return NULL;
}
typedef struct{
spe_context_ptr_t spe_id;
unsigned long *args;
} thread_arg_t; //wrapping degli argomenti della funzione
void *run_program(void* thread_arg){
unsigned int entry;
entry = SPE_DEFAULT_ENTRY;
spe_stop_info_t stop_info;
ret = spe_context_run(arg->spe,&entry,0,NULL,NULL,&stop_info);
if(ret<0){
perror("Errore di context_run");
return NULL;
}
printf("status %dn",spe_stop_info_read(arg->spe,&stop_info));
return NULL;
}
Allora, programmiamo?
int main(int argc,char **argv){
int i,ret_value;
spe_context_ptr_t spe[NUM_THREADS];
pthread_t thread[NUM_THREADS];
thread_arg_t arg[NUM_THREADS];
for(i=0;i<NUM_THREADS;i++){
spe[i] = spe_context_create(SPE_EVENTS_ENABLE,NULL);
if(!spe[i]){
perror("spe_context_create error n");
exit(1);
}
ret = spe_program_load(spe[i],&hello_spu);
if(ret){
perror("errore di spe_program_loadn");
exit(1);
}//... CONTINUA
int main(int argc,char **argv){
int i,ret_value;
spe_context_ptr_t spe[NUM_THREADS];
pthread_t thread[NUM_THREADS];
thread_arg_t arg[NUM_THREADS];
for(i=0;i<NUM_THREADS;i++){
spe[i] = spe_context_create(SPE_EVENTS_ENABLE,NULL);
if(!spe[i]){
perror("spe_context_create error n");
exit(1);
}
ret = spe_program_load(spe[i],&hello_spu);
if(ret){
perror("errore di spe_program_loadn");
exit(1);
}//... CONTINUA
Allora, programmiamo?
arg[i].spe = spe[i];
arg[i].args = NULL;
ret = pthread_create(&thread[i],NULL,run_spu_program,&arg[i]);
if(ret){
perror("errore di pthread_createn");
exit(1);
}
}
for(i=0;i<NUM_THREADS;i++){
pthread_join(thread[i],NULL);
ret = spe_context_destroy(spe[i]);
if(ret){
perror("errore di spe_context_destroy!n");
exit(1);
}
}
return 0;
}
arg[i].spe = spe[i];
arg[i].args = NULL;
ret = pthread_create(&thread[i],NULL,run_spu_program,&arg[i]);
if(ret){
perror("errore di pthread_createn");
exit(1);
}
}
for(i=0;i<NUM_THREADS;i++){
pthread_join(thread[i],NULL);
ret = spe_context_destroy(spe[i]);
if(ret){
perror("errore di spe_context_destroy!n");
exit(1);
}
}
return 0;
}
Compilazione
● The ”old way”
– spu-gcc -o hello_spu hello_spu.c -g
– ppu-embedspu hello_spu hello_spu hello_spu-
embed.o
– ar –qcs hello_spu.a hello_spu-embed.o
– ppu-gcc -o hello hello_ppu.c -lspe2 hello_spu.a
– ./hello
● Makefile
– compreso nel cellsdk
Funzioni di accesso alla
memoria
● int spe_mfcio_put (spe_context_ptr_t spe,
unsigned int lsa, void *ea, unsigned int size,
unsigned int tag, unsigned int tid, unsigned
int rid)
● int spe_mfcio_get (spe_context_ptr_t spe,
unsigned int lsa, void *ea, unsigned int size,
unsigned int tag, unsigned int tid, unsigned
int rid)
Comunicazione tra 2 SPE
● int spe_out_mbox_read (spe_context_ptr_t
spe, unsigned int *mbox_data, int count)
● int spe_in_mbox_write (spe_context_ptr_t
spe, unsigned int *mbox_data, int count,
unsigned int behavior)
To be continued...
GRAZIE PER LA CORTESE ATTENZIONE

More Related Content

PDF
Forza4 PIC microcontroller
PDF
Sistemi Operativi: Meccanismi - Lezione 03
PDF
Sistemi Operativi: Struttura - Lezione 04
PDF
Trace32 lo-strumento-piu-completo-per-il-debug-di-un-sistema-linux
PDF
Sistemi Operativi: Struttura avanzata - Lezione 05
PDF
Amministrazione base dei sistemi Linux
PDF
Sistemi Operativi: CPU Scheduler - Lezione 09
PDF
Grix.it wood board usb
Forza4 PIC microcontroller
Sistemi Operativi: Meccanismi - Lezione 03
Sistemi Operativi: Struttura - Lezione 04
Trace32 lo-strumento-piu-completo-per-il-debug-di-un-sistema-linux
Sistemi Operativi: Struttura avanzata - Lezione 05
Amministrazione base dei sistemi Linux
Sistemi Operativi: CPU Scheduler - Lezione 09
Grix.it wood board usb

What's hot (18)

PDF
BeRTOS: Sistema Real Time Embedded Free
PDF
Introduzione Alla Uml Mconsole
PDF
Sistemi Operativi: Introduzione - Lezione 01
PDF
Virtualizzazione
PDF
Sistemi Operativi: Componenti - Lezione 02
PDF
Oracle Application Server 10g
PPT
Elementidi informatica
PDF
Introduzione User Mode Linux
PDF
Intro BeagleBone Black - Massimiliano D'Ambrosio
PPTX
L' architettura dell' elaboratore( parte 1) (parte 2) periferiche
PDF
Arkanoid on Altera DE-1
PDF
Primi passi con la scheda BeagleBone Black
PPTX
Scheda Madre
PPTX
Architettura degli Elaboratori
PPTX
Delphi Day 2009 Win7 Dev Overview
PPTX
OpenCL - Introduzione al framework OpenCL
PPT
Guida al Computer - Lezione 51 - Il Sistema Operativo Parte 1
BeRTOS: Sistema Real Time Embedded Free
Introduzione Alla Uml Mconsole
Sistemi Operativi: Introduzione - Lezione 01
Virtualizzazione
Sistemi Operativi: Componenti - Lezione 02
Oracle Application Server 10g
Elementidi informatica
Introduzione User Mode Linux
Intro BeagleBone Black - Massimiliano D'Ambrosio
L' architettura dell' elaboratore( parte 1) (parte 2) periferiche
Arkanoid on Altera DE-1
Primi passi con la scheda BeagleBone Black
Scheda Madre
Architettura degli Elaboratori
Delphi Day 2009 Win7 Dev Overview
OpenCL - Introduzione al framework OpenCL
Guida al Computer - Lezione 51 - Il Sistema Operativo Parte 1
Ad

Viewers also liked (7)

PDF
Variabili casuali - Lezione 5
PDF
Energy aware networking
PDF
Scheduling power-aware abstract
PPTX
Green scheduling
PDF
Cell Programming 2
PDF
Linguaggio R, principi e concetti
PDF
R e la statistica
Variabili casuali - Lezione 5
Energy aware networking
Scheduling power-aware abstract
Green scheduling
Cell Programming 2
Linguaggio R, principi e concetti
R e la statistica
Ad

Similar to Cell Programming 1 (20)

PDF
Assemblare un pc
PDF
Modelli arduino
PDF
Microcontrollori
PDF
Raspberry pi per tutti (workshop presso Warehouse Coworking Pesaro)
ODP
Linux Capabilities - ita - v2.1.5 - compatta
PDF
Angelo Impedovo, Linux Day 2016, Programmazione Parallela in openCL
PDF
DHow2 - L5
PPT
Cpu Abacus
PPT
Cpu abacus
PPT
PDF
Arduino 2- Slide descrizione Architettura
PDF
Introduzione ad Arduino del Maker DevLab
PDF
Linux Day 2016 Milano - Open Source Hardware PowerPC Notebook
PDF
SLIDES PRESENTAZION LEZIONE 1 ARDUINO.pdf
PDF
Software libero nei sistemi embedded
PDF
Come Abilitare La Connettività Usb Con La Famiglia Di Js16 8 A 8 Bit Della Fr...
PDF
Arduino galileo edison_udoo
KEY
Introduzione ad Arduino
PPTX
Arduino ICT2016 [IT]
Assemblare un pc
Modelli arduino
Microcontrollori
Raspberry pi per tutti (workshop presso Warehouse Coworking Pesaro)
Linux Capabilities - ita - v2.1.5 - compatta
Angelo Impedovo, Linux Day 2016, Programmazione Parallela in openCL
DHow2 - L5
Cpu Abacus
Cpu abacus
Arduino 2- Slide descrizione Architettura
Introduzione ad Arduino del Maker DevLab
Linux Day 2016 Milano - Open Source Hardware PowerPC Notebook
SLIDES PRESENTAZION LEZIONE 1 ARDUINO.pdf
Software libero nei sistemi embedded
Come Abilitare La Connettività Usb Con La Famiglia Di Js16 8 A 8 Bit Della Fr...
Arduino galileo edison_udoo
Introduzione ad Arduino
Arduino ICT2016 [IT]

Cell Programming 1

  • 1. Introduzione alla playstation 3 Vincenzo De Maio matricola 0510200251
  • 2. Sommario ● PS3: Cluster o console? ● Architettura CELL ● Programmazione usando il CELL
  • 3. PS3: Cluster o console? ● Specifiche: – CPU: Processore CELL – GPU: RSX – Memoria: 256Mb XDR Ram principale, 256Mb GDDR3 VRAM – Hard disk: SATA 2.5'' (dimensioni variabili a seconda del modello) – Svariate altre periferiche, a seconda del modello
  • 4. PS3: Cluster o console? ● Dal sito della IBM: ”Cell combines a general-purpose Power Architecture core of modest performance with streamlined coprocessing elements which greatly accelerate multimedia and vector processing applications, as well as many other forms of dedicated computation.” ● “ Though sold as a game console, what will in fact enter the home is a Cell-based computer. ” - Ken Kutaragi, padre della console playstation
  • 5. PS3: Cluster o console? RISPOSTA: CLUSTER E CONSOLE! ● Accontenta i videogiocatori, fornendo loro una notevole esperienza videoludica... ● Fornisce un cluster di tutto rispetto per un prezzo relativamente economico
  • 6. Alcune informazioni ● Cell: abbreviazione di Cell Broadband Engine Architecture (talvolta si trova anche la sigla CBEA) ● Progettato in cooperazione da IBM, Sony e Toshiba espressamente per la PS3
  • 7. Sommario ● PS3: Cluster o console? ● Architettura CELL ● Programmazione usando il CELL
  • 9. Architettura CELL ● 1 Power Processor Element (PPE) ● 8 Synergistic Processor Element (SPE) ● Accesso alla memoria
  • 10. PPE: Power Processor Element ● ”A core to rule them all...” ● Architettura PowerPC a 64 bit 4GHZ (3.2 per la PS3) ● Cache L1: 32KB per le istruzioni, 32KB per i dati ● Cache L2: 512 KB ● Si occupa di mappare i tasks alle SPE ● Su di essa viene eseguito il sistema operativo... ● ... il maggior carico computazionale viene sopportato dalle SPE ● Dual-threaded ● in-order
  • 11. PPE: Power Processor Element ● Perchè in-order? – Per poter fornire le capacità di esecuzione out- of-order, c'è bisogno ovviamente di una maggiore complessità architetturale – Lo scheduling delle istruzioni è totale responsabilità del compilatore...
  • 12. Architettura CELL ● 1 Power Processor Element (PPE) ● 8 Synergistic Processor Element (SPE) ● Accesso alla memoria
  • 14. SPE:Synergistic Processor Element ● Le SPE rappresentano il ”braccio armato” della PPE... ● Architettura SIMD ● Si prendono sulle loro spalle il maggior carico computazionale ● 128 registri a 128 bit ● 4 floating point unit capaci di 32GFLOPS e 4 integer unit capaci di 32 GOPS ● Local store di 256KB... Manca qualcosa?
  • 15. SPE:Synergistic Processor Element ● Eh? manca la cache! ● Motivazioni di questa scelta: – Aggiunge complicazioni, dovute alla natura stessa della cache – Possiamo usare il Local Store...
  • 16. SPE:Synergistic Processor Element ● LOCAL STORE – Tramite questo la SPE accede alla memoria (non può farlo direttamente) – Possiamo spostare 16byte(128 bit) per ciclo da e verso la local store... esattamente il carico di ogni registro! – A differenza della cache, la local store può sostenere questo carico per oltre 10000 cicli
  • 17. SPE:Synergistic Processor Element ● Un possibile problema: contesa – Dobbiamo contemporaneamente caricare dati dalla memoria, scrivere dati in memoria e scrivere/caricare dati nei/dai registri... ● Soluzione: – La local store accede alla memoria in blocchi di almeno 1024bit per ciclo (circa 0.5 tera al secondo!)
  • 18. SPE:Synergistic Processor Element ● Local Store vs CACHE – Un tipico esempio: audio processing ● Se riesco a caricare all'interno del Local Store l'intero blocco di audio su cui devo lavorare, annullo gli accessi alla memoria durante l'esecuzione del programma... ● Impossibile (o comunque estremamente difficile) farlo con la cache
  • 19. SPE: Synergistic Processor Element ● Ulteriori vantaggi delle SPE – Possono essere usate efficacemente per stream programming... (GPU)
  • 20. Pensandoci su... ● Perchè tutto questo funzioni, c'è bisogno che le SPU siano sempre riempite di dati... ● Necessità di un sistema di accesso alla memoria e alle periferiche di I/O altamente performante...
  • 21. Architettura CELL ● 1 Power Processor Element (PPE) ● 8 Synergistic Processor Element (SPE) ● Accesso alla memoria – EIB e MMU – Memorie e dispositivi di I/O
  • 22. Element Interconnect Bus ● Unisce tutte le componenti sul chip ● Composto di 4 anelli da 16byte ciascuno e permettono di effettuare fino a 3 trasferimenti simultanei. ● Cosa fa? – Si occupa di spostare dati dalla memoria principale alle SPE e viceversa – Smista le istruzioni della PPE alle varie SPE
  • 23. Element Interconnect Bus ● Prestazioni: – 96 bytes per ciclo di clock, anche se secondo l'IBM ne sarebbero disponibili solo 64 nella pratica ● E la protezione della memoria? – Gestita dalle MMU contenute nelle SPE
  • 24. Memory Management Unit ● Utilizzate dalle SPE per l'accesso alla memoria o per accedere agli altri Local Store ● Forniscono i meccanismi di coerenza e protezione della memoria
  • 25. Importanza di EIB e MMU ● Entrambi devono essere performanti... ● Ma sufficientemente complessi da riuscire a gestire un enorme flusso di dati da distribuire in diverse destinazioni e una coda di almeno 128 richieste di memoria
  • 26. Architettura CELL ● 1 Power Processor Element (PPE) ● 8 Synergistic Processor Element (SPE) ● Accesso alla memoria – EIB e MMU – Memorie e dispositivi di I/O
  • 27. Memorie e dispositivi di I/O ● Dati tecnici: – XDR Rambus 256MB – Controller FlexIO – Ampiezza di banda della memoria: 25.6 GB/sec – Ampiezza di banda dei dispositivi di I/O: 76.8 GB/sec
  • 28. Intervallo ● Dolorosi incidenti di percorso... (vedi anche: ”la zappa sui piedi”) – come ho distrutto la playstation (1) – come ho distrutto la playstation (2)
  • 29. Come ho distrutto la playstation (1) ● Configurazione del sistema: Yellow Dog Linux 5.0 ● Necessario installare il cellsdk, ma a ogni tentativo ricevo un errore ”can't update glibc because of unresolved dependencies” ● IDEA: rimuovo le dipendenze, tanto ”se tolgo qualcosa di importante il sistema mi avviserà...” DON
  • 30. Come ho distrutto la playstation (1) ● A fianco vedete il risultato... ● Soluzione: formattazione e installazione di Fedora 5
  • 31. Come ho distrutto la playstation (2) ● Installata fedora 5, ma il cellsdk3.0 richiede fedora 7! ● Piano piano, aggiorno glibc dalla versione della 5 alla versione della 7... ● installo il cellsdk... ● applico varie patch al kernel... ● compilo ed eseguo con successo vari programmi... ● il tutto senza MAI riavviare la playstation 3! DON
  • 32. Come ho distrutto la playstation (2) ● La mia espressione al successivo riavvio della playstation ● Soluzione: installata fedora 7 e il cellsdk seguendo le ”procedure standard”
  • 33. Sommario ● PS3: Cluster o console? ● Architettura CELL ● Programmazione usando il CELL
  • 34. Una citazione doverosa... “To put it quite bluntly: as long as there were no machines, programming was no problem at all; when we had a few weak computers, programming became a mild problem, and now we have gigantic computers, programming has become an equally gigantic problem." -- E. Dijkstra, 1972 Turing Award Lecture Sarà vero??
  • 35. Programmare con il Cell ● Ingredienti: – Conoscerne l'architettura – Tanta pazienza – Linux (Fedora 7.0 o Red Hat Enterprise 5.0) – IBM CellSDK 3.0
  • 36. CellSDK ● Scaricabile dal sito della IBM (www.ibm.com) ● Fornisce un ambiente di sviluppo per la programmazione con il Cell, compatibile con qualsiasi architettura (purchè abbia FC 7 o RHE 5 installato)
  • 37. CellSDK ● STRUMENTI DI SVILUPPO – libspe.h, libspe2.h – ppu-gcc – spu-gcc – ppu-embedspu ● STRUMENTI DI DEBUGGING – ppu-gdb – spu-gdb ● ALTRO – systemsim-cell
  • 38. Altri tools utili non inclusi nell'sdk ● Eclipse + plugin per il cellsdk (richiede la JVM della IBM) ● Anjuta o Kdevelop
  • 39. Hello, Cell! ● Obiettivo: scrivere il classico ”Hello, world” utilizzando tutti le SPE del cell. 1) Isolare il task che ogni SPE dovrà eseguire (in questo caso stampare la stringa ”Hello, world da spe_id” (dove spe_id è l'id della SPE in esadecimale) 2) Fare in modo che il PPE mappi il task giusto ad ogni SPE
  • 40. Hello, Cell! ● Il primo passo è abbastanza banale... #include <stdio.h> int main(unsigned long long spe_id, unsigned long long argp, unsigned long long envp){ printf(”Hello, world! da 0x%xn”,(unsigned int) spe_id); return 0; } #include <stdio.h> int main(unsigned long long spe_id, unsigned long long argp, unsigned long long envp){ printf(”Hello, world! da 0x%xn”,(unsigned int) spe_id); return 0; }
  • 41. Hello, Cell! ● Passo 2: iniziano i guai... – come indichiamo alla PPE il programma da includere? – come effettuiamo il mapping ai vari SPE?
  • 42. Hello, Cell! ● I programmi che vanno eseguiti dalle SPE sono scritti per lavorare insieme alla PPE, ma hanno vengono compilati indipendentemente ● 1 compilatore per i programmi della PPE e 1 per i programmi della SPE, rispettivamente ppu-gcc e spu-gcc
  • 43. Hello, Cell! ● spu-gcc produce delle immagini ELF (Extensible Linking Format) che possono essere incluse nei programmi della PPE ● Ogni immagine ha la propria sezione di dati e di codice ● Le funzioni di Input/Output vengono eseguite richiedendo il servizio alla PPE
  • 44. Hello, Cell! extern spe_program_handle spe_program; extern spe_program_handle spe_program; Ecco come dichiareremo il programma ”esterno” da inserire nelle SPE all'interno della PPE Ora... bisogna dire alle SPE di caricare questo programma!
  • 45. Hello, Cell! ● Soluzione: potremmo dire a ogni PPE di eseguire un thread corrispondente al programma sopra descritto ● In libspe.h, esistono funzioni apposite... – spe_create_thread() - crea un thread che esegue al suo interno il programma – spe_wait() - aspetta la terminazione di un thread
  • 46. Hello, Cell! #include <stdio.h> #include <libspe2.h> #define NUM_THREAD 6 extern spe_program_handle spe_program; int main(void){ spe_id_t[NUM_THREAD] spe_id; int i; //creiamo i thread... for(i=0;i<NUM_THREAD;i++){ id[i] = spe_create_thread(0,&spe_program,NULL,NULL,-1,0); } //attendiamo la loro terminazione for(i=0;i<NUM_THREAD;i++){ spe_wait(id[i],NULL,0); } } #include <stdio.h> #include <libspe2.h> #define NUM_THREAD 6 extern spe_program_handle spe_program; int main(void){ spe_id_t[NUM_THREAD] spe_id; int i; //creiamo i thread... for(i=0;i<NUM_THREAD;i++){ id[i] = spe_create_thread(0,&spe_program,NULL,NULL,-1,0); } //attendiamo la loro terminazione for(i=0;i<NUM_THREAD;i++){ spe_wait(id[i],NULL,0); } }
  • 48. Hello, Cell! NO! LIBSPE DEPRECATA! Bisogna usare libspe2 in combinazione con la ben nota pthread.h
  • 49. Hello, Cell! ● Riscriviamo il programma usando la libspe2... ● A livello concettuale, vale tutto quello che abbiamo detto finora... ● semplicemente, siamo costretti a usare la pthread per la gestione dei threads
  • 50. Hello, Cell! ● Creazione/distruzione dei thread – pthread_create(id,thread_attr,thread_func,func_arg); – pthread_join(id,value); ● Più alcuni amici da libspe2... – spe_context_create(flags,gang_context) – spe_program_load(spe_context_ptr,program_handle ) – spe_context_run(spe_context_ptr,entry_point,runflag s,argp,envp,stopinfo) – spe_context_destroy(spe_context_ptr)
  • 51. Amici da libspe2 ● spe_context_create(flags,gang_context) – flags: ● SPE_EVENTS_ENABLE: abilita la gestione degli eventi ● – gang_context: ● equivalente al thread group, viene creato usando spe_gang_context_create Crea il context in cui viene eseguito il programma esterno
  • 52. Amici da libspe2 ● spe_program_load(spe_context_ptr,progr am_handle) – spe_context_ptr: puntatore al context spe – program_handle: puntatore al programma da eseguire all'interno del context specificato Carica il programma all'interno del context specificato
  • 53. Amici da libspe2 ● spe_context_run(spe_context_ptr,entry_p oint,runflags,argp,envp,stopinfo) – spe_context_ptr: puntatore allo spe_context da eseguire – entry_point: parametro inout ● in: il valore dell'instruction pointer da cui il programma inizierà la sua esecuzione ● out: il valore dell'instruction pointer al momento della terminazione del programma
  • 54. Amici da libspe2 ● spe_context_run(spe_context_ptr,entry_p oint,runflags,argp,envp,stopinfo) – runflags: or bitwise di più costanti ● 0: comportamento di default ● SPE_NO_CALLBACKS: vieta l'esecuzione automatica di callbacks ● SPE_RUN_USER_REGS: inizializza i 3 registri della SPU con i 48bytes puntati da argp – argp: (OPZIONALE) puntatore a dati del programma passati come secondo argomento
  • 55. Amici da libspe2 ● spe_context_run(spe_context_ptr,entry_p oint,runflags,argp,envp,stopinfo) – envp: (OPZIONALE) puntatore a dati specifici dell'ambiente di esecuzione, passati come terzo parametro al programma – stopinfo: (OPZIONALE) puntatore a una struttura spe_stop_info_t in cui scriveremo i dati relativi alla terminazione del programma
  • 56. Amici da libspe2 ● spe_context_destroy(spe_context_ptr) – libera le risorse associate a uno spe_context
  • 57. Allora, programmiamo? typedef struct{ spe_context_ptr_t spe_id; unsigned long *args; } thread_arg_t; //wrapping degli argomenti della funzione void *run_program(void* thread_arg){ unsigned int entry; entry = SPE_DEFAULT_ENTRY; spe_stop_info_t stop_info; ret = spe_context_run(arg->spe,&entry,0,NULL,NULL,&stop_info); if(ret<0){ perror("Errore di context_run"); return NULL; } printf("status %dn",spe_stop_info_read(arg->spe,&stop_info)); return NULL; } typedef struct{ spe_context_ptr_t spe_id; unsigned long *args; } thread_arg_t; //wrapping degli argomenti della funzione void *run_program(void* thread_arg){ unsigned int entry; entry = SPE_DEFAULT_ENTRY; spe_stop_info_t stop_info; ret = spe_context_run(arg->spe,&entry,0,NULL,NULL,&stop_info); if(ret<0){ perror("Errore di context_run"); return NULL; } printf("status %dn",spe_stop_info_read(arg->spe,&stop_info)); return NULL; }
  • 58. Allora, programmiamo? int main(int argc,char **argv){ int i,ret_value; spe_context_ptr_t spe[NUM_THREADS]; pthread_t thread[NUM_THREADS]; thread_arg_t arg[NUM_THREADS]; for(i=0;i<NUM_THREADS;i++){ spe[i] = spe_context_create(SPE_EVENTS_ENABLE,NULL); if(!spe[i]){ perror("spe_context_create error n"); exit(1); } ret = spe_program_load(spe[i],&hello_spu); if(ret){ perror("errore di spe_program_loadn"); exit(1); }//... CONTINUA int main(int argc,char **argv){ int i,ret_value; spe_context_ptr_t spe[NUM_THREADS]; pthread_t thread[NUM_THREADS]; thread_arg_t arg[NUM_THREADS]; for(i=0;i<NUM_THREADS;i++){ spe[i] = spe_context_create(SPE_EVENTS_ENABLE,NULL); if(!spe[i]){ perror("spe_context_create error n"); exit(1); } ret = spe_program_load(spe[i],&hello_spu); if(ret){ perror("errore di spe_program_loadn"); exit(1); }//... CONTINUA
  • 59. Allora, programmiamo? arg[i].spe = spe[i]; arg[i].args = NULL; ret = pthread_create(&thread[i],NULL,run_spu_program,&arg[i]); if(ret){ perror("errore di pthread_createn"); exit(1); } } for(i=0;i<NUM_THREADS;i++){ pthread_join(thread[i],NULL); ret = spe_context_destroy(spe[i]); if(ret){ perror("errore di spe_context_destroy!n"); exit(1); } } return 0; } arg[i].spe = spe[i]; arg[i].args = NULL; ret = pthread_create(&thread[i],NULL,run_spu_program,&arg[i]); if(ret){ perror("errore di pthread_createn"); exit(1); } } for(i=0;i<NUM_THREADS;i++){ pthread_join(thread[i],NULL); ret = spe_context_destroy(spe[i]); if(ret){ perror("errore di spe_context_destroy!n"); exit(1); } } return 0; }
  • 60. Compilazione ● The ”old way” – spu-gcc -o hello_spu hello_spu.c -g – ppu-embedspu hello_spu hello_spu hello_spu- embed.o – ar –qcs hello_spu.a hello_spu-embed.o – ppu-gcc -o hello hello_ppu.c -lspe2 hello_spu.a – ./hello ● Makefile – compreso nel cellsdk
  • 61. Funzioni di accesso alla memoria ● int spe_mfcio_put (spe_context_ptr_t spe, unsigned int lsa, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) ● int spe_mfcio_get (spe_context_ptr_t spe, unsigned int lsa, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid)
  • 62. Comunicazione tra 2 SPE ● int spe_out_mbox_read (spe_context_ptr_t spe, unsigned int *mbox_data, int count) ● int spe_in_mbox_write (spe_context_ptr_t spe, unsigned int *mbox_data, int count, unsigned int behavior)
  • 63. To be continued... GRAZIE PER LA CORTESE ATTENZIONE