Laboratorul 7 Familiarizarea cu arhitectura CELL, SDK 3.0

Scopul acestui laborator este familiarizarea cu arhitectura Cell si are ca finalitate scrierea, compilarea si rularea unui program simplu ce va afisa Hello World. Continutul laboratorului va fi structurat in doua parti: prezentarea arhitecturii CELL BE, urmata apoi de un tutorial.

Cuprins

1.   Descrierea arhitecturii CELL

      1.1.  PowerPC Processor Element (PPE)

      1.2. Synergistic Processor Elements (SPE-uri)

      1.3.  Ordonarea byte-ilor si numerotarea bitilor

      1.4.  Vectorizarea SIMD

      1.5. Tipurile de date vector

      1.6. Threaduri si taskuri

2.   Mediul de lucru

        2.1.  Instalarea imaginii de FC7 cu Cell SDK 3.0

      2.2.  Scrierea primului program pentru Cell Broadband Engine

      2.3.  Scrierea unui program multi-threaded pentru CBE

      2.4.  Rularea programului in simulator

3.  Linkuri utile

 

 

1.       Descrierea arhitecturii CELL

 

Arhitectura Cell Broadband Engine consta din noua procesoare pe un singur chip, toate interconectate si avand conexiuni la dispozitive externe printr-o magistrala cu latime mare de banda .

 

In Figura 1 este prezentata diagrama bloc a arhitecturii Cell Broadband Engine. Principalele elemente sunt:

 

-          PowerPC Processor Element (PPE): PPE este procesorul principal si contine un core RISC cu arhitectura PowerPC pe 64 biti si subsistem traditional de memorie virtuala. PPE ruleaza sistemul de operare, se ocupa de managementul resurselor intregului sistem si are ca rol primar asigurarea controlului resurselor, inclusiv alocarea si managementul threadurilor SPE. Poate rula software scris pentru arhitectura PowerPC si e eficient in rularea de cod de control de sistem. Suporta atat setul de instructiuni pentru PowerPC cat si setul de instructiuni Vector/SIMD Multimedia Extension.

-          Synergistic Processor Elements (SPEs). Cele opt SPEuri sunt procesoare de tip SIMD optimizate pentru operatii cu seturi multiple de date ce le sunt alocate de catre PPE. SPEurile sunt identice ca arhitectura si contin un core RISC, cu memorie locala de instructiuni si date controlata software (local store) de 256 KB si un fisier de registri generali cu 128 registri de 128 biti fiecare. SPEurile suporta un set special de instructiuni SIMD si folosesc transferuri DMA asincrone pentru a muta date si instructiuni intre spatiul principal de stocare (main storage, spatiul de adrese efective care include si memoria principala) si memoriile locale (local stores). Transferurile DMA ale SPEurilor aceseaza memoria principala (main storage) folosind adrese efective PowerPC. In cazul PPE, translatarea adreselor se face de catre segmentul de arhitectura PowerPC si folosind tabele de paginare. Diferenta consta in faptul ca SPEurile nu sunt proiectate sa se ocupe de rularea unui sistem de operare.

-          Element Interconnect Bus (EIB). Procesorul PPE si SPEurile comunica in mod coerent intre ele, cu spatiul principal de stocare (main storage) si cu elementele I/O prin intermediul magistralei EIB. Magistrala EIB are o structura bazata pe 4 inele (doua in sens orar si doua in sens anti-orar) pentru transferul datelor si o structura arborescenta pentru comenzi. Latimea de banda interna a magistralei EIB este de 96 bytes pe ciclu si suporta mai mult de 100 de cereri DMA in asteptare intre SPEuri si spatiul principal de stocare (main storage).

Fig. 1. Diagrama bloc a arhitecturii Cell Broadband Engine

 

Asa cum se observa in Figura 1, magistrala EIB cu acces coerent la memorie are doua interfete externe:

 

-          Controllerul de interfata cu memoria (Memory Interface Controller (MIC)) asigura interfata dintre magistrala EIB si spatiul principal de stocare (main storage). Suporta doua canale cu memoria de tip Rambus Extreme Data Rate (XDR) I/O (XIO) si accese la memorie pe fiecare canal de 1-8, 16, 32, 64, sau 128 bytes.

-          Interfata cu Cell Broadband Engine (Cell Broadband Engine Interface (BEI)) asigura managementul transferurilor de date intre magistrala EIB si dispozitivele I/O. Asigura translatarea adreselor, procesarea comenzilor, interfatarea cu magistrala si pune la dispozitie un controller intern de intreruperi. Suporta doua canale de tip Rambus FlexIO external I/O. Unul dintre aceste canale suporta doar dispozitive I/O non-coerente cu memoria. Cel de-al doilea canal poate fi configurat sa suporte atat transferuri non-coerente cat si transferuri coerente cu memoria care extind la nivel logic magistrala EIB cu cu alte dispozitive externe compatibile, cum ar fi de exemplu un alt Cell Broadband Engine.

 

 

