Familiarizarea cu arhitectura CELL, SDK 3.0/3.1

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.

Descrierea arhitecturii Cell Broadband Engine

  • 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.

Power Processor Element (PPE)

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

Programele scrise pentru procesorul Power 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).

Power 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 Power Processor Element (PPE)

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

  • setul complet de registri Power 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.

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 Power 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 Power. 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.

Ordonarea byte-ilor si numerotarea bitilor

Setul de instructiuni pentru PPE este o versiune extinsa a setului de instrutiuni Power. Extensiile sunt reprezentate de catre setul de instructiuni Multimedia Vector/SIMD plus cateva adaugari si schimbari aduse setului de instructiuni Power. 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

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

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 C, de 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 Type Content SPU/PPU
vector unsigned char 16 8-bit unsigned chars Both
vector signed char 16 8-bit signed chars Both
vector unsigned short 8 16-bit unsigned halfwords Both
vector signed short 8 16-bit signed halfwords Both
vector unsigned int 4 32-bit unsigned words Both
vector signed int 4 32-bit signed words Both
vector unsigned long long 2 64-bit unsigned doublewords SPU
vector signed long long 2 64-bit signed doublewords SPU
vector float 4 32-bit single-precision floats Both
vector double 2 64-bit double-precision floats SPU
qword quadword (16-byte), used exclusively as an input/output to a SPU specific intrinsic function SPU
vector bool char 16 8-bit bools - 0 (false) 255 (true) PPU
vector bool short 8 16-bit bools - 0 (false) 65535 (true) PPU
vector bool int 4 32-bit bools - 0 (false) 2^32-1 (true) PPU
vector pixel 8 16-bit unsigned halfword, 1/5/5/5 pixel PPU

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 continuare.

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

  • 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 task’s 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

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.

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 pe fep.grid.pub.ro in patru arhive ce trebuiesc concatenata in locatia /tmp/CellVmareImage-Split

Atentie : arhiva de mai sus ocupa 3.5 GB spatiu pe hard disk. Dupa descarcare, mai sunt necesari inca 8 GB spatiu pe hard disk pentru a dezarhiva continutul arhivei zip. In total va fi necesar un spatiu pe disc de cel putin 11.5 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: vmware.com.

Dupa instalarea VMware, in fereastra Inventory (stanga) (daca este afisata, se apasa 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

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:

  1. 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:

  1. 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

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

Makefile
  1. ################
  2. # Subdirectories
  3. ################
  4.  
  5. DIRS := spu
  6.  
  7. ################
  8. # Target
  9. ################
  10. PROGRAM_ppu := simple
  11.  
  12. ################
  13. # Local Defines
  14. ################
  15.  
  16. IMPORTS := spu/lib_simple_spu.a -lspe2 -lpthread
  17.  
  18. # imports the embedded simple_spu library
  19. # allows consolidation of spu program into ppe binary
  20.  
  21. ################
  22. # make.footer
  23. ################
  24.  
  25. # make.footer is in the top of the SDK
  26. ifdef CELL_TOP
  27. include $(CELL_TOP)/buildutils/make.footer
  28. else
  29. include ../../../../buildutils/make.footer
  30. endif

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

simple.c
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <errno.h>
  4. #include <libspe2.h>
  5. #include <pthread.h>
  6.  
  7. extern spe_program_handle_t simple_spu;
  8.  
  9. #define MAX_SPU_THREADS 16
  10.  
  11. void *ppu_pthread_function(void *arg) {
  12. spe_context_ptr_t ctx;
  13. unsigned int entry = SPE_DEFAULT_ENTRY;
  14.  
  15. ctx = *((spe_context_ptr_t *)arg);
  16. if (spe_context_run(ctx, &entry, 0, NULL, NULL, NULL) < 0) {
  17. perror ("Failed running context");
  18. exit (1);
  19. }
  20. pthread_exit(NULL);
  21. }
  22.  
  23. int main()
  24. {
  25. int i, spu_threads;
  26. spe_context_ptr_t ctxs[MAX_SPU_THREADS];
  27. pthread_t threads[MAX_SPU_THREADS];
  28.  
  29. /*
  30.   * Determine the number of SPE threads to create.
  31.   */
  32.  
  33. spu_threads = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);
  34. if (spu_threads > MAX_SPU_THREADS) spu_threads = MAX_SPU_THREADS;
  35.  
  36. /*
  37.   * Create several SPE-threads to execute 'simple_spu'.
  38.   */
  39.  
  40. for(i=0; i<spu_threads; i++) {
  41. /* Create context */
  42. if ((ctxs[i] = spe_context_create (0, NULL)) == NULL) {
  43. perror ("Failed creating context");
  44. exit (1);
  45. }
  46.  
  47. /* Load program into context */
  48. if (spe_program_load (ctxs[i], &simple_spu)) {
  49. perror ("Failed loading program");
  50. exit (1);
  51. }
  52.  
  53. /* Create thread for each SPE context */
  54. if (pthread_create (&threads[i], NULL, &ppu_pthread_function, &ctxs[i])) {
  55. perror ("Failed creating thread");
  56. exit (1);
  57. }
  58. }
  59.  
  60. /* Wait for SPU-thread to complete execution. */
  61. for (i=0; i<spu_threads; i++) {
  62. if (pthread_join (threads[i], NULL)) {
  63. perror("Failed pthread_join");
  64. exit (1);
  65. }
  66.  
  67. /* Destroy context */
  68. if (spe_context_destroy (ctxs[i]) != 0) {
  69. perror("Failed destroying context");
  70. exit (1);
  71. }
  72. }
  73.  
  74. printf("\nThe program has successfully executed.\n");
  75. return 0;
  76. }

