Compilar waifu2x en Debian Stretch

[Advertencia:] Las instrucciones en este post no funcionan para tarjetas de video NVIDIA. Si tienes una tarjeta de video AMD, sigue leyendo.


Si la versión web de waifu2x no es suficiente para ti, puedes intentar compilar tu propia versión. En este post intentaré compilar uno de los forks de waifu2x para tarjetas de video AMD.

El repositorio oficial de waifu2x incluye código que está diseñado para funcionar usando la tecnología CUDA de NVIDIA, lo cual está indicado como un requisito, por lo que no puedo siquiera intentar compilar el código ya que tengo una vieja tarjeta de video AMD. Así que en lugar de usar el código original opté por uno de los forks que ofrecen soporte para tarjetas AMD, en particular el fork waifu2x-converter-cpp. Si eres usuario de Windows puedes bajar ejecutables precompilados desde la sección releases o puedes bajar waifu2x-caffe. En Linux, sin embargo, tenemos que compilar manualmente el código.

Después de descargar el código o clonar el repositorio de waifu2x-converter-cpp podemos instalar desde el gestor de paquetes el paquete clinfo para obtener información sobre OpenCL en nuestro sistema:

monstruosoft@debian:~$ clinfo 
Number of platforms                               0

Como podemos ver, el comando clinfo no detectó OpenCL en mi sistema, eso significa que no tengo instalados los paquetes para soporte de OpenCL. Desde el gestor de paquetes podemos instalar los paquetes mesa-opencl-icd y opencl-headers para instalar el soporte para OpenCL. Después de instalar estos paquetes, clinfo reporta lo siguiente en mi sistema:

monstruosoft@debian:~$  clinfo 
Number of platforms                               1
  Platform Name                                   Clover
  Platform Vendor                                 Mesa
  Platform Version                                OpenCL 1.1 Mesa 13.0.6
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_icd
  Platform Extensions function suffix             MESA

  Platform Name                                   Clover
Number of devices                                 1
  Device Name                                     AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)
  Device Vendor                                   AMD
  Device Vendor ID                                0x1002
  Device Version                                  OpenCL 1.1 Mesa 13.0.6
  Driver Version                                  13.0.6
  Device OpenCL C Version                         OpenCL C 1.1 
  Device Type                                     GPU
  Device Profile                                  FULL_PROFILE
  Max compute units                               2
  Max clock frequency                             650MHz
  Max work item dimensions                        3
  Max work item sizes                             256x256x256
  Max work group size                             256
  Preferred work group size multiple              32
  Preferred / native vector sizes                 
    char                                                16 / 16      
    short                                                8 / 8       
    int                                                  4 / 4       
    long                                                 2 / 2       
    half                                                 0 / 0        (n/a)
    float                                                4 / 4       
    double                                               0 / 0        (n/a)
  Half-precision Floating-point support           (n/a)
  Single-precision Floating-point support         (core)
    Denormals                                     No
    Infinity and NANs                             Yes
    Round to nearest                              Yes
    Round to zero                                 No
    Round to infinity                             No
    IEEE754-2008 fused multiply-add               No
    Support is emulated in software               No
    Correctly-rounded divide and sqrt operations  No
  Double-precision Floating-point support         (n/a)
  Address bits                                    32, Little-Endian
  Global memory size                              1073741824 (1024MiB)
  Error Correction support                        No
  Max memory allocation                           751619276 (716.8MiB)
  Unified memory for Host and Device              Yes
  Minimum alignment for any data type             128 bytes
  Alignment of base address                       1024 bits (128 bytes)
  Global Memory cache type                        None
  Image support                                   No
  Local memory type                               Local
  Local memory size                               32768 (32KiB)
  Max constant buffer size                        751619276 (716.8MiB)
  Max number of constant args                     13
  Max size of kernel argument                     1024
  Queue properties                                
    Out-of-order execution                        No
    Profiling                                     Yes
  Profiling timer resolution                      0ns
  Execution capabilities                          
    Run OpenCL kernels                            Yes
    Run native kernels                            No
  Device Available                                Yes
  Compiler Available                              Yes
  Device Extensions                               cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_byte_addressable_store