Fig. 2: Diagrama Bloc a arhitecturii CELL Broadband Engine

 

 

Fig. 3: Diagrama Bloc a procesorului PPE

Fig. 4: Diagrama Bloc a procesorului SPE

 

 

Fig. 5: Topologia de date a magistralei Element Interconnect Bus (EIB)

 

Dezvoltarea de software in limbajul C/C++ este sustinuta de catre un set bogat de extensii de limbaj care definesc tipurile de date din C/C++ pentru operatii SIMD si contin C/C++ intrinsics (comenzi sub forma de apeluri de functii) spre una sau mai multe instructiuni de asamblare.

Aceste extensii de limbaj ofera programatorilor in C/C++ un control mai mare asupra performantelor ce pot fi obtinute din cod, fara a fi nevoie de programare in limbaj de asamblare. Dezvoltarea de software este sustinuta si de existenta:

-          Unui SDK complet bazat pe Linux,

-          Unui simulator de sistem si a

-          Unui set bogat de librarii de aplicatii, unelte de performanta si debugging.

 

 

 

1.1. PowerPC Processor Element (PPE)

 

PowerPC Processor Element (PPE) este un procesor cu scop general, dual-threaded, cu arhitectura RISC pe 64 de biti conforma cu arhitectura PowerPC, versiunea 2.02, avand setul de extensii Multimedia Vector/SIMD.

Programele scrise pentru procesorul PowerPC 970, de exemplu, pot fi rulate pe Cell Broadband Engine fara nici o modificare.

Asa cum reiese si din Figura 6, procesorul PPE are doua unitati principale:

-          Power Processor Unit (PPU).

-          Power Processor Storage Subsystem (PPSS).

 

PowerPC Processor Element (PPE) este responsabil de controlul general asupra sistemului si ruleaza sistemele de operare pentru toate aplicatiile ce ruleaza pe Cell Broadband Engine.

 

Fig. 6. Diagrama Bloc a PowerPC Processor Element (PPE)

 

Power Processor Unit (PPU) se ocupa de controlul si executia instructiunilor. Acesta contine:

-          setul complet de registri PowerPC pe 64 biti,

-          32 registri de vector pe 128 de biti,

-          un cache de instructiuni de nivel 1 (L1) de 32 KB,

-          un cache de date de nivel 1 (L1) de 32 KB,

-          o unitate de control de instructiuni,

-          o unitate pentru load and store,

-          o unitate pentru numere intregi in virgula fixa,

-          o unitate pentru numere in virgula mobila,

-          o unitate pentru vectori,

-          o unitate de predictie de ramificatie,

-          o unitate de management a memoriei virtuale.

 

Power Processor Unit (PPU) suporta executia simultana a doua threaduri si poate fi privit ca un multiprocesor 2-way cu flux de date partajat (shared dataflow). Din punct de vedere software, acesta este vazut ca doua unitati de procesare independente.

Power Processor Storage Subsystem (PPSS) se ocupa cu cererile de acces la memorie venite din partea PPE si cererile externe pentru PPE venite din partea altor procesoare si dispozitive I/O. Acesta contine:

-          un cache de nivel 2 (L2) unificat de date si instructiuni de 512 KB,

-          o serie de cozi (queues),

-          o unitate de interfata cu magistrala cu rol de arbitru de magistrala EIB.

 

Memoria este vazuta ca vector liniar de bytes indexati de la 0 la 264 - 1. Fiecare byte este identificat prin indexul sau, numit adresa, si contine o valoare. Se face cate un singur acces la memorie o data.

Cache-ul de nivel 2 (L2) si cache-urile folosite pentru translatarea adreselor tabele de management care permit controlul lor din software. Acest control software asupra resurselor de cache este in special util pentru programarea de timp real.

 

 

1.2. Synergistic Processor Elements (SPE-uri)

 

Fiecare dintre cele opt Synergistic Processor Elements (SPE-uri) este un procesor RISC pe 128 biti specializat in aplicatii SIMD ce necesita calcul intens asupra unor seturi multiple de date.

Asa cum reiese si din Figura 7, fiecare Synergistic Processor Element (SPE) contine doua unitati principale:

-          Synergistic Processor Unit (SPU).

-          Memory Flow Controller (MFC).

 

Fig. 7. Diagrama Bloc a Synergistic Processor Element (SPE)

 

Synergistic Processor Unit (SPU) se ocupa in primul rand de controlul si executia instructiunilor. Contine:

-          un singur fisier de registri cu 128 registri, fiecare de 128 biti,

-          o memorie locala (local store - LS) unificata (instructiuni si date) de 256 KB,

-          o unitate de control a instructiunilor,

-          o unitate de load and store,

-          doua unitati pentru numere in virgula fixa,

-          o unitate pentru numere in virgula mobila si

-          o interfata DMA.

 

Synergistic Processor Element (SPU) implementeaza un nou set de instructiuni SIMD, numit SPU Instruction Set Architecture, care e specific pentru Broadband Processor Architecture.

Fiecare Synergistic Processor Unit (SPU) este un procesor independent cu numarator (counter) propriu de program si este optimizat pentru rularea de threaduri SPE lansate de catre PowerPC Processor Element (PPE). Instructiunile pentru Synergistic Processor Unit (SPU) sunt aduse din memoria locala (local store LS) iar datele sunt aduse si salvate tot in memoria locala (local store LS). Fiind proiectata pentru a fi accesata in primul de catre SPU-ul propriu, memoria locala (local store LS) este neprotejata si netranslatata. Memory Flow Controller (MFC) contine un controller DMA pentru transferurile DMA. Programele care ruleaza pe SPU, pe PPE sau pe alt SPU, folosesc transferuri DMA controlate de MFC pentru mutarea datelor si instructiunilor intre memoria locala (local store LS) a SPU-urilor si spatiul principal de stocare (main storage). Spatiul principal de stocare (main storage) este format din spatiul de adrese efective care include memoria principala (main memory), memoriile locale ale altor SPE-uri si registri mapati in memorie cum ar fi registrii I/O [MMIO]. Memory Flow Controller (MFC) interfateaza Synergistic Processor Unit (SPU) cu Element Interconnect Bus (EIB), implementeaza facilitatile de rezervare bandwidth pe magistrala si sincronizeaza operatiile dintre Synergistic Processor Unit (SPU) si celelalte procesoare din sistem.

Pentru transferurile DMA, Memory Flow Controller (MFC) foloseste cozi de comenzi DMA. Dupa ce o comanda DMA a fost transmisa catre Memory Flow Controller (MFC), Synergistic Processor Unit (SPU) poate continua executia instructiunilor in timp ce Memory Flow Controller (MFC) proceseaza comenzile DMA autonom si asincron. Executia de comenzi DMA de catre Memory Flow Controller (MFC) autonom fata de executia de instructiuni de catre Synergistic Processor Unit (SPU) permite planificarea eficienta a transferurilor DMA pentru a acoperi latenta de memorie.

Fiecare transfer DMA poate avea maxim 16 KB. Totusi, doar SPU-ul asociat MFC-ului poate lansa lista de comenzi DMA. Acestea pot contine pana la 2048 transferuri DMA, fiecare de cate 16 KB. Informatia cu privire la translatarea adreselor de memorie virtuala este pusa la dispozitia MFC de catre sistemul de operare ce ruleaza pe PPE. Atributele sistemului de stocare (translatarea si protectia adreselor) sunt controlate prin tabelele de segmentare si paginare ale arhitecturii PowerPC. Totusi exista software special pentru PPE care poate mapa adresele si memoriile locale (local store LS) si anumite resurse MFC in spatiul de adrese din main-storage, permitand astfel PPE si altor SPU-uri din sistem sa acceseze aceste resurse.

SPE-urile ofera un mediu de operare determinist. Acestea nu au memorii cache, astfel ca nu exista cache miss-uri care sa le afecteze performanta. Regulile de planificare pe pipeline sunt simple, astfel ca performantele codului sunt usor de evaluat static. Desi memoria locala (local store LS) este partajata intre operatiile DMA de citire si scriere, load and store si de prefetch de instructiuni, operatiile DMA sunt cumulate si pot accesa memoria locala (LS) cel mult unul din 8 cicluri. La prefetch de instructiuni sunt aduse cel putin 17 instructiuni secventiale de pe ramura tinta. In acest mod, impactul operatiilor DMA asupra timpilor de operatii load and store si de executie a programelor este limitata din designul arhitecturii.

 

 

1.3. Ordonarea byte-ilor si numerotarea bitilor

 

Setul de instructiuni pentru PPE este o versiune extinsa a setului de instrutiuni PowerPC. Extensiile sunt reprezentate de catre setul de instructiuni Multimedia Vector/SIMD plus cateva adaugari si schimbari aduse setului de instructiuni PowerPC. Setul de instructiuni pentru SPE este asemanator cu setul de instructiuni Multimedia Extins Vector/SIMD al PPE. Desi PPE si SPE-urile executa instructiuni SIMD, seturile de instructiuni sunt diferite pentru fiecare din ele (PPE si SPE), iar programele scrise pentru PPE si SPE-uri trebuie compilate cu compilatoare diferite.

 

