Upload
others
View
42
Download
0
Embed Size (px)
Citation preview
Python + CUDA = PyCUDA
Clase 15, 01/06/2015http://fisica.cab.cnea.gov.ar/gpgpu/index.php/en/icnpg/clases
cp -a /share/apps/codigos/alumnos_icnpg2015/pycuda .
http://bit.ly/1PZTg1B
¿ Qué es Python?
● Lenguaje multipropósito (Web, GUI, Scripting, cintífico).
● Orientado a Objetos.
● Interpretado.
● Producido para tener alta legibilidad y alta productividad.
Características:
● Todo en python es un objeto (de verdad, TODO).
● Shell interactiva.
● Multiplataforma.
● Varias implementaciones: CPython, Jython, PyPy.
● Incluye baterías.
Herramientas:
● Python tiene una de las comunidades de desarrolladores más grandes. Hay herramientas para casi todo.
● Desarrollo web: Django.
● Bibliotecas gráficas: wxPython, PyQt, PyOpenGL.
● Bases de datos: PyMySQL, pyodbc, ect.
● Cálculo científico: scipy, numpy, matplotlib, scikts.
● Cálculo paralelo: PyOpenCL, PyCUDA, scikts.cuda.
Interpretado vs. compilado
Edición
Compilación
Linkedición
Ejecución
Flujo de creación de un programa en C/Fortran:
Sintaxis
● Podemos trabajar en consola (en linux ya está instalado, simplemente escribir python) o bien en un script:
>>> print “Hola inmundo!”
● No hay que usar llaves, ni “;”. Los bloques se definen por indentación:
a = 3b = "hola manola"
if a == 3 and "manola" in b: # esto es un comentario
print b c = a*5else: b = "hola manola"
c = a/3.0
# esto ya esta afuera del if/elsed = "hola manola"
Tipos de datos
# stringsname = "Nicolas"
# multi-line stringbio = '''Mi nombre es Nicolás naci en Rafaela, Santa Fe'''
# another multi-line stringquote = """Sombondrolo la cantarpioaea - N.R."""
#enterosyear = 2015year = int("2015")
# floatspi = 3.14159265pi = float("3.14159265")
#listaslista1 = [] lista2 = [1,2,3,4,5,6,7,8,9,10]lista3 = ["hola","manola","pepe"]lista4 = [1, "hola", lista1, lista3]
# diccionariosperson = {}person['nicolas'] = 'Ingeniero'person.update({'favoritos':['Cortazar', 'Pink Floyd', 'Dolina'], 'genero':'male',})person[55] = 'numero'
# Nulldata = None
#tuplas (datos inmutables)a = (123,"hola") a[0] = "chau" ----> Error!
#booleanosthis_is_true = Truethis_is_also_true = bool("any object")this_is_false = False or 0 or "" or [] or {} or None
Ej: tipos.py
Algo de magia - Strings
animales = "liebre " + "perro "animales +="gato "#animales = "liebre perro gato"
animales = ", ".join(["liebre","perro", "gato"])# animales = liebre, perro, gato
fecha = "%d de %s, %d" % (1, 'Junio', 2015)# 1 de Junio, 2015
fecha = "%(nombre)s %(apellido)s" %{'nombre':'Nicolas', 'apellido':'Chiaraviglio'}# Nicolas Chiaraviglio
print 2 * "hola "# hola hola
Algo de magia - Iteradores
from random import randint
a = [randint(0,121) for i in range(0,1000)]
b = [i for i in a if not i%2]
b = [k**2 - j for j,k in enumerate(a) if not k%2 and j%2]
Algo de magia - Listas
for x in range(0,10): print x# 0 1 2 3 4 5 6 7 8 9
frutas = ['manzana', 'banana', 'pera', 'frutilla', 'vino tinto']for fr in fruta: print fr# manzana banana pera frutilla vino tinto
num = [1,2,3,4,5]for i,fr in zip(num,frutas): print i, fr# 1 manzana 2 banana 3 pera 4 frutilla 5 vino tinto
for i,fr in enumerate(frutas): print i, fr# 0 manzana 1 banana 2 pera 3 frutilla 4 vino tinto
Ej: iteradoresListas.py
También: funciones, generadores, clases
def fibonacci(n = 3): resultado =[]
a,b = 0,1
for i in range(0,n):
resultado.append(a)
a,b = b, a + b
return resultado
print fibonacci(10)# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print fibonacci()# [0, 1, 1]
def fibonacci(n): a,b = 0,1
while True:
yield a
a,b = b, a + b
generador = fibonacci()for i in range(0,10): print generador.next()# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
Ej: funcGeneradores.py
Numpy - Python para cálculo numérico
● Soporte de operaciones que actúan sobre arrays N-dimensionales (eficiencia).
● Herramientas para integración con C/C++ y Fortran.
● Funciones de álgebra lineal: Transformadas, integrales, números aleatorios.
● También incluye baterías
A los bifes:
● Definiciones: Vectores, Matrices, Tipos
● Operaciones entre vectores/matrices
● Sistemas de ecuaciones
● Reshape
● Broadcast
Demo: demoNumpy.py
Entonces... PyCUDA?
●PyCuda permite acceder al API de Cuda desde Python.
Pero... y la performance?
Manipulación de datosFlujo general del programa
Cálculo
I/O
Python Cuda
“Scripting for the brain, GPUs for inner loop”Klöckner
Flujo de trabajo de PyCUDA
Edición
Ejecución
Cache?
nvcc .cubin
Envío a GPU
Ejecución en GPU
Source Module (“...”)
no
Algunos ejemplos
import pycuda.driver as cudaimport pycuda.autoinit, pycuda.compilerimport numpy as np
a = np.random.randn(4,4).astype(np.float32)a_gpu = cuda.mem_alloc(a.nbytes)cuda.memcpy_htod(a_gpu,a)
mod = pycuda.compiler.SourceModule(""" __global__ void twice (float *a) { int tid = threadIdx.x + threadIdx.y * 4; a[tid] *= 2; } """)
func = mod.get_function("twice")func(a_gpu, block=(4,4,1))
a_doubled = np.empty_like(a)cuda.memcpy_dtoh(a_doubled,a_gpu)print a_doubledprint a
#include <stdlib.h>#include <stdio.h>#include <time.h>
__global__ void twice (float *a){ int tid = threadIdx.x + threadIdx.y * 4; a[tid] *= 2;}
int main( int argc, const char** argv ) { int N = 4; float *a, gpu_a*, *a_doubled;
a = (float *)malloc(sizeof(float) * N); a_doubled = (float *)malloc(sizeof(float) * N); cudaMalloc((void**)&gpu_a, sizeof(float) * N); srand(time(NULL)); for (int i = 0; i < N; i++) a[i] = random()/RAND_MAX; cudaMemcpy(gpu_a, a, sizeof(float) * N, cudaMemcpyHostToDevice); dim3 blockDim(N,N,1); dim3 gridDim(1,1,1); twice<<<gridDim,blockDim>>>(a); cudaMemcpy(a_doubled, gpu_a, sizeof(float) * N, cudaMemcpyHostToDevice);
for (int i = 0; i < N; i++) printf("%f\t",a_doubled[i]); for (int i = 0; i < N; i++) printf("%f\t",a[i]); return 0;}
Ejs: twice.cu - twice.py
Todavía escribimos mucho?- gpuarray
import numpyimport pycuda.autoinitimport pycuda.gpuarray as gpuarray
x = np.random.randn(4,4).astype(np.float32)a_gpu = gpuarray.to_gpu(x)
a_doubled = (2*a_gpu).get()print a_doubledprint a_gpu
Ej: twice2.py
Y algo más complicado?
from pycuda.curandom import rand as curand
a_gpu = curand((50,))b_gpu = curand((50,))
from pycuda.elementwise import ElementwiseKernellin_comb = ElementwiseKernel( " float a, float *x, float b, float *y, float *z", " z[i] = a * x[i] + b * y[i]")
c_gpu = gpuarray.empty_like(a_gpu)lin_comb(5, a_gpu, 6, b_gpu, c_gpu)
assert la.norm((c_gpu - (5 * a_gpu + 6 * b_gpu)).get()) < 1e-5
Ej: element.py
import numpy as npimport pycuda.autoinitimport pycuda.gpuarray as gpuarrayfrom pycuda.curandom import rand as curandfrom pycuda.reduction import ReductionKernel
dot = ReductionKernel(dtype_out = np.float32, neutral ="0", reduce_expr = "a+b", map_expr = "x[i] * y[i]",
arguments = "const float *x, const float *y")
x = curand((1000*1000), dtype = np.float32)y = curand((1000*1000), dtype = np.float32)
x_dot_y = dot(x,y).get()x_dor_y_cpu = np.dot(x.get(), y.get())
Ej: Reductions.py
Esta Charla
● Empresas que usan Python - http://bit.ly/1AvYbR2 ● Introducción a Python - http://bit.ly/1AvYo6V● Estructuras de datos en Python - http://bit.ly/1jPmL3p● Guía de Numpy/Scipy - http://bit.ly/1GGwAO2● Documentación PyCUDA - http://bit.ly/1J8SLMZ● Charla de A. Klöckner
sobre PyCUDA/PyOpenCL - http://bit.ly/1J8SLMZ● Repositorio de PyCUDA - http://bit.ly/1LLArt1● Guía de instalación de PyCUDA - http://bit.ly/1dzM6jH