NULL platform behavior
  clGetPlatformInfo(NULL, CL_PLATFORM_NAME, ...)  Clover
  clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, ...)   Success [MESA]
  clCreateContext(NULL, ...) [default]            Success [MESA]
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_CPU)  No devices found in platform
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU)  Success (1)
    Platform Name                                 Clover
    Device Name                                   AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_ACCELERATOR)  No devices found in platform
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_CUSTOM)  No devices found in platform
  clCreateContextFromType(NULL, CL_DEVICE_TYPE_ALL)  Success (1)
    Platform Name                                 Clover
    Device Name                                   AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)

ICD loader properties
  ICD loader Name                                 OpenCL ICD Loader
  ICD loader Vendor                               OCL Icd free software
  ICD loader Version                              2.2.11
  ICD loader Profile                              OpenCL 2.1

Esto significa que el soporte para OpenCL está instalado.

waifu2x también requiere OpenCV. Para instalar OpenCV debemos instalar desde el gestor de paquetes el paquete libopencv-dev que instalará una lista de paquetes extra para el soporte de OpenCV. Una vez instalados los paquetes, podemos verificar que las librerías de desarrollo de OpenCV están instaladas usando pkg-config:

monstruosoft@debian:~$ pkg-config --modversion opencv 
2.4.9.1

