Notas para contenedor de docker:
Comando de docker para ejecución de la nota de forma local:
nota: cambiar <ruta a mi directorio>
por la ruta de directorio que se desea mapear a /datos
dentro del contenedor de docker.
docker run --rm -v <ruta a mi directorio>:/datos --name jupyterlab_r_kernel_openblas -p 8889:8888 -d palmoreck/jupyterlab_r_kernel_openblas:1.1.0
password para jupyterlab: qwerty
Detener el contenedor de docker:
docker stop jupyterlab_r_kernel_openblas
Al ejecutar el run
anterior se descargará la imagen y posteriormente se instalará OpenBLAS adaptado a su sistema. Esto tardará $10-15$ minutos aproximadamente. Pueden revisar de vez en vez con el commando:
docker logs jupyterlab_r_kernel_openblas
hasta que salga un mensaje del tipo: ...Installed kernelspec ir in /usr/local/share/jupyter/kernels/ir...The Jupyter Notebook is running at... y poder acceder al puerto 8888 de sus máquinas
Nota: Lo anterior se realizó de esta forma (construir una imagen de docker con software simple y posteriormente instalar el software especializado) pues si hubiera construído la imagen de docker adaptada a mi máquina, es muy probable que se tendría que haber adaptado nuevamente a sus máquinas. Ver: docker images with architecture-optimisation
Documentación de la imagen de docker palmoreck/jupyterlab_r_kernel_openblas:1.1.0
en liga.
In [1]:
install.packages("microbenchmark",lib="/usr/local/lib/R/site-library/",
repos="https://cran.itam.mx/",verbose=TRUE)
In [2]:
library(microbenchmark)
En Handle different versions of BLAS and LAPACK se explica que BLAS: Basic Linear Algebra Subprograms y Linear Algebra Package: LAPACK además de ser implementaciones, también son API* standard para operaciones básicas del álgebra lineal. Muchas implementaciones de la API existen. Un ejemplo de implementaciones son las incluidas al instalar R o Python. Otras son las que se pueden instalar vía línea de comando:
sudo apt-get install -y libblas3 libblas-dev liblapack3 liblapack-dev
en un sistema operativo Ubuntu por ejemplo. Ver libblas3 libblas-dev liblapack3 liblapack-dev.
*Ver Application Programming Interface: API para una explicación de lo que es una API.
Sin embargo existen otras implementaciones de la API que están optimizadas para la arquitectura de nuestras máquinas, por ejemplo:
Revisaremos en esta nota algunas comparaciones en tiempo de ejecución de la API de BLAS y LAPACK que viene integrada en R
vs la que provee OpenBLAS.
En la documentación de OpenBLAS podemos revisar la liga supported-cpus-and-operating-systems para conocer procesadores y sistemas operativos soportados. En específico, la instalación que se realiza con la imagen de docker detallada al inicio de la nota utiliza Precompiled installation packages.
Las siguientes mediciones fueron calculadas con un procesador: (hay que usar el kernel de Python3 para la siguiente línea)
In [1]:
%%bash
lscpu
En R
a diferencia de Python
podemos cambiar de implementación con las siguientes líneas de comando (hay que usar el kernel de Python3 para la siguiente línea):
In [2]:
%%bash
sudo update-alternatives --config libblas.so.3-x86_64-linux-gnu
In [3]:
%%bash
sudo update-alternatives --config liblapack.so.3-x86_64-linux-gnu
Entonces desde una terminal se ejecutan las líneas anteriores y elegimos la opción $1$ en ambas. Se obtendrá un output similar a:
update-alternatives: using /usr/lib/x86_64-linux-gnu/blas/libblas.so.3 to provide /usr/lib/x86_64-linux-gnu/libblas.so.3 (libblas.so.3-x86_64-linux-gnu) in manual mode
update-alternatives: using /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3 to provide /usr/lib/x86_64-linux-gnu/liblapack.so.3 (liblapack.so.3-x86_64-linux-gnu) in manual mode
para la primera y segunda línea respectivamente.
Comprobamos que estamos usando la implementación que está en la instalación de R
(hay que usar el kernel de R para la siguiente línea) con:
In [2]:
sessionInfo()
y hacemos algunas pruebas: no realizar los siguientes writes en máquinas con menos de 11gb
In [3]:
set.seed(2020)
m<-10**4
r<-10**4
A <- matrix(runif(m*r), m, r)
write(format(A,digits=16), "A_R.txt", ncolumns=r)
In [1]:
set.seed(2021)
r<-10**4
n<-10**4
B <- matrix(runif(r*n), r, n)
write(format(B,digits=16), "B_R.txt", ncolumns=n)
Mientras se ejecuta la siguiente celda se sugiere en la terminal ejecutar en la línea de comando htop
In [3]:
m<-10**4
r<-10**4
A<-scan("A_R.txt",what = numeric(0),sep='')
A_mat<-matrix(A,nrow=m,ncol=r,byrow=T)
In [4]:
rm(A)
Mientras se ejecuta la siguiente celda se sugiere en la terminal ejecutar en la línea de comando htop
In [5]:
r<-10**4
n<-10**4
B<-scan("B_R.txt",what = numeric(0),nmax=r*n,sep='')
B_mat<-matrix(B,nrow=r,ncol=n,byrow=T)
In [6]:
rm(B)
In [ ]:
mbk<-microbenchmark(
A_mat%*%B_mat,
times=2
)
después de $5$ min no terminó el proceso anterior...
Para el caso de OpenBLAS volvemos en la terminal a ejecutar las líneas de comando: (hay que usar el kernel de Python3 para la siguiente línea)
In [1]:
%%bash
sudo update-alternatives --config libblas.so.3-x86_64-linux-gnu
In [2]:
%%bash
sudo update-alternatives --config liblapack.so.3-x86_64-linux-gnu
Entonces desde una terminal se ejecutan las líneas anteriores y elegimos la opción $0$ en ambas.
Comprobamos que estamos usando la implementación que está en la instalación de R
(hay que usar el kernel de R para la siguiente línea) con:
In [3]:
sessionInfo()
y hacemos algunas pruebas: no realizar los siguientes writes en máquinas con menos de 11gb
In [3]:
set.seed(2020)
m<-10**4
r<-10**4
A <- matrix(runif(m*r), m, r)
write(format(A,digits=16), "A_R.txt", ncolumns=r)
In [1]:
set.seed(2021)
r<-10**4
n<-10**4
B <- matrix(runif(r*n), r, n)
write(format(B,digits=16), "B_R.txt", ncolumns=n)
Mientras se ejecuta la siguiente celda se sugiere en la terminal ejecutar en la línea de comando htop
In [4]:
m<-10**4
r<-10**4
A<-scan("A_R.txt",what = numeric(0),sep='')
A_mat<-matrix(A,nrow=m,ncol=r,byrow=T)
In [5]:
rm(A)
Mientras se ejecuta la siguiente celda se sugiere en la terminal ejecutar en la línea de comando htop
In [6]:
r<-10**4
n<-10**4
B<-scan("B_R.txt",what = numeric(0),nmax=r*n,sep='')
B_mat<-matrix(B,nrow=r,ncol=n,byrow=T)
In [7]:
rm(B)
Mientras se ejecuta la siguiente celda se sugiere en la terminal ejecutar en la línea de comando htop
In [10]:
mbk<-microbenchmark(
A_mat%*%B_mat,
times=2
)
In [11]:
print(mbk)
R
. De hecho la de R
no terminó después de $5$ min en la línea de microbenchmark
.Referencias:
Para referencias sobre el uso de BLAS y LAPACK con C ver:
Hay implementaciones en paralelo de BLAS para sistemas de memoria distribuida. Ver por ejemplo:
También NVIDIA tiene su propia implementación de BLAS para uso con GPU's: CUBLAS y su implementación de LAPACK: CUSOLVER. Para más sobre CUBLAS y CUSOLVER ver: C/extensiones_a_C/CUDA/CUBLAS y C/extensiones_a_C/CUDA/CUSOLVER/
Otras referencias para uso de GPU's con implementaciones de BLAS y LAPACK se encuentran:
MAGMA, MAGMA en NVIDIA, ver por ejemplo: Matrix computations on the GPU
Para otra implementación de BLAS y LAPACK ver: