test_gpu.py 2.37 KB
import numpy as np
import pyopencl as cl

a_np = np.random.rand(50000).astype(np.float32)
b_np = np.random.rand(50000).astype(np.float32)

ctx = cl.create_some_context()#C'est la "table de jeu". Permet aux devices de recevoir les kernels et de transferer les données
queue = cl.CommandQueue(ctx)#Permet de créer la queue de commandes dans le context

mf = cl.mem_flags #specifie comment la mémoire doit être gérée et utilisée
#print(mf.to_string(1))
a_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a_np)#espace de mémoire temporaire. Ce sera une allocation de mémoire sur un periph (gpu) pour stocker les données qui seront utilisées dans des calculs parallèles
b_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b_np)

#creation du programme
prg = cl.Program(ctx, """
__kernel void sum(
    __global const float *a_g, __global const float *b_g, __global float *res_g)
{
  int gid = get_global_id(0);
  res_g[gid] = a_g[gid] + b_g[gid];
}
""").build()

res_g = cl.Buffer(ctx, mf.WRITE_ONLY, a_np.nbytes)#Crée un buffer dans le contexte allouant de la mémoire sur le gpu pour stocker les resultats du calcul. Comme "WRITE-ONLY", il est destiné à stocker les données de sortie du noyau OpenCl
knl = prg.sum#On defini knl afin d'appeler le noyau sum du programme qu'on a créé précédement
knl(queue, a_np.shape, None, a_g, b_g, res_g)#execute le noyau sum sur le GPU à l'aide de la queue

res_np = np.empty_like(a_np)#Crée un tableau numpy de même dimension que a_np mais vide afin de stocker les résultats du calcul
cl.enqueue_copy(queue, res_np, res_g)#Copie les données depuis le buffer sur le petipherique (GPU) vers le tableau res_np

# Check on CPU with Numpy:
print(res_np - (a_np + b_np))#Permet de voir si les donées ont été exportées correctement dans le tableau res_np en checkant la difference entre le tableau et les deux variables du départ. Ca doit etre egal à 0.
print(np.linalg.norm(res_np - (a_np + b_np)))#Calcul la norme L2 de la difference entre res_np et (a_np + b_np). Si les deux vecteurs sont identique, ça devrait etre egal à 0. Ca nous donne une mesure de l'erreur entre les resultats du noyau OpenCl et les resultats attendus
assert np.allclose(res_np, a_np + b_np)#Compare les tableaux et verifie s'ils sont suffisament proches les uns des autres. S'ils le sont, le programme tourne normalement sinon, l'assertion renvoie un message d'echec.