38
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

Al borde de un ataque de Matlab… sálvame C++§ Fácil uso y con una sintaxis similar a Matlab. § Basada en templates y C++11. § Lambdas (transform, for_each, reduce) ... Evaluación

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Al borde de un ataque de Matlab… sálvame C++Francisco Javier García Blas

[email protected] Carlos III de Madrid

Grupo ARCOS2016

2

Matlab ’’

3

Introducción

§ ¿Qué es Matlab?, MATrix LABoratory

§ Es un lenguaje de programación (inicialmente escrito en C) para realizarcálculos numéricos con vectores y matrices. Como caso particular puede también trabajar con números escalares, tanto reales comocomplejos.

§ 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 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

Matlab es lento

9

Mito 2:Matlab es lento

10

Mito 3:Matlab es caro

11

12

Mito 3:Matlab es caro

13

§ 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

¿Qué SI nos gusta de Matlab?

14

§ 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.

¿Qué NO nos gusta de Matlab?

15

Sálvame C++

16

§ Eigen

§ Armadillo

§ ArrayFire

Alternativas a Matlab en C++

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.

http://arma.sourceforge.net/

#pragma omp parallel forfor (int i = 0; i < inda.n_elem; ++i) {slicevf_GM.at(inda(i)) = ODF(ODF.n_rows - 1 ,i);

} }

19

§ 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)

Asignatura/Tema

Operadores en Armadillo

20

Ejemplo: multiplicación de matrices

#include <iostream>#include <armadillo>

using namespace std;using namespace arma;

int main (int argc, char** argv){

mat A = randu<mat>(5000,5000);mat B = randu<mat>(5000,5000);mat C = A *B;return 0;

}

21

Ejemplo: Solver

#include <iostream>#include <armadillo>

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

g++ -o solver solver.cpp -larmadillo

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 Armadillofor 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) .*

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<T>(n_order,Reblurred_S); RL_factor = KernelT * (Signal % Ratio) / ((KernelT * Reblurred) +

std::numeric_limits<T>::epsilon()); fODF = fODFi % RL_factor; Reblurred = Kernel * fODF; Reblurred_S = (Signal % Reblurred) / sigma2; sigma2_i = (1.0/N) * sum( (pow(Signal,2) + pow(Reblurred,2))/2 - (sigma2 %

Reblurred_S) % Ratio , 0) / n_order; sigma2_i.transform( [](T val) { return std::min<T>(std::pow<T>(1.0/10.0,2),

std::max<T>(val, std::pow<T>(1.0/50.0,2))); } ); sigma2 = repmat(sigma2_i, N, 1);

}

MAT

LAB

Arm

adillo

24

§ 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)

¿Cómo puedo hacer para acelerar mi aplicación?

25

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

Configurando NVBLAS

%> LD_PRELOAD=LD_PRELOAD=/usr/local/cuda-7.5/lib64/libnvblas.so ./miapplicacion

26

§ 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

ArrayFire

https://github.com/arrayfire/arrayfire

27

Ejemplos básicos

array A = array(seq(1,9), 3, 3); af_print(A);

af_print(A(0)); // primer elementoaf_print(A(0,1)); // primera fila, segunda columna

af_print(A(end)); // último elementoaf_print(A(-1)); // último elemento (también)

af_print(A(1,span)); // segunda filaaf_print(A.row(end)); // última filaaf_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

#include <arrayfire.h>#include <stdio.h>#include <math.h>#include <cstdlib>

static af::array A;static void fn(){

af::array B = af::matmul(A,A);B.eval();

} int main(int argc, char ** argv){

double peak = 0;try {

int device = argc > 1 ? atoi(argv[1]) : 0;af::setDevice(device);af::info();

std::cout << “Benchmark N-by-N” << std::endl;

for (auto n = 128; n <= 2048; n += 128) {std::cout << n << “x” << n << “ ”;A = af::constant (1, n, n);double time = af::timeit(fn);double gflops = 2.0 * powf(n,3) / (time * 1e9);if (gflops > peak)

peak = gflops;

std::cout << gflops << “GF” << std::endl;}

} catch (af::exception & e) {std::cout << e.what() << std::endl;;throw;

}

std::cout << “## Max“ << peak << “ GFLOPS“ << std::endl;

return 0;}

Ejemplo

29

§ 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:

Gfor-loop

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

§ Ambos comparten el mismo layout de memoria (column-major).§ Es posible transferir datos de la clase Mat (Armadillo) a array

(ArrayFire).

ArrayFire + Armadillo

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:

§ Quirófano (operatorio).§ Procesamiento estadístico (clínico).

http://www.bitbucket.com/fjblas/phardi

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)

)

.)

*))

*.)

+))

+.)

,))

,.)

-))

����� ������� ������ ���� �1������� ����������%�������-)&

���� �1������������

%�������-)&

����#���������������%�������-)&

����#�������%����/0)&

�������"�� ���

�����

��%�������&

*))�!�� ���� �� *+0"*+0"/)� !�"���

������$ ����� ������$ �� ��� ��� ���$ ����� ��� ���$ �� ���

35

Evaluación (y III)

%

!

!%

"

"%

#

#%

"%& %!" !� "$ "� $' $� (& '�!(" !&�#'$

����� � �����

�����

���

������

��� ���� �����

��������� ������������ ����� ��� ��������� ����$ �

���� � ����

!

&!

"!!

"&!

#!!

#&!

$!!

$&!

#&' &"# "�!#% #�!%( %�!)' (�")# "'�$(%

�������� ����

�����

�����

�����

�������������

����������� ����������� ���������� �������������%!�

��� �� �����

36

Conclusiones

§ Es posible el despliegue de aplicaciones fuera del ámbito Matlab.§ Flexibilidad de desarrollo.§ Matlab como DSL.

37

Al borde de un ataque de Matlab… sálvame C++.

Francisco Javier García BlasUniversidad Carlos III de Madrid

Grupo ARCOS2016