Números aleatorios Clase 8, 4/5/2015 http://fsica.cab.cnea.gov.ar/gpgpu/index.php/en/icnpg/clases Un tour sobre tres herramientas C++ template library (parallel) Random Numbers Random123: a Library of Counter-Based Random Number Generators GPU y CPU multicore GPU y CPU multicore CUFFT Cual elegimos? Generar números aleatorios en paralelo "anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin" John von Neumann Generar números (pseudo)aleatorios en paralelo Muchos algoritmos que usan números aleatorios son muy paralelizables El problema es que usualmente necesitamos muchísimos, y garantizar que estos satisfagan ciertas condiciones … (batería de tests) Calculando usando números aleatorios 4 Azules/(Negros + Azules) → ? Calculando usando números aleatorios 1 Versión Serial while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi = 0.25*Azules/Totales 0 1 ¿ Que cuidados hay que tener con los RNs ? ¿ Versión Paralela ? ¿ Porque conviene ? ¿ Que cuidados hay que tener ? 4 Azules/(Negros + Azules) → Calculando usando números aleatorios ¿Versión Paralela? → M tiradores tiran N dardos ¿Porque conviene? → Debería ser como si un solo tirador tirara NxM ¿Que cuidados hay que tener? → que los tiradores y sus tiros sean descorrelacionados. Calculando usando números aleatorios Semilla[0], Semilla[1], Semilla[2], Semilla[3], Semilla[4], Semilla[5] Transformación while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[0] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[1] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[2] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[3] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[4] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[5] = 0.25*Azules/Totales Reducción Reducción: Pi = (Pi[0] + Pi[1] + Pi[2] + Pi[3] + Pi[4] + Pi[5])/6 Counter-based RNGs Parallel Random Numbers: As Easy as 1, 2, 3 John K. Salmon, Mark A. Moraes, Ron O. Dror, David E. Shaw “.. We demonstrate that independent, keyed transformations of counters produce a large alternative class of PRNGs with excellent statistical properties... are ideally suited to modern multicore CPUs, GPUs, clusters, and special-purpose hardware because they vectorize and parallelize well, and require little or no memory for state. ... All our PRNGs pass rigorous statistical tests and produce at least 2^64 unique parallel streams of random numbers, each with period 2^128 or more. In addition to essentially unlimited parallel scalability, our PRNGs offer excellent single-chip performance: Philox is faster than the CURAND library on a single NVIDIA GPU. http://www.thesalmons.org/john/random123/releases/1.06/docs/ [koltona@gpgpu-fisica examples]$ ls /share/apps/codigos/Random123-1.07/examples/ Cual elegimos? Calculando usando números aleatorios Semilla[0], Semilla[1], Semilla[2], Semilla[3], Semilla[4], Semilla[5] Transformación while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[0] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[1] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[2] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[3] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[4] = 0.25*Azules/Totales while(Totales < N) { x, y números random en [0,1] Azules += ((x*x + y*y) < 1) Totales ++; } Pi[5] = 0.25*Azules/Totales Reducción Reducción: Pi = Pi[0] + Pi[1] + Pi[2] + Pi[3] + Pi[4] + Pi[5] Hands-on "Hands-on" refers to human interaction, often with technology. It implies active participation in a direct and practical way. [koltona@gpgpu-fisica]$ cp -r /share/apps/codigos/alumnos_icnpg2015/Simple_Pi . [koltona@gpgpu-fisica]$ cd Simple_Pi/ [koltona@gpgpu-fisica Simple_Pi]$ ls [koltona@gpgpu-fisica Simple_Pi]$ make [koltona@gpgpu-fisica Simple_Pi]$ ls ¿ Que compila el make ? Hands-on Pi.cu struct estimate_pi{ __device__ float operator()(unsigned int thread_id){ RNG philox; RNG::ctr_type c={{}}; RNG::key_type k={{}}; RNG::ctr_type r; k[0]=thread_id; float sum = 0; unsigned int N = 10000; // muestras por thread for(unsigned int i = 0; i < N; ++i){ c[0]=i; r = philox(c, k); Una “key” distinta Para cada tirador Un “counter” distinto Para cada dardo del tirador float x=(u01_closed_closed_32_53(r[0])); float y=(u01_closed_closed_32_53(r[1])); float dist = sqrtf(x*x + y*y); // distancia al origen if(dist <= 1.0f) sum += 1.0f; } sum *= 4.0f; return sum / N; } }; Estimación de Pi del tirador Tira el dardo Hands-on Pi.cu struct estimate_pi{ __device__ float operator()(unsigned int thread_id){ RNG philox; RNG::ctr_type c={{}}; RNG::key_type k={{}}; RNG::ctr_type r; k[0]=thread_id; float sum = 0; unsigned int N = 10000; // muestras por thread for(unsigned int i = 0; i < N; ++i){ c[0]=i; r = philox(c, k); float x=(u01_closed_closed_32_53(r[0])); float y=(u01_closed_closed_32_53(r[1])); float dist = sqrtf(x*x + y*y); // distancia al origen Una “key” distinta Para cada tirador Un “counter” distinto Para cada dardo del tirador Tira el dardo if(dist <= 1.0f) sum += 1.0f; } sum *= 4.0f; return sum / N; } }; Estimación de Pi del tirador Hands-on struct estimate_pi{...} using namespace thrust; int main(void) { //uso 30K tiradores independientes, y cada uno tira 10K dardos int M = 30000; float estimate; estimate = transform_reduce( counting_iterator<int>(0), counting_iterator<int>(M), estimate_pi(), 0.0f, thrust::plus<float>() ); Pi.cu Una secuencia (implícita) de semillas 0,1,2,..., M-1 Qué se genera con cada semilla Valor inicial y operación de reducción estimate /= M; // 300K dardos tirados...(comparar tiempos con CPU) std::cout << "pi es aproximadamente " << estimate << std::endl; return 0; } Hands-on [koltona@gpgpu-fisica Simple_Pi]$ cat submit_gpu.sh [koltona@gpgpu-fisica Simple_Pi]$ qsub submit_gpu.sh [koltona@gpgpu-fisica Simple_Pi]$ cat submit_cpu.sh [koltona@gpgpu-fisica Simple_Pi]$ qsub submit_cpu.sh ¡Comparar resultados! Calculando usando números aleatorios Calculando usando números aleatorios transform N N CORES reduce semillas semillas N Estimaciones de pi + DRAM Estimaciones de Pi k CORES k+1 DRAM 1 HRAM Transform_reduce + implicit sequence Adaptado de suma de cuadrados de 1 k CORES k+1 DRAM HRAM
© Copyright 2024