4. Creati un director numit spu.

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

Makefile
  1. # Target
  2. PROGRAMS_spu := simple_spu
  3. LIBRARY_embed := lib_simple_spu.a
  4.  
  5. # include partea care face toata treaba pe baza definitiilor de mai sus
  6.  
  7. ifdef CELL_TOP
  8. include $(CELL_TOP)/buildutils/make.footer
  9. else
  10. include ../../../../buildutils/make.footer
  11. endif

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

simple_spu.c
  1. #include <stdio.h>
  2. int main(unsigned long long id)
  3. {
  4. /*
  5.   * The first parameter of an spu program will always be the spe_id of the spe
  6.   * thread that issued it.
  7.   */
  8.  
  9. printf("Hello World! from Cell (0x%llx)\n", id);
  10. return 0;
  11. }

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

  1. [razvan.dobre@cell-qs22-4 ~]$ 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.

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 :

  1. [razvan.dobre@cell-qs22-4 ~]$ mkdir sim
  2. [razvan.dobre@cell-qs22-4 ~]$ cd sim
  3. [razvan.dobre@cell-qs22-4 ~]$ export PATH=/opt/ibm/systemsim-cell/bin:$PATH
  4. [razvan.dobre@cell-qs22-4 ~]$ ulimit -s unlimited

2. Porniti simulatorul cu interfata grafica:

  1. [razvan.dobre@cell-qs22-4 ~]$ 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 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:

  1. [razvan.dobre@cell-qs22-4 ~]$ 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:

  1. [razvan.dobre@cell-qs22-4 ~]$ callthru source /tmp/simple > simple

Sintaxa comenzii este:

  1. 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:

  1. [razvan.dobre@cell-qs22-4 ~]$ mount -o loop /opt/ibm/systemsim-cell/image/cell/sysroot_disk /mnt
  2. [razvan.dobre@cell-qs22-4 ~]$ cp /tmp/simple /mnt/simple
  3. [razvan.dobre@cell-qs22-4 ~]$ 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:

  1. [razvan.dobre@cell-qs22-4 ~]$ chmod +x simple

7. Rulati programul folosind urmatoarea comanda:

  1. [razvan.dobre@cell-qs22-4 ~]$ ./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:

  1. [razvan.dobre@cell-qs22-4 ~]$ ps -aux | grep mysim
  2. [razvan.dobre@cell-qs22-4 ~]$ kill PID

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

Fig. 16. Rularea programului si afisarea rezultatelor

Taskuri

1. PThreads

  1. Folosind phtreads scrieti un program in C ce afiseara “Hello World!” din fiecare thread. Creati 8 astfel de threaduri.
  2. Modificati programul anterior pentru a permite transferul de parametrii catre thread. Definiti structura thread_param cu campul index de tip int. Trimiteti fiecarui thread ca si parametru cate o astfel de structura cu continut particularizat pentru fiecare thread.

2. CELL

  1. Scrieti un program in C pentru arhitectura Cell BE ce va crea un context ce va afisa din cadrul SPE mesajul “Hello World”. Programul de pe PPU se va numi lab1cell-ppu-1 iar ce pe SPE lab1cell-spu-1.
  2. Modificati programul scris anterior pentru a permite crearea a 16 contexte ce vor rula in paralel folosind PThreads.
  3. Modificati programul scris anterior astfel incat 8 contexte sa afiseze “Hello World 1” sau celelalte 8 “Hello World 2”.
  • man 3 spe_context_create
  • man 3 spe_context_run
  • man 3 spe_program_load

Linkuri utile

asc/lab6/index.txt · Last modified: 2013/03/26 14:24 by emil.slusanschi
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0