Stocarea datelor si instructiunilor in Cell Broadband Engine respecta ordonarea big-endian. Acest tip de ordonare are urmatoarele caracteristici:

-          Byte-ul cel mai semnificativ este stocat la cea mai mica adresa, iar cel mai putin semnificativ byte este stocat la cea mai mare adresa.

-          Numerotarea bitilor intr-un byte incepe de la cel mai semnificativ bit (bitul 0) pana la cel mai putin semnificativ bit (bitul n). Acest lucru difera fata de alte procesoare care folosesc tot ordonarea big-endian. Aceste aspecte sunt reprezentate grafic in Figura 8.

 

 

Fig. 8. Ordonarea Big-endian a byte-ilor si numerotarea bitilor in arhitectura Cell BE

 

 

1.4. Vectorizarea SIMD

 

Un vector este un operand pentru o instructiune si contine un set de elemente (date) grupate sub forma unui tablou (array) uni-dimensional. Elementele pot fi numere intregi sau in virgula mobila. Majoritatea instructiunilor SPU si din setul Multimedia Extins Vector/SIMD au ca operanzi vectori. Vectorii mai sunt numiti si operanzi SIMD sau operanzi impachetati.

Procesarea SIMD exploateaza paralelismul la nivel de date. Paralelismul la nivel de date se refera la faptul ca operatiile ce trebuie aplicate pentru a transforma un set de elemente grupate intr-un vector pot fi aplicate simultan asupra tuturor elementelor. Cu alte cuvinte, aceeasi instructiune poate fi aplicata simultan asupra mai multor elemente de date.

Suportul pentru operatii SIMD este omniprezent in arhitectura Cell Broadband Engine. In PPE, suportul este asigurat prin setul de instructiuni Multimedia Extins Vector/SIMD. In SPE-uri, suportul este asigurat de catre setul de instructiuni al SPU.

Atat in PPE cat si in SPE-uri, registrii de vectori contin mai multe elemente de date sub forma unui singur vector. Registrii si caile de date care suporta operatiile SIMD sunt pe 128 biti. Aceasta inseamna ca patru cuvinte pe 32 biti pot fi incarcate intr-un singur registru si, de exemplu, pot fi adunate cu alte patru cuvinte dintr-un alt registru intr-o singura operatie. Acest exemplu este reprezentat grafic in Figura 9. Operatii similare pot fi efectuate cu operanzi vectori continand 16 bytes, 8 semicuvinte sau 2 dublucuvinte.

 

Fig.9. Patru operatii de adunare executate simultan

 

Procesul de pregatire al unui program pentru a fi folosit pe un procesor ce lucreaza cu vectori se numeste vectorizare (vectorization sau SIMDization). Acest proces poate fi facut manual de catre programator sau de catre un compilator capabil de auto-vectorizare.

In Figura 10 se poate vedea un alt exemplu de operatie SIMD operatia de byte-shuffle. Selectia byte-ilor pentru operatia de shuffle din registrii sursa (VA si VB) se face pe baza informatiilor din vectorul de control din registrul VC, in care un 0 indica VA ca sursa iar un 1 indica VB ca sursa. Rezultatul operatiei de shuffle este salvat in registrul VT.

 

Fig. 10. Operatia de Byte-shuffle

 

 

1.5. Tipurile de date vector

 

Modelul Multimedia Extins Vector/SIMD adauga un set de tipuri de date fundamentale, numite tipuri de vectori (vector types).

Tipurile de vectori sunt afisate in Tabelul 1. Valorile reprezentate sunt in notatie zecimala (baza 10). Registrii de vectori sunt pe 128 biti si pot contine:

-          16 valori pe 8 biti, cu semn sau fara semn.

-          8 valori pe 16 biti, cu semn sau fara semn.

-          4 valori pe 32 biti, cu semn sau fara semn.

-          4 valori de numere in virgula mobila IEEE-754 in simpla precizie.

Toate tipurile de vectori folosesc prefixul vector in fata tipului de date standard Cde exemplu: vector signed int sau vector unsigned short. Un tip de date vector reprezinta un vector cu atatea elemente de tip standard C, cat incap intr-un registru de 128 biti. Astfel, un vector signed int este un operand pe 128 de biti care contine patru elemente signed int pe 32 de biti. Un vector unsigned short este un operand pe 128 de biti care contine opt elemente unsigned short pe 16 biti.

 

Tabelul 1 Tipurile de date din setul Multimedia Extins Vector/SIMD

 

Vector Data Types

Meaning

