Al borde de un ataque de Matlab… sálvame C++Francisco Javier García Blas
[email protected] Carlos III de Madrid
Grupo ARCOS2016
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.
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
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?
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
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.