Comment GPU faire cela ?

Transcription

Comment GPU faire cela ?
Formation CIRA :
« Calcul Intensif en Rhône Alpes »
Comment GPU faire cela ?
« La science, c'est ce que le père enseigne à son fils. La technologie, c'est ce que le fils enseigne à son papa. »
Michel Serres (Interview du Monde)
Les GPUs : de la technologie pour la science ?
Ce que cette présentation
se sera pas/sera !
●
●
Ce que ce ne sera pas :
●
Une présentation n°57005 sur la techno des GPU
●
Une présentation ne vantant « que » les avantages
●
Une présentation des différentes solutions commerciales
Ce que ce sera :
●
Une approche personnelle issue de deux ans de recul
●
Une présentation « à grain » variable
●
Un tour d'horizon des solutions existantes
●
Un recueil de « trucs & astuces »
●
Un exemple d'implémentation : le modèle d'Ising en 2D
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
2/54
Le Triptyque du projet
●
Où en sommes-nous ?
●
●
Où allons-nous ?
●
●
Mais de combien de temps nous disposons ?
Comment y aller ?
●
●
Mais, d'abord, qui sommes-nous ?
Le pragmatisme comme premier principe
Tout est histoire de contexte !
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
3/54
La difficulté du sujet « tendance »
A chaque combinaison de réponses, une solution !
Pourquoi ?
Quoi ?
Qui ?
Comment ?
Où ?
Quand ?
Combien ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
4/54
Quelle présentation ?
Fil directeur : les 7 questions
« Back to Basics » : retour aux fondamentaux...
●
Pourquoi ? Ou pourquoi autant de puissance ?
●
Quand ? Ou comment en est-on arrivé là ?
●
Quoi ? Ou quels usages en attendre aujourd'hui ?
●
Qui ? Ou quels sont les « acteurs » du domaine ?
●
Où ? Ou quels domaines d'application ?
●
Combien ? Ou quelle «métrologie» y associer ?
●
Comment ? Ou comment l'aborder, en tirer avantage ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
5/54
1er au Top 500 : Tianhe 1A
la première vitrine du GPU
●
Quand : Novembre 2010
●
Où : Chine
●
Combien : 2.507 Pflops
●
Quoi : Linpack
●
Comment : CPU+GPU
●
●
7168 Nvidia Tesla C2050
●
14336 CPU Xeon
●
●
1/4 siècle auparavant
Qui : NUDT
Le « DARPA » chinois)
Pourquoi : ...
Le 7 novembre 2011
sur les écrans de cinéma
« The Last Starfighter »
Formation CIRA/GPU/2011 EQ
6/54
Pourquoi ? Ou d'où vient une telle
puissance de calcul...
Un film de série B...
Mais une arrivée fracassante de l'image de synthèse !
http://img.wallpaperstock.net:81/the-last-starfighter-wallpapers_16826_1024x768.png
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
7/54
Pourquoi ? Ou d'où vient une telle
puissance de calcul...
« The Last Starfighter »
●
27 minutes d'images
●
22.5e9 opérations/image
●
Usage d'un Cray X-MP
●
1984 : 12 jours sur X-MP4
●
2011 : 11 min sur GTX 560 Ti
●
Performances : x1500
●
Prix : 1/150 000
●
●
Consommation : 1/25000
●
Le 7 novembre 2011
Si Unité Centrale : 1/15000
Si Unité Centrale : 1/5000
Formation CIRA/GPU/2011 EQ
8/54
Pourquoi autant de puissance ?
Une croissance très différente
●
●
●
CPU : Passmark x20
●
2001 : AMD Athlon XP 2000+ : 370
●
2011 : Intel Xeon X5650 : 8000
GPU : Shader operations vs Flops x2500
●
2001 : GeForce FX 5200 ~1 Gops
●
2011 : GTX 590 ~2500 GFlops
Croissance GPU >> Croissance CPU
●
●
Près de 125x pour le processeur graphique
Tout ça pour faire des « Starfighter » en temps réel ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
9/54
Pourquoi autant de puissance ?
Pour construire une scène 3D !
●
●
2 approches :
●
Le « lancer de rayons » : PovRay
●
La « rastérisation » : 3 opérations
Lancer de rayons
●
●
Partir de l'œil et se déplacer vers les « objets » de la scène
Rastérisation :
●
Model2World : on place des objets vectoriels dans l'espace
●
World2View : on projète les objets sur un plan de vue
●
View2Projection : on transforme le plan de vue en points
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
10/54
Pourquoi autant de puissance :
Rastérisation & calcul matriciel
●
●
●
Modele 2 World : 3 produits matriciels
●
Rotation
●
Translation
●
Mise à l'échelle
M2W
W2V
World 2 View : 2 produits matriciels
●
Position de la caméra
●
Direction de l'endroit pointé
V2P
View 2 Projection
Un GPU : un « gros » multiplicateur de matrices
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
11/54
Pourquoi autant de puissance ?
Un retour au « généralisme »
Dans les GPU
●
Des processeurs dédiés
●
Efficacité = enchaînement
Mais perte d'adaptation
●
Scènes changeantes
●
Détails différents
La Solution
Disposer de processeurs plus « généralistes »
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
12/54
Pourquoi autant de puissance :
une machine massivement...
●
Vectorielle : SIMD (Simple Instruction Multiple Data)
●
●
Parallèle : MIMD (Multiple Instructions Multiple Data)
●
●
Addition de deux positions (x,y,z) : 1 seule commande
Plusieurs programmes en parallèle des mêmes données
En fait, SIMT : Simple Instruction Multiple Threads
●
Les cœurs de calcul se répartissent les Threads
●
Chaque cœur peut travailler indépendamment des autres
●
Nécessité de synchroniser les Threads
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
13/54
Combien ? Ou lorsque le « budget »
devient un sujet
●
●
La puissance : « avec 200€, t'as... »
●
« selon les fabricants » 1262 Gflops32...
●
« selon les testeurs » 512 Gflops32 (SGEMM)
●
Et « seulement » 100 Gflops64 (DGEMM) !
La consommation : « avec 200€ et 170W, t'as... » :
●
●
3 Gflops32/W et 0.6 Gflops64/W (sans l'UC ☺)
Les trois coûts du logiciel : (essentiellement humain !)
●
D'entrée : appropriation de la technologie
●
D'exploitation : maintien en fonctionnement
●
De sortie : migration vers une architecture différente
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
14/54
Quand ? Nvidia et sa carte C1060
« Nvidia Launches Tesla Personal Supercomputer »
●
Quand : le 19/11/2008
●
Où : sur Tom's Hardware
●
Quoi : une carte C1060 PCIe avec 240 coeurs
●
Combien : 933 Gflops SP (mais 78 Gflops DP)
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
Qui : Nvidia
15/54
Quand ?
Quelques grandes étapes...
●
1992-01 : OpenGL et la naissance d'un standard
●
1998-03 : OpenGL 1.2 et des fonctions intéressantes
●
2002-12 : Cg Toolkit (Nvidia) et l'extension du langage
●
Des Wrappers pour d'autres langages (Python)
●
2007-06 : CUDA (Nvidia) ou l'arrivée d'un vrai langage
●
2008-06 : Snow Leopard (Apple) intégrant OpenCL
●
La volonté d'utiliser au mieux sa machine ?
●
2008-11 : OpenCL 1.0 et ses premières spécifications
●
2011-04 : WebCL et sa première version par Nokia
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
16/54
Quelle position ?
Les Autres Accélérateurs...
●
●
Accélérateurs : une vieille histoire de coprocesseur...
●
1980 : 8087 (sur 8086/8088) pour calcul en virgule flottante
●
1989: 80387 (sur 80386) et le respect de la IEEE 754
●
1990 : 80486DX avec l'intégration du FPU dans le CPU
●
1997 : K6-3DNow ! & Pentium MMX : le SIMD dans le CPU
●
1999 : fonction SSE et le début d'une longue série (SSE4)
Quand les puces ressortent du CPU
●
1998 : les DSP style TMS320C67x comme outils
●
2008: Cell dans la PS3, IBM dans le Road Runner et Top1
Affaire de compilateurs & Programmation « fine »
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
17/54
Qui : pour qui et par qui ?
Ou quels sont les acteurs...
●
Chercheurs/Enseignant-chercheurs
●
Stagiaires/Doctorants/Post-doctorants
●
Ingénieurs en calcul scientifique
●
Ingénieurs systèmes & réseaux
●
Éditeurs :
●
●
Nvidia, AMD, (Intel), Nokia, (Apple), (Samsung)
●
Open Source Teams
Fabricants de matériels :
●
●
Nvidia, AMD/ATI, Intel
Intégrateurs : Dell, HP, ...
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
18/54
Quoi ? Ou des domaines
d'application très différents
●
Codes EXE : exécutable fournis par l'éditeur
●
●
●
●
À exécuter sous contraintes (matériel, architecture, OS, librairies, etc...)
Codes SRC : code source fourni par l'éditeur
●
À compiler sous contraintes (architecture, compilateur, librairies)
●
À exécuter sous contraintes
Codes OSS : Open Source Software
●
À modifier : tou(te)s architectures, compilateurs, librairies
●
À fiabiliser/consolider/pérenniser/étendre/valoriser
Codes CFS : Code « From Scratch »
●
À concevoir/développer
●
À fiabiliser/consolider/pérenniser/étendre/valoriser
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
19/54
Quoi ? Ou l'allégorie du « bateau »
et le modèle « en couches »
Programmes
Chercheur
Enseignant-Chercheur
Pour
Qui !
Stagiaire Doctorant
Post-doctorant
Ingénieur en Calcul
Scientifique
Par
Qui !
Technicien & Ingénieur
Systèmes & Réseaux
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
Kernels
OpenCL
CUDA
Langages
C, Fortran
Python
OpenCL
Cuda
ClAmd*
Librairies
Pilote
OS
GPU
Matériel
CPU/RAM
20/54
Quoi ?
Question de « hard » et de « soft »
●
Toujours question de « hard » et de « soft »
●
●
●
Outils « métier » : durée de vie longue !
●
Abinit 25 ans, Blast 21 ans, Lammps 7 ans, BigDFT 6 ans
●
Gaussian 41 ans, Molcas 22 ans, Vasp 20 ans
Matériels : durée de vie courte !
●
●
Le GPGPU a 4 ans, le Cell a vécu 5 ans, Larrebee mort né, MIC ?
Logiciels (OS, librairies, compilateurs, intergiciels, ...)
●
●
Mais quelles différences ?
Évolution permanente : BLAS né 1979 avec 16+9 implémentations
Méthodologie :
●
Entre conservatisme & modernité
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
21/54
Où ? Ou des domaines
d'applications très divers
●
Applications au calcul scientifique :
●
Visualisation scientifique (de gros volumes de données)
–
–
●
Traitement de données
–
–
●
Algèbre linéaire : CuBLAS, clAmdBlas, CuSparse , (CULA)
Analyse spectrale : CuFFT, clAmdFFT, PyFFT
Simulation numérique :
–
●
Lié à OpenGL (forte intrication dans OpenCL)
OpenCV (pour acquisition & traitement temps réel)
Toutes les librairies !
Des liens : http://gpuscience.com/
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
22/54
Où ? Ou des domaines
d'applications très divers
●
Applications informatiques « générales »
●
●
●
Accélération AES (pour SSL)
Pare-feu (packet-shader) :
http://shader.kaist.edu/packetshader/io_engine/index.html
Base de données (2004) :
–
●
Tri rapide
–
●
http://gamma.cs.unc.edu/DB/
http://code.google.com/p/back40computing/wiki/RadixSorting
Craqueur de mot de passe :
–
OclHashCat
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
23/54
Environnements CUDA/OpenCL :
3 acteurs Nvidia/AMD/(Intel)/Nokia
Composant
Pilote Nvidia
Pilote ATI
Cuda Toolkit
Architecture
Version
CPU
32
Développeur
Vers.
GPU
280.5.9
64
oui oui
270.41.19
11.9
Cuda OpenCL BLAS Sparse
lib
lib
dev
dev
FFT RNG
oui oui
4.0.17
oui
oui
oui oui
oui
oui oui
oui
oui oui
AMD APP SDK
2.5
AMD APP ML
1.4.182
Intel OpenCL
1.5
PyCUDA
2011.1.2
PyOpenCL
2011.1.2
oui
oui
oui oui
oui
WebCL Nokia
1.0.2rc30
oui
oui
oui oui
oui
Le 7 novembre 2011
Intégrateur
oui
oui
oui
oui
lib/dev
oui
oui
oui oui
oui
oui
oui
oui
Formation CIRA/GPU/2011 EQ
24/54
Comment ?
Installation de base
●
3 Implémentations OpenCL : Nvidia (+Cuda), AMD, Intel
●
Ce qu'il faut (avoir) : (pas nécessaire pour AMD et Intel)
●
Une carte graphique compatible
●
Un pilote propriétaire compatible avec son OS
–
●
●
OpenCL 1.1 sur Nvidia, pas le pilote 270.41.19, mais le 285.05.09 !
Ce qu'il faut (faire) :
●
Installer le pilote propriétaire (dispensé pour OpenCL/CPU)
●
Installer les librairies
●
Installer le SDK pour lancer les exemples
Ce qu'il faut (en penser) : à vous de voir !
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
25/54
Comment ?
Petites remarques préalables...
●
OS supportés : Linux, Windows, MacOS X
●
●
●
Nvidia : double précision réservé aux « puissantes »
●
Les peu puissantes généralement non (portables, etc...)
●
Les plus puissantes oui (au dessus de la GTX 260)
ATI : double précision bizarrement implémenté
●
●
Linux : OK, MacOSX > 10.6.8, Windows : XP, Vista, 7
Une 4350 à 23€ oui, une 6870 à 150€ non, une 5850 oui
Des calculs GPU distants
●
Nvidia : no problemo ●
ATI : « bricolage » du GDM et « ssh -x » indispensables
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
26/54
Comment ?
Premier contact...
●
●
●
Approche « perturbative »
●
Examiner les exemples des SDK (en C/C++) et les modifier
●
Problèmes : pas compatibles entre eux en OpenCL
Approche « constructive » : Python pour GPU
●
Installer les PyOpenCL et PyCuda
●
Prendre un problème très simple en Python et le transcrire
Approche « positive » : WebCL
●
Installer Firefox 7 (32 bits) et le greffon Nokia
●
Aller sur le « WebCL Kernel Toy » et jouer avec Len(n)a
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
27/54
Comment par WebGL ?
Son GPU à travers Firefox
●
Le prérequis :
●
Une implémentation OpenCL sur sa machine
–
–
–
Celle de Nvidia (avec pilote 285.05.09, pas le 270.41.19)
Celle de AMD/ATI (permettant d'utiliser le processeur)
Celle d'Intel (non, je plaisante !)
●
Firefox 7 (en x86, pas x86_64)
●
Greffon Nokia : http://webcl.nokiaresearch.com/
●
Aller sur : http://webcl.nokiaresearch.com/kerneltoy/
●
Petite démo ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
28/54
Comment par Python ?
Son GPU à travers Python
●
Le prérequis :
●
Une implémentation OpenCL ou Cuda sur sa machine
–
–
●
Librairies de développement OpenCL ou Cuda
–
–
●
Celle de Nvidia (avec pilote 285.05.09, pas le 270.41.19)
Celle de AMD/ATI (permettant d'utiliser le processeur)
Celle de Nvidia
Celle de AMD
●
Python, Boost (pour la liaison au C), Compilateur C
●
PyCUDA ou PyOpenCL à télécharger
Petite démo ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
29/54
Comment par C/C++ ?
Son GPU avec AMD ou Nvidia
●
Le prérequis :
●
Une implémentation OpenCL ou Cuda sur sa machine
–
–
●
Librairies de développement OpenCL ou Cuda
–
–
●
●
Celle de Nvidia (avec pilote 285.05.09, pas le 270.41.19)
Celle de AMD/ATI (permettant d'utiliser le processeur)
Celle de Nvidia
Celle de AMD
Un compilateur C
Petite démo ? Vous êtes sûr ? En OpenCL ?
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
30/54
Comment ?
Un « Hello World » en OpenCL...
●
●
●
●
Addition de
Les dupliquer en deux gros vecteurs 2 vecteurs a+b =c
pour tout n :
Les ajouter avec un noyau OpenCL c[n] = a[n] + b[n]
Imprimer à l'écran le résultat (oui, c'est tout...)
Définir deux vecteurs en « Ascii »
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
Hello OpenCL World!
The End
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
31/54
Comment ?
« Hello World » OpenCL en C...
#include <stdio.h>
cl_mem GPUVector1 = clCreateBuffer(GPUContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
#include <stdlib.h>
sizeof(int) * SIZE, HostVector1, NULL);
#include <CL/cl.h>
cl_mem GPUVector2 = clCreateBuffer(GPUContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
"__kernel void VectorAdd(__global int* c, __global int* a,__global int* b)",
"{",
sizeof(int) * SIZE, HostVector2, NULL);
!
const char* OpenCLSource[] = {
cl_mem GPUOutputVector = clCreateBuffer(GPUContext, CL_MEM_WRITE_ONLY,sizeof(int) * SIZE, NULL, NULL);
cl_program OpenCLProgram = clCreateProgramWithSource(GPUContext, 7, OpenCLSource,NULL, NULL);
"
// Index of the elements to add \n",
"
unsigned int n = get_global_id(0);",
"
// Sum the n’ th element of vectors a and b and store in c \n",
clSetKernelArg(OpenCLVectorAdd, 0, sizeof(cl_mem),(void*)&GPUOutputVector);
"
c[n] = a[n] + b[n];",
clSetKernelArg(OpenCLVectorAdd, 1, sizeof(cl_mem), (void*)&GPUVector1);
ve
rk
ill
clBuildProgram(OpenCLProgram, 0, NULL, NULL, NULL, NULL);
cl_kernel OpenCLVectorAdd = clCreateKernel(OpenCLProgram, "VectorAdd", NULL);
clSetKernelArg(OpenCLVectorAdd, 2, sizeof(cl_mem), (void*)&GPUVector2);
"}"
size_t WorkSize[1] = {SIZE}; // one dimensional Range
};
int InitialData1[20] = {37,50,54,50,56,0,43,43,74,71,32,36,16,43,56,100,50,25,15,17};
int InitialData2[20] = {35,51,54,58,55,32,36,69,27,39,35,40,16,44,55,14,58,75,18,15};
#define SIZE 2048
clEnqueueNDRangeKernel(cqCommandQueue, OpenCLVectorAdd, 1, NULL,
WorkSize, NULL, 0, NULL, NULL);
int HostOutputVector[SIZE];
clEnqueueReadBuffer(cqCommandQueue, GPUOutputVector, CL_TRUE, 0,SIZE * sizeof(int), HostOutputVector, 0, NULL,
NULL);
int main(int argc, char **argv)
clReleaseKernel(OpenCLVectorAdd);
{
int HostVector1[SIZE], HostVector2[SIZE];
for(int c = 0; c < SIZE; c++)
O
HostVector1[c] = InitialData1[c%20];
HostVector2[c] = InitialData2[c%20];
cl_platform_id cpPlatform;
clReleaseCommandQueue(cqCommandQueue);
clReleaseContext(GPUContext);
{
}
clReleaseProgram(OpenCLProgram);
clGetPlatformIDs(1, &cpPlatform, NULL);
clReleaseMemObject(GPUVector1);
clReleaseMemObject(GPUVector2);
clReleaseMemObject(GPUOutputVector);
Noyau
OpenCL
for (int Rows = 0; Rows < (SIZE/20); Rows++) {
printf("\t");
for(int c = 0; c <20; c++) {
printf("%c",(char)HostOutputVector[Rows * 20 + c]);
cl_int ciErr1;
}
cl_device_id cdDevice;
}
ciErr1 = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, NULL);
printf("\n\nThe End\n\n");
cl_context GPUContext = clCreateContext(0, 1, &cdDevice, NULL, NULL, &ciErr1);
cl_command_queue cqCommandQueue = clCreateCommandQueue(GPUContext,
Nombre de Lignes
De OpenCL
return 0;
Appel Noyau
}
cdDevice, 0, NULL);
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
32/54
Comment ?
« Hello World » OpenCL en Python
import pyopencl as cl
mf = cl.mem_flags
import numpy
GPUVector1 = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR,
hostbuf=HostVector1)
import numpy.linalg as la
import sys
OpenCLSource = """
GPUVector2 = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR,
hostbuf=HostVector2)
__kernel void VectorAdd(__global int* c, __global int* a,__global int* b)
GPUOutputVector = cl.Buffer(ctx, mf.WRITE_ONLY, HostVector1.nbytes)
{
OpenCLProgram = cl.Program(ctx, OpenCLSource).build()
// Index of the elements to add
unsigned int n = get_global_id(0);
OpenCLProgram.VectorAdd(queue, HostVector1.shape,
None,GPUOutputVector , GPUVector1, GPUVector2)
// Sum the n th element of vectors a and b and store in c
HostOutputVector = numpy.empty_like(HostVector1)
c[n] = a[n] + b[n];
cl.enqueue_copy(queue, HostOutputVector, GPUOutputVector)
}
GPUVector1.release()
"""
GPUVector2.release()
InitialData1=[37,50,54,50,56,0,43,43,74,71,32,36,16,43,56,100,50,25,15,17]
GPUOutputVector.release()
InitialData2=[35,51,54,58,55,32,36,69,27,39,35,40,16,44,55,14,58,75,18,15]
OutputString=''
SIZE=2048
for rows in range(SIZE/20):
HostVector1=numpy.zeros(SIZE).astype(numpy.int32)
HostVector2=numpy.zeros(SIZE).astype(numpy.int32)
for c in range(SIZE):
HostVector1[c] = InitialData1[c%20]
HostVector2[c] = InitialData2[c%20]
ctx = cl.create_some_context()
OutputString+='\t'
for c in range(20):
OutputString+=chr(HostOutputVector[rows*20+c])
print OutputString
sys.stdout.write("\nThe End\n\n");
queue = cl.CommandQueue(ctx)
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
33/54
Comment ?
« Hello World » OpenCL : la pesée
●
●
Sur l'implémentation OpenCL précédente :
●
En C : 75 lignes, 262 mots, 2848 octets
●
En Python : 51 lignes, 137 mots, 1551 octets
●
Facteurs : 0.68, 0.52, 0.54 en lignes, mots et caractères...
Programmation OpenCL :
●
Contexte de programmation difficile :
–
–
●
Pas de compatibilité entre les SDK de AMD et Nvidia
–
●
Ouvrir le carton est plus difficile que de monter le meuble...
Exigence d'une API simplifiant l'appel d'OpenCL
Chacun a développé son API : portabilité des codes difficile...
Une solution, sinon « LA » solution : Python
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
34/54
Une « success story » pour finir ?
Petite aventure au royaume d'Ising
●
Un verre de spin complété aléatoirement de valeurs -1 ou 1
D U D U
4x4
U
U U D D
U D D U
D
D U U D
●
D
256x256
Une intéraction simple basée sur les quatre voisins
●
●
U
LocalEnergy=2*J*s(x,y)*[s(x-1,y)+s(x-1,y)+s(x,y-1)+s(x,y+1)]
Une règle simple de retournement (1→-1 or -1→1) de site :
●
1) Si LocalEnergy est négative : convertie par ses voisins
–
●
Loi des « moutons de Panurge »
2) Si RNG + petit que le facteur de Boltzmann (@ LocalEnergy and T°)
–
Loi de « l'esprit bien français »
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
35/54
Le modèle d'Ising en équations :
Implémentation « naïve »
●
Fonction Metropolis : Metropolis(sigma,J,T,step,iterations)
●
sigma : verre de spin
●
J : facteur de couplage (égal à l'unité pour les simulations)
●
T : Température d'exploration
●
Step : itérations entre 2 étapes (pour sauver un état)
●
Iterations : nombre total d'explorations aléatoire du verre
●
Température d'exploration : de 0.1 à 5 avec un pas de0.1
●
Sortie :
●
Energie : basée sur l'estimation de l'intéraction de couplage
●
ImageDeSortie : verre de Spin après itérations
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
36/54
Modèle d'Ising (en Python)
Procédure principale
def MainLoop(sigma,J,T,iterations):
for p in range(0,iterations):
Appels RNG
● Coordonnées X,Y
● Entre 0 et 1
● Conditions aux bords
● « univers cylindrique »
● Interaction des Spins
● Estimation de l'énergie
● Facteur de Boltzmann
● Appel Random & test
●
X=numpy.random.randint(SIZE),
Y=numpy.random.randint(SIZE)
DeltaE=2.*J*sigma[X,Y]*(
sigma[X,(Y+1)%SIZE]+
sigma[X,(Y-1)%SIZE]+
sigma[(X-1)%SIZE,Y]+
sigma[(X+1)%SIZE,Y])
if DeltaE < 0. or random() < exp(-DeltaE/T):
sigma[X,Y]=-sigma[X,Y]
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
37/54
Modèle d'Ising (en Python) :
pour une température donnée T...
Durée
147s
Portable
E6410
Intel i7 M640
Initial : T=0.1
i=N²
i=N³/4
Durée
153s
Station
Precision 7500
2 Intel X5650
Final : i=N³
Le 7 novembre 2011
i=3N³/4
i=N³/2
Formation CIRA/GPU/2011 EQ
38/54
Modèle d'Ising (en Python) :
Vers une température critique
Initial
Energie=f(T)
Le 7 novembre 2011
Tc~2.3
T=0.1
T=2.4
Formation CIRA/GPU/2011 EQ
T=0.8
T=3.2
T=1.6
T=4.0
39/54
Modèle d'Ising (en Python) :
OpenCL version « globale »
for (uint i=0;i<iterations;i++) {
#define znew (z=36969*(z&65535)+(z>>16))
uint x=(uint)(MWCfp*sizex) ;
#define wnew (w=18000*(w&65535)+(w>>16))
uint y=(uint)(MWCfp*sizey) ;
#define MWC ((znew<<16)+wnew )
int p=s[x+size*y];
#define MWCfp (MWC + 1.0f) * 2.328306435454494e-10f
int d=s[x+size*((y+1)%size)];
__kernel void MainLoop(__global char *s,
int u=s[x+size*((y-1)%size)];
int l=s[((x-1)%size)+size*y];
float J,float T,uint size,uint iterations,
int seed_w,int seed_z)
{
int r=s[((x+1)%size)+size*y];
float DeltaE=2.0f*J*p*(u+d+l+r);
RNG Marsaglia
MWC
int factor=((DeltaE < 0.0f) ||
(MWCfp <
int z=seed_z;
exp(-DeltaE/T))) ? -1:1;
s[x%size+size*(y%size)] = factor*p;
int w=seed_w;
barrier(CLK_GLOBAL_MEM_FENCE);
}
}
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
40/54
Modèle d'Ising (en Python)
Simulation finale
●
Pour une verre de spin de 256x256
●
Pour 51 températures (de 0.1 à 5 par pas de 0.1)
●
Pour 256x256x256 itérations
●
En Python (bestial !) : 126 min (150 sec/T°)
●
En Python et OpenCL « global » : 23 min (26 sec/T°)
●
Et en C (classique) : 2 min 7 sec
●
Il va falloir trouver autre chose !
Segmenter le verre de spin en sous domaines...
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
41/54
Modèle d'Ising (en Python)
OpenCL version « locale »
#define BSZ $block_size
// Main loop
/* Marsaglia RNG very simple implementation */
for (uint i=0;i<iterations;i++)
#define znew (z=36969*(z&65535)+(z>>16))
{
#define wnew (w=18000*(w&65535)+(w>>16))
// Version with MWCfp
// MWC is a signed one : between -2^31 to 2^31-1
int x=(uint)(MWCfp*BSZ)%BSZ;
#define MWC ((znew<<16)+wnew )
int y=(uint)(MWCfp*BSZ)%BSZ;
// MWCfp is a float one : between 0 and 1
#define MWCfp (float)((MWC + 2.147483648e9f) * 2.328306435454494e-10f)
__kernel void MainLoop(__global int *s,
int p=s[((base_idx+x)%size)+size*((base_idy+y)%size)];
int u= s[((base_idx+x)%size)+size*((base_idy+y-1)%size)];
int d= s[((base_idx+x)%size)+size*((base_idy+y+1)%size)];
__constant int *seed_w,
int l= s[((base_idx+x-1)%size)+size*((base_idy+y)%size)];
__constant int *seed_z,
int r= s[((base_idx+x+1)%size)+size*((base_idy+y)%size)];
float J,float T,uint size,uint iterations)
float DeltaE=2.0f*J*p*(float)(u+d+l+r);
{
int factor= ((DeltaE < 0.0f) || (MWCfp < exp(-DeltaE/T))) ? -1:1;
// Define global offset for each work items
s[base_idx+x+(base_idy+y)*size]= factor*p;
uint base_idx=(uint)(BSZ*get_global_id(0));
barrier(CLK_GLOBAL_MEM_FENCE);
uint base_idy=(uint)(BSZ*get_global_id(1));
// Assign eath work item a random defined seed provided by host
int z=seed_z[(uint)(get_global_id(0))%get_global_size(0)];
}
barrier(CLK_GLOBAL_MEM_FENCE);
int w=seed_w[(uint)(get_global_id(1))%get_global_size(1)];
RNG Marsaglia
MWC
Le 7 novembre 2011
Conditions
aux bords
Formation CIRA/GPU/2011 EQ
Synchronisation
42/54
Modèle d'Ising (en Python/OpenCL)
Résultats version « Locale »
●
●
Petits rappels :
●
En Python pur : 126 minutes
●
En C : 2 minutes (Gcc) et 1 minute (Icc)
●
En Python OpenCL « Global » : 23 minutes
Sur la même machine : Precision 7500
●
Avec l'appel sur la carte graphique : 46 secondes
●
Avec l'appel des processeurs : 8 secondes...
●
Moralité : OpenCL est sacrément puissant (en CPU)
●
Prévisible ? Oui !
●
Des synchronisations entre tâches à tous moments...
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
43/54
Modèle d'Ising (en Python/OpenCL)
Différents GPU & version Locale
●
Une GTX 560Ti écrase une Quadro 4000 !
●
Un processeur « virtuel » (Qemu de KVM) qui scale...
Quadro 4000
Dual Core AMD Opteron 275
Tesla C1060
GPU portables...
HD 4890
Intel Xeon [email protected]
HD 4850
Intel Pentium 4 3.00GHz
Intel Core i5 [email protected]
GeForce GT220
Processeur
Type de GPU
GeForce 8600MGT
GeForce GT220
GeForce 8400GS
QEMU Virtual CPU version 0.12.5
Intel Core 2Duo [email protected]
GeForce GT430
HD 5850
Intel Core 2 Quad [email protected]
GeForce GTX260
GPU
NVS 3100M
GeForce GTX560Ti
0,00
200,00
400,00
600,00
800,00
Durée en secondes
Réel
Le 7 novembre 2011
Utilisateur
Système
1000,00
1200,00
Intel Core i7 [email protected]
CPU
Intel Xeon [email protected]
1400,00
0,00
Ca « scale » bien !
40,00
60,00
80,00
100,00 120,00 140,00 160,00
Durée en secondes
Réel
Formation CIRA/GPU/2011 EQ
20,00
Utilisateur
Système
44/54
Modèle d'Ising : et en Cuda ?
●
Quel passage de OpenCL vers Cuda ?
●
Quelles performances pour Cuda ?
Quadro 4000
OpenCL vers Cuda
●
●
Les mêmes concepts
Des noms différents
(find/replace) suffit !
●
En Python, moins d'1/2 j
GeForce 8600MGT
GeForce GT220
Type de GPU Nvidia
●
Tesla C1060
GeForce GT220
GeForce 8400GS
GeForce GT430
GeForce GTX260
NVS 3100M
GeForce GTX560Ti
0,00
100,00 200,00 300,00 400,00 500,00 600,00 700,00 800,00 900,00 1000,00
Durée en secondes
Réel
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
Utilisateur
Système
45/54
Modèle d'Ising :
Cuda meilleur que OpenCL ?
Résultats ambigus
●
Quadro 4000
Pour la meilleure :
Tesla C1060
●
●
Puissantes anciennes
●
●
Cuda
Peu puissantes :
●
●
OpenCL
Cuda
Quadro :
●
Rapport de durées Cuda/Nvidia
GeForce 8600MGT
GeForce GT220
GeForce GT220
GeForce 8400GS
GeForce GT430
GeForce GTX260
NVS 3100M
GeForce GTX560Ti
0
Cuda
Le 7 novembre 2011
0,2
0,4
0,6
0,8
1
1,2
1,4
1,6
1,8
2
Type de GPU Nvidia
Réel
Formation CIRA/GPU/2011 EQ
46/54
Modèle d'Ising : et les résultats ?
●
●
●
●
●
Un processus
aléatoire
Une bonne
superposition
Les + et puissants
Des résultats
cohérents
Une Tc ~ 2,3
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
47/54
Retour aux personnes
au-dessus de la ligne de flottaison
●
●
Pour les utilisateurs finaux de codes : EXE
●
Des versions GPU se développent (tout comme les tarifs)
●
ACEMD, Charmm, Gamess
●
Un « marché » dopé par la mode
Conseils : disposer de quelques éléments
●
un jeu de tests pertinent et portable (référence)
●
plusieurs architectures matérielles (Carte vidéo)
●
plusieurs implémentations logicielles (OS, pilote)
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
48/54
Retour aux personnes
« sur la ligne de flottaison »
●
●
Pour ceux du calcul scientifique qui compilent : SRC
●
« Free as a beer » : VMD, NAMD, ...
●
« Free as an idea » : Gromacs, BigDFT, Lammps, ...
●
Des librairies « métier » : OpenMM, PetSC
●
Des librairies « support » : CuBLAS, CuFFT, AMDAPP, Magma,
Conseils :
●
disposer de quelques éléments
–
–
–
–
Un jeu de tests pertinent et portable (référence)
Plusieurs environnements de développement (compilateurs)
Plusieurs implémentations logicielles (OS, pilote)
Plusieurs architectures matérielles (Carte vidéo)
●
Avoir une approche « intégrative »
●
Rester pragmatique (se fixer des objectifs raisonnables)...
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
49/54
Retour aux personnes
« à la ligne de flottaison »
●
Pour ceux du calcul scientifique qui programment : OSS
●
Des librairies en version GPU devenues courantes :
–
–
●
Des langages :
–
–
●
« métier » comme OpenMM,
« support » comme CuBLAS, APPAMD, Magma, CuFFT, CuSparse, ...
CUDA chez Nvidia
OpenCL chez Nvidia, AMD et Intel
Conseils :
●
Disposer de jeux de tests pertinents
●
Avoir une approche « intégrative ascendante » initiale
●
Utiliser systématiquement les directives
●
Analyser son code par des « profileurs » (gProf, Valgrind)
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
50/54
Retour aux personnes
« sous la ligne de flottaison »
●
Pour ceux qui démarrent de 0 : le « From Scratch »
●
Le retour d'un cadre : la localité CPU/mémoire
–
–
–
●
Des outils pour y arriver :
–
–
–
●
Il y a longtemps : tout à plat (un cœur, une mémoire)
Il y a peu de temps : plusieurs (cœurs|nœuds) : OpenMP, MPI
Maintenant : connaître l'architecture (plusieurs cœurs ou RAM)
WebCL pour appréhender les concepts du langage
Python OpenCL ou Cuda pour travailler sur les noyaux
Par4all et son « transformateur » de boucles pour le « générique »
Conseils :
●
Programmation plutôt « agile »
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
51/54
Trucs & Actuces
●
En GPU comme en Inde, attention aux « castes »
●
●
Toujours évaluer la pertinence de l'usage float/double
●
●
Toujours « caster » ses variables en I/O et dans les noyaux
Parfois, 32 bits suffisent amplement !
Le calcul scientifique, c'est de la « cuisine » !
●
La cuisine : le GPU, ses processeurs et sa mémoire privée
●
Plan de travail : mémoire locale, rapide et limitée
●
Placards : mémoire globale, « lente » (et aussi limitée)
●
... et utiliser le tout de la manière la plus efficace
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
52/54
Retour sur le précédent épilogue
●
●
3 activités du calcul scientifique et quelle utilisation des GPU ?
●
Visualisation : un acteur incontournable
●
Traitement de données : une alternative aux DSP
●
Simulation numérique : une utilisation sous haute surveillance
Et si finalement le GPU n'était qu'un
●
Calculateur spécialisé, avec une puissance colossale, mais...
–
–
●
Calculateur « analogique »
–
●
Des contraintes d'exploitation
Des domaines d'application spécifiques
Un retour aux « phénomènes » physiques, mais lesquels ?
Mais GPU devient GP GPU
(GP comme General Purpose, bientôt JeePU)
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
53/54
Conclusion
●
Des bonnes pratiques
●
Du code « générique »
–
–
●
●
des librairies éprouvées pour pérenniser l'ensemble
des directives pour permettre de rajouter d'autres technologies
Des tests (permanents, et ce n'est pas plus mal !)
Une période charnière passée (pour OpenCL) ? OUI !
●
De 2 à 5 acteurs (AMD, Nvidia, Intel, Nokia, Samsung)
●
Un développement pour le Web (WebCL)
●
Une généralisation de son usage dans les smartphones
Le 7 novembre 2011
Formation CIRA/GPU/2011 EQ
54/54