Values

vector unsigned char

Sixteen 8-bit unsigned values

0255

vector signed char

Sixteen 8-bit signed values

-128127

vector bool char

Sixteen 8-bit unsigned boolean

0(false), 255 (true)

vector unsigned short

Eight 16-bit unsigned values

065535

vector unsigned short int

Eight 16-bit unsigned values

065535

vector signed short

Eight 16-bit signed values

-3276832767

vector signed short int

Eight 16-bit signed values

-3276832767

vector bool short

Eight 16-bit unsigned values

0(false), 65535 (true)

vector bool short int

Eight 16-bit unsigned values

0(false), 65535 (true)

vector unsigned int

Four 32-bit unsigned values

0232-1

vector signed int

Four 32-bit signed values

-231231-1

vector bool int

Four 32-bit signed values

0 (false), 231-1 (true)

vector float

Four 32-bit unsigned values

IEEE-754 values

vector pixel

Eight 16-bit unsigned values

1/5/5/5 pixel

 

 

1.6. Threaduri si taskuri

 

Intr-un sistem care ruleaza sistemul de operare Linux, threadul principal al unui program este un thread Linux care ruleaza pe PPE. Threadul principal Linux al programului poate crea unul sau mai multe taskuri Linux pentru Cell Broadband Engine.

Un task Linux pentru Cell Broadband Engine are unul sau mai multe threaduri de Linux asociate cu acesta, care pot fi rulate fie pe PPE fie pe SPE. Un thread SPE este un thread de Linux care ruleaza pe SPE. Aceste notinui sunt detaliate in Tabelul 2.

Threadurile software descrise in aceasta sectiune nu au legatura cu capacitatea de hardware multithreading a PPE.

 

Tabelul 2 Definirea threadurilor si taskurilor

 

Term

Definition

Linux Thread

A thread running in the Linux operating-system environment.

PPE thread

A Linux thread running on a PPE.

SPE thread

A Linux thread running on an SPE. Each such thread:

-       has its own SPE context which includes the 128 x 128-bit register file, program counter, and MFC Command Queues.

-       can communicate with other execution units (or with effective-address memory through the MFC channel interface).

Cell Broadband Engine Linux task

A task running on the PPE and SPE.

-       Each such task has one or more Linux threads.

-       All the Linux threads within the task share the tasks resources.

 

 

Un thread de Linux poate interactiona direct cu un thread SPE prin memoria locala a SPE-ului (local store LS) si indirect prin memoria de adrese efective (EA) sau prin interfata oferita de catre subrutinele din SPE Runtime Management library.

Sistemul de operare ofera mecanismul si politicile de rezervare a unui SPE disponibil. Acesta are si rolul de a prioritiza aplicatiile de Linux pentru sistemul Cell Broadband Engine si de a planifica executia pe SPE, independenta de threadurile normale Linux. Este de asemenea responsabil si de incarcarea runtimeului, transmiterea parametrilor catre programele SPE, notificarea in cazul evenimentelor si erorilor din SPE-uri si asigurarea suportului pentru debugger.


 

Fig. 11. Vedere generala asupra unui chip Cell Broadband Engine

 

 

2.       Mediul de lucru

 

PPE ruleaza aplicatii si sisteme de operare, care pot include instructiuni din setul Multimedia Extins Vector/SIMD.

PPE necesita un sistem de operare extins pentru a oferi suport pentru caracteristicilor hardware a arhitecturii Cell Broadband Engine, cum ar fi: multiprocesarea cu SPE-uri, accesul la functiile din setul Multimedia Extins Vector/SIMD pentru PPE, controllerul de intreruperi din arhitectura Cell Broadband Engine si restul de functionalitati particulare din arhitectura Cell Broadband Engine. In acest mediu de operare, PPE se ocupa cu alocarea de threaduri si managementul de resurse intre SPE-uri. Kernelul Linux de pe SPE-uri controleaza rularea programelor pe SPU-uri.

Threadurile SPE urmeaza modelul de thread M:N, ceea ce inseamna ca M threaduri sunt distribuite la N elemente de procesare. In mod normal, threadurile SPE ruleaza pana la terminare. Totusi, rularea acestora este controlata de catre prioritatile si politicile de planificare a threadurilor. Cuanta de timp alocata pentru threadurile SPE este in mod normal mai mare decat cea a threadurilor PPE, doarece o schimbare de context pe SPE are un cost mai ridicat.

Kernelul Linux se ocupa cu managementul memoriei virtuale, inclusiv maparea fiecarei memorii locale (local store LS) si fiecarei zone problem state (PS) in spatiul de adrese efective. Kernelul controleaza atat maparea memoriei virtuale a resurselor MFC, cat si manipularea segment-fault-urilor si page-fault-urilor MFC. Sunt suportate si paginile mari (16 MB), care folosesc extensia Linux hugetlbfs.

 

2.1. Instalarea imaginii de FC7 cu Cell SDK 3.0

 

Primul pas consta in descarcarea imaginii de VMware cu Fedora Core 7, continand SDK de Cell versiunea 3.0, de la adresa :

 

http://storage.grid.pub.ro/vmware-images/Cell-VMWare-F7-SDK30.zip

 

Atentie : imaginea de mai sus ocupa 7.3 GB spatiu pe hard disk. Dupa descarcare, mai sunt necesari inca 7.3 GB spatiu pe hard disk pentru a dezarhiva continutul arhivei zip. In total va fi necesar un spatiu pe disc de cel putin 15.6 GB. Dupa dezarhivare, fisierul .zip se poate sterge.

 

Dupa descarcarea imaginii Cell-VMWare-F7-SDK30, se va descarca si instala VMware server, de la adresa :

 

http://register.vmware.com/content/download-a.html

 

Dupa instalarea VMware, in fereastra Inventory (stanga) (daca este afisata, se afasa F9) se da Dreapta-Click -> Open Virtual Machine -> Browse -> Se selecteaza fisierul Cell Broadband.vmx-> Ok-> Din meniul Power (sus) se selecteaza Power On.

 

Pentru a intra in contextul imaginii virtuale, se apasa stanga click in fereastra din dreapta. Pentru a iesi din contextul imaginii virtuale se apasa combinatia de taste(default) CTRL+ALT.

 

Informatii de acces :

User : root

Password : inn0vate

(atentie: al patrulea caracter din parola este cifra).

2.2. Scrierea primului program pentru Cell Broadband Engine

Pot fi mai multe tipuri de programe: programe PPE, programe SPE si programe pentru Cell Broadband Engine (programe PPE care au programme SPE embedded).

Programele pentru PPE si SPE folosesc compilatoare diferite. Compilatorul, flagurile compilatorului si librariile trebuie folosite in functie de tipul de procesor si program. De obicei, un PPE seteaza, porneste si opreste SPEuri. Un aspect important ce trebuie luat in consideratie este comunicarea dintre PPEuri si SPEuri.

Exista doua modalitati de baza pentru a testa un program pentru Cell Broadband Engine: prima se refera la folosirea de fisiere Makefile iar cea de a doua la folosirea unui mediu IDE (aceasta modalitate va fi prezentata in laboratorul urmator, folosind Eclipse). Mai departe vom exemplifica lucrul cu fisiere Makefile. Pentru mai multe detalii se poate consulta fisierul README_build_env.txt ce poate fi gasit in /opt/cell/sdk/buildutils.

In fisierele Makefile se pot declara tipul programelor, compilatorul ce va fi folosit, optiunile de compilare si librariile ce vor fi folosite. Cele mai importante tipuri de tinte (target types) sunt: PROGRAM_ppu and PROGRAM_spu, pentru compilarea programelor PPE si respective SPE. Pentru a folosi definitiile pentru makefile din kitul SDK, trebuie inclusa urmatoarea linie la sfarsitul fisierului makefile:

 

include ../../../buildutils/make.footer

 

Trebuie folosit un numar sufiecient de ../ pentru a ajunge la directorul buildutils. Alternativa este indicarea sursei pentru make.footer (mai ales cand se lucreaza din Eclipse IDE framework) definind in prealabil si folosind variabila de mediu CELL_TOP dupa cum urmeaza:

 

include $(CELL_TOP)/buildutils/make.footer

 

Se pot folosi ambele metode de a importa make.footer, asa cum se va vedea in exemplul de mai jos. In Figura 12 este prezentata structura de directoare si fisiere makefile pentru un sistem cu un program PPE si un program SPE. Acest proiect sampleproj are un director de proiect si doua subdirectoare. Directorul ppu contine codul sursa si fisierul makefile pentru programul PPE. Directorul spu contine codul sursa si fisierul makefile pentru programul SPE. Fisierul makefile din directorul de proiect lanseaza in executie fisierele makefile din cele doua subdirectoare. Aceasta structura de organizare pe directoare nu este unica.

 

Fig. 12. Exemplu de structura de directoare a unui proiect si fisiere makefile

 

2.3. Scrierea unui program multi-threaded pentru CBE

 

Pentru a scrie un program pentru CBE, sunt recomandati pasii descrisi mai jos (exemplul de cod este inclus in kitul SDK si poate fi gasit in /opt/cell/sdk/src/tutorial/simple).

Proiectul se numeste simple. Ca diversitate, in acest exemplu, codul pentru PPE va fi scris in directorul proiectului, in locul subdirectorului ppu.

 

