Al borde de un ataque de Matlab… sálvame C++
Francisco Javier García Blas [email protected] Universidad Carlos III de Madrid Grupo ARCOS 2016 2
Matlab ’’ 3
Introducción
§ ¿Qué es Matlab?, MATrix LABoratory
§ Es un lenguaje de programación (inicialmente escrito en C) para realizar cálculos numéricos con vectores y matrices. Como caso particular puede también trabajar con números escalares, tanto reales como complejos.
§ Cuenta con paquetes de funciones especializadas. 4
Mito 1: Matlab es difícil 5
Google Trend
§ Gran comunidad de usuarios. § Usado en múltiples áreas de la ingeniería. 6
Mito 1: Matlab es difícil 7
Mito 2: Matlab es lento 8
Matlab es lento
§ Matlab utiliza Intel Matk Kernel Library (MKL)
§ Intel MKL incluye una nueva función de Descarga Automática (AO). § Multiprocesadores § Intel Xeon Phi de forma automática y transparente 9
Mito 2: Matlab es lento 10
Mito 3: Matlab es caro 11 12
Mito 3: Matlab es caro 13
¿Qué SI nos gusta de Matlab?
§ Prototipado rápido de aplicaciones § Soporte para desarrolladores § Representación sencilla de operaciones algebraicas § Interfaz gráfica (GUI) para depuración y desarrollo § Matlab Simulink § Programación paralela basada en maestro-esclavo (workers) § Parfor – Bucles paralelos § GPU 14
¿Qué NO nos gusta de Matlab?
§ Entorno cerrado de desarrollo (esclavos de Matlab). § Gestión de memoria. § El despliegue de aplicaciones es altamente dependiente. § Limitadas alternativas para la paralelización eficiente en memoria compartida. 15
Sálvame C++ 16
Alternativas a Matlab en C++
§ Eigen
§ Armadillo
§ ArrayFire 17
¿Qué es Armadillo?
§ Biblioteca de código libre para C++. § Fácil uso y con una sintaxis similar a Matlab. § Basada en templates y C++11. § Lambdas (transform, for_each, reduce) § Contenedores § Soporte para BLAS y LAPACK de forma adicional. § Representa tipos básicos para representación matemática: § Mat (2D) § Cube (3D) § Soporte para aceleración mediante tarjetas gráfica (GPU). § Proporciona vectorización automática SIMD (eg. SSE2). § CUIDADO: representación column-major. § Soporte para CMake
http://arma.sourceforge.net/ 18
¿Qué NO proporciona Armadillo?
§ Todo el conjunto de bibliotecas proporcionadas por Matlab. § Paralelización de operaciones sobre vectores.
#pragma omp parallel for for (int i = 0; i < inda.n_elem; ++i) { slicevf_GM.at(inda(i)) = ODF(ODF.n_rows - 1 ,i); } }
http://arma.sourceforge.net/ Asignatura/Tema 19
Operadores en Armadillo
§ Operadores sobrecargados para clases Mat, Col, Row y Cube § +: Suma de dos objetos.
§ -: Resta de un objeto de otro o negación de un objeto.
§ /: División de un objeto por otro objeto o un escalar.
§ * Multiplicación matricial de dos objetos; No aplicable a la clase Cube a menos que multiplique un cubo por un escalar.
§ %: Multiplicación por elementos de dos objetos.
§ ==: Evaluación de igualdad entre elementos de dos objetos; Genera una matriz de tipo umat con entradas que indican si en una posición dada los dos elementos de los dos objetos son iguales (1) o no iguales (0) 20
Ejemplo: multiplicación de matrices
#include
using namespace std; using namespace arma;
int main (int argc, char** argv) { mat A = randu
Ejemplo: Solver
g++ -o solver solver.cpp -larmadillo
#include
int main() { arma::vec b; b << 2.0 << 5.0 << 2.0;
arma::mat A; A << 1.0 << 2.0 << arma::endr << 2.0 << 3.0 << arma::endr << 1.0 << 3.0 << arma::endr;
std::cout << ”Solución a mínimos cuadrados: “ << std::end; std::cout << solve(A,b) << std::end;
return 0; }
3.0000 -0.3636 22
Ejemplo: Programación funcional
// Idiff(Idiff>1) = 1; // Idiff(Idiff<0) = 0; Idiff.elem( find(Idiff > 1.0) ).ones(); Idiff.elem( find(Idiff < 0.0) ).zeros(); 23
Matlab Vs Armadillo
for i = 1:Niter fODFi = fODF; Ratio = mBessel_ratio(n_order,Reblurred_S); RL_factor = KernelT * ( Signal .* (Ratio)) ./ (KernelT * (Reblurred)+ eps); fODF = fODFi .* RL_factor; Reblurred = Kernel * fODF; Reblurred_S = (Signal .* Reblurred) ./ sigma2; sigma2_i = (1/N) * sum( (Signal.^2 + Reblurred.^2)/2 - (sigma2 .* Reblurred_S) .*
MATLAB Ratio, 1)./n_order; sigma2_i = min((1/10)^2, max(sigma2_i,(1/50)^2)); sigma2 = repmat(sigma2_i,[N, 1]); end
for (auto i = 0; i < Niter; ++i) { fODFi = fODF; Ratio = mBessel_ratio
Armadillo Reblurred_S) % Ratio , 0) / n_order; sigma2_i.transform( [](T val) { return std::min
¿Cómo puedo hacer para acelerar mi aplicación?
§ Permite paralelización “casi” mágica de mi aplicación: § Mediante enlazado de bibliotecas comúnmente usadas: § Intel MKL (CPU) § OpenBLAS (CPU) § Atlas (CPU) § Magma (GPU) § …
§ NVidia permite la descarga (offloading) del cálculo matricial § cuBLAS: necesitamos trabajar con API (complejo) § NVBLAS: descarga automática (fácil) 25
Configurando NVBLAS
NVBLAS_LOGFILE nvblas.log
NVBLAS_CPU_BLAS_LIB libmkl_rt.so #NVBLAS_CPU_BLAS_LIB libopenblas.so
NVBLAS_GPU_LIST 0 #NVBLAS_GPU_LIST ALL
NVBLAS_TILE_DIM 2048
#NVBLAS_GPU_DISABLED_SGEMM #NVBLAS_GPU_DISABLED_DGEMM #NVBLAS_GPU_DISABLED_CGEMM #NVBLAS_GPU_DISABLED_ZGEMM
NVBLAS_CPU_RATIO_CGEMM 0.07
%> LD_PRELOAD=LD_PRELOAD=/usr/local/cuda-7.5/lib64/libnvblas.so ./miapplicacion 26
ArrayFire
§ Programación orientada a dispositivos § Basado en la clase array § Limitado a datos en 1D/2D/3D § Open source § Neutral § Nvidia § AMD (OpenCL) § CPU (CUDA) § Múltiples funcionalidades § Soporte para CMake
https://github.com/arrayfire/arrayfire 27
Ejemplos básicos
arrayA = array(seq(1,9), 3, 3); af_print(A);
af_print(A(0)); // primer elemento af_print(A(0,1)); // primera fila, segunda columna
af_print(A(end)); // último elemento af_print(A(-1)); // último elemento (también)
af_print(A(1,span)); // segunda fila af_print(A.row(end)); // última fila af_print(A.cols(1,end)); // todo menos la segunda fila
float b_host[] = {0,1,2,3,4,5,6,7,8,9}; array b(10, 1, b_host); af_print(b(seq(3))); af_print(b(seq(1,7))); af_print(b(seq(1,7,2))); af_print(b(seq(0,end,2))); 28
Ejemplo
#include
Gfor-loop
§ La construcción gfor-loop puede utilizarse para iniciar simultáneamente todas las iteraciones de un bucle for de la GPU o dispositivo. § siempre y cuando las iteraciones sean independientes.
§ gfor-loop se realiza cada iteración al mismo tiempo (en paralelo).
§ Tamaño del intervalo limitado.
§ FFT a cada rodaja de un volumen:
for (auto i = 0; i < N; ++i) A(span,span,i) = fft2(A(span,span,i)); // Secuencial
gfor (seq i, N) A(span,span,i) = fft2(A(span,span,i)); // Paralelo 30
ArrayFire + Armadillo
§ Ambos comparten el mismo layout de memoria (column-major). § Es posible transferir datos de la clase Mat (Armadillo) a array (ArrayFire).
af::array mat_gpu = af::array(filas, columnas, mat_cpu.memptr());
…
mat_gpu.host(mat_cpu.memptr()); 31
Caso de uso: pHARDI
§ Identificación de fibras nerviosas para estudiar el grado de conectividad de las distintas áreas del cerebro. § Rendimiento: pseudo-tiempo real: http://www.bitbucket.com/fjblas/phardi § Quirófano (operatorio). § Procesamiento estadístico (clínico). 32 33
Evaluación (I)
§Intel Xeon E5-2630 v3 § 8 núcleos § 2.40 GHz, § 128 GB RAM §Ubuntu 14.04 x64 §CUDA versión 7.5. §Compiladores § GCC 5.1 § Flags –O3 y –DNDEBUG §Nvidia Tesla K40 §GTX 680 34
Evaluación (II)