Ahora podemos intentar continuar con el proceso de compilación de waifu2x. El primer problema que encontré fue la versión mínima requerida de CMake en el archivo CMakeLists.txt era la 3.8 pero la versión en Debian Stretch es la 3.7.2. Instalar CMake 3.8 es una opción pero primero intenté averiguar si era posible compilar con el software que viene en Debian Stretch haciendo los siguientes cambios sencillos al archivo CMakeLists.txt:

  • En primer lugar, obviamente, debemos cambiar la versión mínima de 3.8 a 3.7:

    cmake_minimum_required(VERSION 3.7)
  • El método find_package() de CMake no detectaba correctamente OpenCV en mi sistema así que lo cambié por el siempre confiable pkg-config. Para esto debemos agregar o cambiar en el archivo CMakeLists.txt las líneas marcadas en negrita a continuación:

    … 
    project(waifu2xcpp)
    include("CMakeDependentOption")
    include("CheckIncludeFileCXX")
    include(FindPkgConfig)
    
    … 
    add_executable(conv conv.c)
    if(UNIX)
    #	set(OPENCV_PREFIX "/usr" CACHE FILEPATH "OpenCV path")
    	pkg_check_modules(OPENCV opencv)
    	find_package(PkgConfig)
    	find_package(OpenCV)
    	if(${OPENCV_FOUND})
    		set(HAVE_OPENCV TRUE)
    		set(CMAKE_REQUIRED_INCLUDES ${OpenCV_INCLUDE_DIR})
    		include_directories(${OpenCV_INCLUDE_DIR})
    #		CHECK_INCLUDE_FILE_CXX("${OPENCV_PREFIX}/include/opencv2/opencv.hpp" HAVE_OPENCV)
    		if (HAVE_OPENCV)
    			link_directories(${OPENCV_LIBRARY_DIRS})
    		endif()
    	endif()
    …
  • Por último, el archivo CMakeLists.txt define el estandar C++17 como predeterminado pero esta es una opción de CMake 3.8 así que lo cambié por C++14 esperando que el código no hiciera uso de las características de C++17:

    … 
    if(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    	set(CMAKE_CXX_STANDARD 14)

Después de hacer estos cambios intenté compilar waifu2x usando los siguientes comandos:

monstruosoft@debian:~$ cd waifu2x-converter-cpp-master/
monstruosoft@debian:~/waifu2x-converter-cpp-master$ mkdir release
monstruosoft@debian:~/waifu2x-converter-cpp-master$ cd release/
monstruosoft@debian:~/waifu2x-converter-cpp-master/release$ cmake ..
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29") 
-- We are on: Linux (Linux)
-- Checking for module 'opencv'
--   Found opencv, version 2.4.9.1
CUDA_TOOLKIT_ROOT_DIR not found or specified
-- Could NOT find CUDA (missing:  CUDA_TOOLKIT_ROOT_DIR CUDA_NVCC_EXECUTABLE CUDA_INCLUDE_DIRS CUDA_CUDART_LIBRARY) 
-- CUDA not found. disabled.
-- Configuring done
-- Generating done
-- Build files have been written to: /home/monstruosoft/waifu2x-converter-cpp-master/release
monstruosoft@debian:~/waifu2x-converter-cpp-master/release$ make
Scanning dependencies of target conv
[  4%] Building C object CMakeFiles/conv.dir/conv.c.o
[  8%] Linking C executable conv
[  8%] Built target conv
Scanning dependencies of target gensrcs
[ 13%] Generating modelHandler_OpenCL.cl.h
[ 13%] Built target gensrcs
Scanning dependencies of target w2xc
[ 26%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler_fma.cpp.o
[ 26%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler_avx.cpp.o
[ 26%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler.cpp.o
[ 30%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler_sse.cpp.o
[ 34%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler_OpenCL.cpp.o
[ 39%] Building CXX object CMakeFiles/w2xc.dir/src/convertRoutine.cpp.o
[ 43%] Building CXX object CMakeFiles/w2xc.dir/src/threadPool.cpp.o
[ 47%] Building CXX object CMakeFiles/w2xc.dir/src/modelHandler_CUDA.cpp.o
[ 52%] Building CXX object CMakeFiles/w2xc.dir/src/w2xconv.cpp.o
[ 56%] Building CXX object CMakeFiles/w2xc.dir/src/common.cpp.o
[ 60%] Building CXX object CMakeFiles/w2xc.dir/src/cvwrap.cpp.o
[ 65%] Building CXX object CMakeFiles/w2xc.dir/src/Env.cpp.o
[ 69%] Building CXX object CMakeFiles/w2xc.dir/src/Buffer.cpp.o
[ 73%] Linking CXX shared library libw2xc.so
[ 73%] Built target w2xc
Scanning dependencies of target runtest
Scanning dependencies of target runbench
Scanning dependencies of target waifu2x-converter-cpp
[ 82%] Building C object CMakeFiles/runtest.dir/w32-apps/runtest.c.o
[ 82%] Building C object CMakeFiles/runbench.dir/w32-apps/runbench.c.o
[ 86%] Building CXX object CMakeFiles/waifu2x-converter-cpp.dir/src/main.cpp.o
[ 91%] Linking C executable runtest
[ 95%] Linking C executable runbench
[100%] Linking CXX executable waifu2x-converter-cpp
[100%] Built target runbench
[100%] Built target runtest
[100%] Built target waifu2x-converter-cpp
monstruosoft@debian:~/waifu2x-converter-cpp-master/release$ cp ../models_rgb/ . -r

El proceso de compilación no toma más de unos cuantos segundos y al terminar tendremos el archivo ejecutable waifu2x-converter-cpp así que es hora de probarlo:

monstruosoft@debian:~/waifu2x-converter-cpp-master/release$ ./waifu2x-converter-cpp --list-processor
   0: AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)(OpenCL    ): num_core=2
   1: Intel(R) Core(TM) i3 CPU         550  @ 3.20GHz(SSE3      ): num_core=4

Como puedes ver, en mi sistema, waifu2x detectó dos posibles modos de procesamiento, usando el CPU o usando el GPU.


[Advertencia:] Antes de continuar te recomiendo guardar todos los archivos que tengas abiertos en caso de que algo salga mal 😛 .


Es hora de probar nuestra versión de waifu2x:

monstruosoft@debian:~/waifu2x-converter/release$ ./waifu2x-converter-cpp -i archivo-a-convertir.jpg -o archivo-de-salida-de-waifu2x.png
CPU: Intel(R) Core(TM) i3 CPU         550  @ 3.20GHz
start process block (0,0) …
…
process successfully done! (all:30.7435[sec], 1 [files processed], 0 [files errored], 26.0731[GFLOPS], filter:26.6116[sec], 30.1213[GFLOPS])

Como puedes ver, waifu2x usa de forma predeterminada el método de procesamiento que cuenta con el mayor número de núcleos, en este caso mi CPU. Puedes forzar otro método de procesamiento desde la línea de comandos usando el argumento -p seguido del número del método de procesamiento deseado (nota que, en este caso, el número 0 corresponde a AMD CEDAR y el número 1 corresponde a Intel® Core i3 CPU):

monstruosoft@debian:~/waifu2x-converter/release$ ./waifu2x-converter-cpp --list-processor
   0: AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)(OpenCL    ): num_core=2
   1: Intel(R) Core(TM) i3 CPU         550  @ 3.20GHz(SSE3      ): num_core=4
monstruosoft@debian:~/waifu2x-converter/release$ ./waifu2x-converter-cpp -i archivo-a-convertir.jpg -o archivo-de-salida-de-waifu2x.png -p 0
Writing OpenCL-Binary to: /home/monstruosoft/waifu2x-converter/release/AMD_CEDAR_(DRM_2.49.0___4.9.0-4-amd64__LLVM_3.9.1).bin
OpenCL: AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)
start process block (0,0) …
…
process successfully done! (all:417.966[sec], 1 [files processed], 0 [files errored], 1.79946[GFLOPS], filter:406.796[sec], 1.84887[GFLOPS])

Algo salió mal 😦 . Al forzar el procesamiento en el GPU en mi sistema, procesar la imagen tomó mucho más tiempo 😦 . Puedes ver que el comando original usando el CPU tardó 30 segundos en procesar la imagen con un promedio de 30.1 GFLOPS. En cambio, ¡usando el GPU tardó 417 segundos! con un promedio de apenas 1.8 GFLOPS 😦 .

Puede haber muchas razones para este pésimo rendimiento usando el GPU: ¿tal vez necesito el AMD APP SDK como lo indica la página del fork de waifu2x? ¿o tal vez necesito la versión 3.3 de OpenCV como lo indica la misma página? ¿es posible que el pésimo rendimiento del GPU se deba a que estoy usando los drivers de video gratuitos en lugar de los drivers non-free? ¿o tal vez simplemente tengo una muy mala tarjeta de video 😛 ?.

Por el momento la versión usando el CPU es suficiente para mi, así que estas preguntas quedarán sin respuesta al menos hasta un próximo post. Si sigues estas instrucciones no olvides dejar un comentario indicando cual fue el resultado en tu caso.

Por último, cabe mencionar que en esta versión de waifu2x podemos indicar escalas mayores a 2x para el archivo de salida pero debes tener en cuenta que el tiempo de procesamiento se incrementa considerablemente entre mayor sea la escala del archivo de salida. Por ejemplo, convertir el archivo usando anteriormente toma 30 segundos para una escala de 2x pero convertir el mismo archivo con una escala de 3x toma 107 segundos:

monstruosoft@debian:~/waifu2x-converter/release$ ./waifu2x-converter-cpp --scale_ratio 3.0 -i archivo-a-convertir.jpg -o archivo-de-salida-de-waifu2x.png
CPU: Intel(R) Core(TM) i3 CPU         550  @ 3.20GHz
start process block (0,0) …
…
process successfully done! (all:107.091[sec], 1 [files processed], 0 [files errored], 29.3205[GFLOPS], filter:106.359[sec], 29.5222[GFLOPS])
SNAG-0002

Imagen original

SNAG-0002-ratio3

Imagen procesada con waifu2x a una escala de 3x

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s