1. Creati un director numit simple.

2. In directorul simple, creati un fisier cu numele Makefile, in care scrieti urmatoarea secventa de cod:

 

################

# Subdirectories

################

 

DIRS := spu

 

################

# Target

################

 

PROGRAM_ppu := simple

 

################

# Local Defines

################

 

IMPORTS := spu/lib_simple_spu.a -lspe2 -lpthread

# imports the embedded simple_spu library

# allows consolidation of spu program into ppe binary

 

 

################

# make.footer

################

 

# make.footer is in the top of the SDK

ifdef CELL_TOP

include $(CELL_TOP)/buildutils/make.footer

else

include ../../../../buildutils/make.footer

endif

 

3. In directorul simple, create fisierul simple.c, in care scrieti urmatoarea secventa de cod:

 

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <libspe2.h>

#include <pthread.h>

 

extern spe_program_handle_t simple_spu;

 

#define MAX_SPU_THREADS 16

 

void *ppu_pthread_function(void *arg) {

spe_context_ptr_t ctx;

unsigned int entry = SPE_DEFAULT_ENTRY;

ctx = *((spe_context_ptr_t *)arg);

if (spe_context_run(ctx, &entry, 0, NULL, NULL, NULL) < 0) {

perror ("Failed running context");

exit (1);

}

pthread_exit(NULL);

}

 

int main()

{

int i, spu_threads;

spe_context_ptr_t ctxs[MAX_SPU_THREADS];

pthread_t threads[MAX_SPU_THREADS];

/* Determine the number of SPE threads to create.

*/

spu_threads = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);

if (spu_threads > MAX_SPU_THREADS) spu_threads = MAX_SPU_THREADS;

/* Create several SPE-threads to execute 'simple_spu'.

*/

for(i=0; i<spu_threads; i++) {

/* Create context */

if ((ctxs[i] = spe_context_create (0, NULL)) == NULL) {

perror ("Failed creating context");

exit (1);

}

/* Load program into context */

if (spe_program_load (ctxs[i], &simple_spu)) {

perror ("Failed loading program");

exit (1);

}

/* Create thread for each SPE context */

if (pthread_create (&threads[i], NULL, &ppu_pthread_function, &ctxs[i])) {

perror ("Failed creating thread");

exit (1);

}

}

 

/* Wait for SPU-thread to complete execution. */

for (i=0; i<spu_threads; i++) {

if (pthread_join (threads[i], NULL)) {

perror("Failed pthread_join");

exit (1);

}

 

/* Destroy context */

if (spe_context_destroy (ctxs[i]) != 0) {

perror("Failed destroying context");

exit (1);

}

}

 

printf("\nThe program has successfully executed.\n");

return (0);

}

 

4. Creati un director numit spu.

5. In directorul spu, creati un fisier numit Makefile, in care scrieti urmatoarea secventa de cod:

 

################

# Target

################

 

PROGRAMS_spu := simple_spu

 

LIBRARY_embed := lib_simple_spu.a

 

 

################

# Local Defines

################

 

 

################

# buildutils/make.footer

################

 

ifdef CELL_TOP

include $(CELL_TOP)/buildutils/make.footer

else

include ../../../../buildutils/make.footer

endif

 

6. Tot in directorul spu, creati un fisier numit simple_spu.c, in care scrieti urmatoarea secventa de cod:

 

#include <stdio.h>

 

int main(unsigned long long id)

{

/* The first parameter of an spu program will always be the spe_id of the spe

* thread that issued it.

*/

printf("Hello World! from Cell (0x%llx)\n", id);

return 0;

}

 

7. Compilati programul folosind urmatoarea comanda in consola, in timp ce va aflati in directorul simple:

 

make

 

