Intro
Contents
La classe gpu_context incapsula la struttura context di OpenCL; Un context definisce un’area dati comune a uno o più device per la creazione e manipolazione di oggetti (memoria, code di comando, programmi..) e l’esecuzione dei kernel su uno o più device definiti nel context;
Le istanze di gpu_context in genere sono create automaticamente all’apertura dell’ambiente OPCL; generalmente un context è associato ad un solo device; i casi dove più device usano lo stesso context sono meno comuni, e non sono considerati in questo articolo.
ad esempio, analizziamo il frammento di codice che segue, usato in Colibrì per effettuare la retinatura di un’immagine:
gpu_kernel *kernel = OPCL::GPU::OpenKernel(prog_name, kernel_name); if (kernel) { // immagine sorgente gpu_image *src = new gpu_image(kernel, img_src, CL_MEM_READ_ONLY); src->Push_kernel(); // immagine trasferita in forma di matrice.. gpu_matrix_2d *dest = gpu_matrix_2d::New(kernel, img_dest, CL_MEM_WRITE_ONLY); dest->Push_kernel(); gpu_screener *screener = gpu_screener::New(kernel, DTH); screener->Push_kernel(); // lut dei colori assegnati per dtv OPCL::gpu_rgb_lut *lut = OPCL::gpu_rgb_lut::New(kernel, MAXDTV + 1, CL_MEM_READ_ONLY, _$str->rgb); lut->Push_kernel(); if (kernel->Set_index_space_2d(ret_area->dx, ret_area->dy)) { if (kernel->Exec()) { bool res = kernel->PopArg(dest); MSGS name; SPRINTF(name, L"%s_dth", img_src->GetName()); img_dest->InitDocInfo(name); img_dest->SetHtmlToolTip(); } else { OPCL::GPU::Display_error_info(); __delete (img_dest); } } kernel->FlushMemObjects(); return img_dest; } else GPU::Display_error_info();
Il comando gpu_kernel *kernel = OPCL::GPU::OpenKernel(prog_name, kernel_name) rimanda un kernel (vedi gpu_kernel) dati i nomi del programma e della funzione __kernel contenuta nel codice C OpenCl; l’inizializzazione di tutta l’infrastruttura OpenCL necessaria all’esecuzione è invisibile al programmatore ed è svolta dalla funzione statica GPU::OpenKernel. L’oggetto gpu_kernel creato contiene tutti i riferimenti per l’esecuzione: il programma compilato per il device selezionato, la piattaforma gpu_platform ed il gpu_context che incapsula il context usato dal runtime OpenCL per manipolare gli oggetti (command-queues, memoria e programmi).
Nelle righe successive del codice non appare mai alcun riferimento a gpu_context.. come mai? Risposta: perché la classe è incapsulata in gpu_kernel, e le sue funzionalità sono usate internamente a quest’ultima.
La riga di codice gpu_image *src = new gpu_image(kernel, img_src, CL_MEM_READ_ONLY) genera un oggetto di memoria gpu_image utilizzabile dal gpu_kernel: l’oggetto è generato nel context OpenCL gestito dal gpu_context incapsulato in gpu_kernel.
La riga successiva: src->Push_kernel() inserisce l’oggetto gpu_image src nella lista degli argomenti del kernel.
Le righe successive creano ed inseriscono nella lista degli argomenti altri oggetti di memoria (gpu_matrix_2d , gpu_screener , gpu_rgb_lut ed altri oggetti appartenenti al namespace OPCL descritti in altri articoli);Il resto del codice è usato per eseguire il kernel ed utilizzarne il risultato; non è importante in questo momento analizzare questa parte del codice (lo faremo in un successivo specifico post): abbiamo evidenziato che la classe gpu_context non appare mai, ma sappiamo che nelle specifiche OpenCL il context rappresenta il cuore di tutte le procedure eseguite.
L’approccio che abbiamo usato ha però permesso di scrivere il codice concentrando l’attenzione solo sulla parte relativa all’esecuzione dei programmi, nascondendo tutti i dettagli verbosi della programmazione OpenCL.