Programmation de cartes graphiques

Slides:



Advertisements
Présentations similaires
GEF 435 Principes des systèmes d’exploitation
Advertisements

Hiver 2010JGA Beaulieu GEF 243B Programmation informatique appliquée Structure de base des programmes en C.
Premier programme en C :
Cours n° 7 Standard Template Library II.
C++ 6ème cours Patrick Reuter maître de conférences
Synchronisation des processus père - fils
GEF 243B Programmation informatique appliquée
Cours n° 8 Conception et Programmation à Objets
Approfondissement du langage
(Classes prédéfinies – API Java)
C.
JAV - TD 6 Structures de données JAVA
Paramètres et pointeurs
FLSI602 Génie Informatique et Réseaux
FLSI602 Génie Informatique et Réseaux
8. Les tableaux P. Costamagna – ISEN N1.
Leçon 3 : Héritage IUP 2 Génie Informatique
Parallel Programming in C with MPI and OpenMP
Système d’Exploitation
Common Gateway Interface
Principes de programmation (suite)
Points importants de la semaine Les fonctions. La portée. La passage par copie. Les tableaux.
Leçon 6 : Structures de données dynamiques IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier.
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009.
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais problèmes de cohérence problèmes de sécurité d'accès.
Quest-ce quune classe dallocation? Une classe dallocation détermine la portée et la durée de vie dun objet ou dune fonction.
Les fichiers binaires en C++
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
IFT-2000: Structures de données Les graphes Dominic Genest, 2009.
Présentation Structures de Données et TDA
Sixième cours Les chaînes de caractères et le passage de paramètres par référence Passage de paramètres par référence String.h.
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Parallel Programming in C with MPI and OpenMP
COURS DE PROGRAMMATION ORIENTEE OBJET :
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement.
Synchronisation Classique
Plan cours La notion de pointeur et d’adresse mémoire.
Animateur : Med HAIJOUBI
Le langage C Structures de données
Le langage C Rappel Pointeurs & Allocation de mémoire.
Programmation Système et Réseau (sous Linux)
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
La notion de type revisitée en POO
et quelques rappels sur certains éléments du langage C
Créer des packages.
Labo 4 : Les structures et les entrées et sorties
Tutorat en bio-informatique
Tutorat en bio-informatique Le 14 novembre Au programme… Les objets –Propriétés (attributs) –Constructeurs –Méthodes.
La programmation système
Programmation Système et Réseau
ETNA – 1ème année Guillaume Belmas –
Strings et Tableaux en Java
1 École des Mines de Saint-Etienne. 158, cours Fauriel Saint-Etienne Cedex 2. Tél Fax Jean-Jacques Girardot
ISBN Chapitre 10 L'implémentation des sous- programmes.
Classe 1 CSI2572 Autres modificateurs de déclaration de variables: & volatile & register & static & auto & extern & const volatile Indique au compilateur.
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
Pthread Ordonnancement. #define _MULTI_THREADED #include #ifndef _CHECK_H #define _CHECK_H /* headers used by a majority of the example program */ #include.
Liste Une liste est une séquence d’éléments. Concept important: Chaque élément possède une position dans la liste. Notation: De quelles opérations a-t-on.
Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions «
Les bases de l’algorithmique
8PRO107 Éléments de programmation Les adresses et les pointeurs.
Philippe Gandy – 10 novembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
C++ BY AURÉLIEN MODULO MARION. PLAN DES TROIS PRÉSENTATIONS C++ avancé C++ orienté objet Bases de C++
Transcription de la présentation:

Programmation de cartes graphiques OpenCL Programmation de cartes graphiques

OpenCL API + langage basé sur le C99 Conçu pour programmer des systèmes parallèles hétérogènes: CPU multi-coeur, GPU, etc. On distingue le processeur hôte des périphériques Un conteneur spécial (context) sert d’interface entre le processeur hôte et les périphériques Les données et les tâches (kernels) sont transférés à l’aide d’une file d’attente (command queue)

Un périphérique vu par OpenCL

Comparaison: C standard // Addition de 2 vecteurs de taille N // void vecadd(int *C, int* A, int *B, int N) { for(int i = 0; i < N; i++) { C[i] = A[i] + B[i]; }

Comparaison: Programmation multithread void vecadd(int *C, int* A, int *B, int N, int NP, int tid) { int ept = N/NP; // nbre d’éléments par thread for(int i = tid*ept; i < (tid+1)*ept; i++) { C[i] = A[i] + B[i]; }

Comparaison: OpenCL __kernel void vecadd(__global int *C, __global int* A, __global int *B) { int tid = get_global_id(0); // fonction OpenCL C[tid] = A[tid] + B[tid]; }

Espace des indices En OpenCL, l’espace des indices des processeurs peut avoir 1, 2 ou 3 dimensions. Il y a deux niveaux d’indices: Un indice global unique pour chaque work-item du périphérique (NDRange) Un indice local unique pour chaque work-item à l’intérieur d’un même workgroup.

NDRange et Workgroups

Connaître son indice get_global_id(dim): indice globale du work-item appelant selon la dimension dim=0,1 ou 2 get_local_id(dim): indice local du work-item appelant get_group_id(dim): indice du workgroup auquel appartient le work-item appelant get_local_size(dim): taille de la dimension dim dans le workgroup du work-item appelant.

Relation entre global et local get_global_id(dim) = get_local_size(dim)*get_group_id(dim) + get_local_id(dim)

Plateformes Une plateforme est une implémentation de OpenCL spécifique à un manufacturier donné Pour obtenir la liste des plateformes: cl_int clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms) clGetPlatformInfo pour obtenir de l’information sur une plateforme donné

Exemple 1 cl_int status; cl_uint numPlatforms = 0; cl_platform_id *platforms = NULL; status = clGetPlatformIDs(0, NULL, &numPlatforms); platforms = (cl_platform_id*)malloc( numPlatforms*sizeof(cl_platform_id)); status = clGetPlatformIDs(numPlatforms, platforms, NULL); char Name[1000]; clGetPlatformInfo(platforms[0], CL_PLATFORM_NAME, sizeof(Name), Name, NULL); printf("Name of platform : %s\n", Name);

Périphériques Pour chacune des plateformes (ex. NVIDIA), on peut obtenir la liste des périphériques associés: cl_int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices)