Acest program CBE creaza threaduri SPE care vor afisa mesajul Hello World! from Cell (#)\n in fereastra de iesire a systemsim, unde # este spe_id-ul al threadului SPE care executa comanda de afisare.

 

2.4. Rularea programului in simulator

 

Dupa terminarea compilarii programului, acesta poate fi rulat fie pe un sistem CBE, fie pe un simulator de sistem CBE. Se va folosi IBM Full System Simulator pentru Cell Broadband Engine cu rol de simulator de sistem CBE urmand in ordine pasii: pornirea simulatorului, importarea programului si rularea lui.

 

Pentru a porni simulatorul IBM Full System Simulator pentru Cell Broadband Engine cu interfata grafica, se recomanda parcurgerea pasilor urmatori:

 

1. Creati un mediu pentru simulator privat si non-root :

 

mkdir sim

cd sim

export PATH=/opt/ibm/systemsim-cell/bin:$PATH

 

2. Porniti simulatorul cu interfata grafica:

 

systemsim -g

 

3. Vor aparea doua ferestre noi pe ecran. Prima fereastra este de linie de comanda/consola cu numele mysim. Cea de a doua fereastra este interfata grafica (GUI). Aceste ferestre sunt prezentate in Figura 13.

 

Fig. 13. Ferestrele care apar dupa pornirea simulatorului cu interfata grafica

 

Fereastra cu numele mysim va fi consola interna pentru sistemul Linux folosit de simulator, ce va boota la pornirea simulatorului. Cand apare prima data, aceasta fereastra nu contine nimic, si nu are inca prompt, pana la pornirea simulatorului.

Fereastra in care se porneste simulatorul (systemsim -g) va avea rol de linie de comanda (consola) pentru simulator (a nu se confunda cu fereastra mysim, aceste console avand roluri diferite).

 

4. Porniti bootarea sistemului de operare Linux folosit de simulator apasand pe butonul Go din interfata grafica (GUI). Daca doriti ca simulatorul sa lucreze in mod rapid, alegeti optiunea Fast (Butonul Mode->Fast din GUI) inainte de a apasa Go. Selectand aceasta optiune, simulatorul sare o parte din pasii standard de analiza de sistem la bootare. Fereastra de consola va afisa informatiile din procesul de bootare a sistemului Linux in simulator. Dupa terminarea procesului de bootare, va aparea o consola (command prompt) in fereastra mysim (vezi Figura 14).

Atentie: daca procesul de bootare se blocheaza, folositi in consola din fereastra din care s-a pornit simulatorul (systemsim -g) urmatoarea comanda:

 

mysim go

 

Fig. 14. Fereastra de consola (mysim) dupa terminarea procesului de bootare in simulator

 

In acest moment, in simulator se poate aduce programul de CBE pentru a fi rulat. Pentru a verifica daca programul exista deja in mediul de simulare, se pot folosi comenzile ls, pwd, cd la command promptul ferestrei mysim pentru a cauta fisierul executabil numit simple.

 

5. Aduceti programul numit simple in mediul de simulare folosind urmatoarea comanda:

 

callthru source /tmp/simple > simple

 

Sintaxa comenzii este: callthru source cale_sursa > cale_destinatie , unde cale_sursa este calea catre fisierul executabil din Linux FC7, iar cale_destinatie este calea catre fisierul executabil din sistemul Linux folosit de simulator. In Figura 15 se poate vedea cum programul a fost adus in mediul de simulare. Aceasta metoda va pastra temporar fisierele aduse pana la inchiderea imaginii de Linux folosite de catre simulator (cand se inchide simulatorul, informatiile aduse se sterg).

Pentru a copia/sterge fisiere ce vor ramane permanent in imaginea de Linux folosita de catre simulator, se poate mounta aceasta imagine de Linux inainte de a porni simulatorul si efectua operatiile dorite. De exemplu, secventa urmatoare:

 

mount -o loop /opt/ibm/systemsim-cell/image/cell/sysroot_disk /mnt

cp /tmp/simple /mnt/simple

umount /mnt

 

este folosita pentru a copia executabilul numit simple din directorul /tmp din sistemul gazda (Fedora Core 7) in directorul sysroot / din imaginea de Linux folosita de catre simulator.

 

 

Fig. 15. Aducerea programului executabil in mediul de simulare

 

In ciuda faptului ca fisierul adus avea drepturi de executie inainte de a fi incarcat, dupa copierea lui in mediul de simulare aceste drepturi trebuie atribuite din nou.

 

6. Adaugati drepturi de executie programului simple folosind urmatoarea comanda:

 

chmod +x simple

 

7. Rulati programul folosind urmatoarea comanda:

 

./simple

 

Rezultatul rularii programului va fi afisat in fereastra de consola (Figura 16).

 

8. Daca inchideti ferestrele din greseala, iar fereastra mysim ramane deschisa, o puteti inchide in felul urmator: intr-o consola Linux FC7, scrieti comanda:

 

ps -aux | grep mysim

kill ID

 

unde ID este id-ul procesului cu numele mysim, obtinut in urma executiei primei comenzi.

 

 

Fig. 16. Rularea programului si afisarea rezultatelor

 

3. Linkuri utile:

1)      Informatii utile despre arhitectura CELL BE : http://www-01.ibm.com/chips/techlib/techlib.nsf/products/Cell_Broadband_Engine

2)      Imagine Fedora Core 7 cu Cell SDK 3.0: http://storage.grid.pub.ro/vmware-images/Cell-VMWare-F7-SDK30.zip

3)      VMware server download : http://register.vmware.com/content/download-a.html