Exemple 2 cl_uint numDevices = 0; cl_device_id *devices = NULL; status = clGetDeviceIDs( platforms[0], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices); devices = (cl_device_id*)malloc( numDevices*sizeof(cl_device_id)); CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);

Contextes Un contexte est un type de conteneur permettant de communiquer des données et des instructions à des périphériques On utilise la fonction: clCreateContext Le premier paramètre sert à limité la porté du contexte, par exemple en spécifiant une plateforme particulière. Le « callback » sert a fournir une fonction qui pourra fournir d’avantage d’information sur les erreurs se produisant tout au long de l’utilisation du contexte.

Contextes cl_context clCreateContext ( const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void (CL_CALLBACK *pfn_notify)( const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret)

Exemple 3 cl_context context = NULL; context = clCreateContext( NULL, numDevices, devices, NULL, &status);

File de commandes On a déjà dit qu’un contexte est un conteneur permettant de communiquer avec un périphérique. On ajoute et retire l’information d’un contexte à l’aide d’une file d’attente appelée « file de commande » (command queue). Toutes les commandes indiquant une communication hôte-périphérique commencent par clEnqueue.

Création d’une file de commandes cl_command_queue clCreateCommandQueue( cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int* errcode_ret) Note: Le paramètre « properties » sert, entre autres, à indiquer si les éléments seront pris dans l’ordre.

Exemple 4 cl_command_queue cmdQueue; cmdQueue = clCreateCommandQueue( context, devices[0], 0, &status);

Objets mémoire Avant d’être transférés, les données doivent être converties dans un format particulier. Il y a deux formats: Les tampons (buffers) Les images Les tampons sont l’équivalent des tableaux en C et sont stockés de façon contiguë en mémoire. Les images sont des objets opaques et sont placées en mémoire de façon optimiser les performances.

Création d’un tampon cl_mem clCreateBuffer( cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret) Note: Le paramètre « flags » sert à indiquer si le tampon est en lecture, en écriture ou les deux.

Écrire dans un tampon cl_int clEnqueueWriteBuffer ( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, // CL_TRUE pour appel bloquant size_t offset, size_t cb, const void *ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

Lire dans un tampon cl_int clEnqueueReadBuffer( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t size, void *ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

Exemple 5 cl_mem bufferA, bufferB, bufferC; bufferA = clCreateBuffer( context, CL_MEM_READ_ONLY, datasize, NULL, &status); bufferB = clCreateBuffer( bufferC = clCreateBuffer( context, CL_MEM_WRITE_ONLY, datasize, NULL, &status); status = clEnqueueWriteBuffer( cmdQueue, bufferA, CL_FALSE, 0, datasize, A, 0, NULL, NULL); cmdQueue, bufferB, CL_FALSE, 0, datasize, B, 0, NULL, NULL);

Kernels Il faut distinguer le programme C de l’ordinateur hôte du programme C OpenCL qui sera exécuté sur un périphérique. Un programme C OpenCL est une collection de fonctions appelées « kernels » Le type de retour de ces fonctions doit être void Les kernels représentent les tâches que l’on peut ordonnancer de façon dynamique sur les périphériques.

Création et exécution d’un kernel Le code source est stocké sous la forme d’une chaîne de caractères La chaine est convertie en objet programmes à l’aide de la commande clCreateProgramWithSource() Un objet programme est compilé à l’aide de la commande clBuildProgram() Un kernel est obtenu à l’aide de la fonction Les paramètres du kernel sont affectés à l’aide de la commande clSetKernelArg() Le kernel est finalement exécuté à l’aide de la commande clEnqueueNDRangeKernel()

Création d’un objet programme cl_program clCreateProgramWithSource ( cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret)

Compiler un objet programme cl_int clBuildProgram ( cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data)

Obtenir un kernel cl_kernel clCreateKernel ( cl_program program, const char *kernel_name,   cl_int *errcode_ret) Note: *kernel_name contient le nom d’une fonction dans le programme source .

Affecter les paramètres cl_int clSetKernelArg ( cl_kernel kernel,   cl_uint arg_index,   size_t arg_size,   const void *arg_value) Note: Les paramètres demeurent affectés au kernel tant qu’il n’y a pas de modification explicite à l’aide de clSetKernelArg()

Exécuter un kernel cl_int clEnqueueNDRangeKernel( cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event)

Organisation de la mémoire

Espaces d’adressage Les qualificat __global: Mémoire partagée par tous les work-items du kernel. __constant: Mémoire en lecture seule partagée par tous les work-items du kernel. __local: Mémoire partagée par tous les work-items d’un même work-group. __private: Mémoire privée pour chaque work-item.

Espace d’adressage par défaut Pour améliorer la performance, on utilise autant que possible la mémoire __local ou __private. S’il n’y a pas de qualificatif, les paramètres des fonctions et les variables locales sont __private Le qualificatif des paramètres qui sont des pointeurs doit être spécifié et ne peut pas être __private. Les mémoires __private et __local ne sont pas préservées à la fin de l’exécution d’un work-item. La seule façon de retourner une valeur à l’hôte est via la mémoire __global.