Documente Academic
Documente Profesional
Documente Cultură
Programación Paralela
Localización y detección de objetos en tiempo real
Índice
Índice 1
Abstract 3
Introducción 4
Motivación 4
Objetivo 7
Alcances 7
Hipotesis 7
Patentes 7
Investigación 9
Algoritmo elegido 12
Metodología implementada 12
GPU 12
Cámara web 13
Código fuente 13
Resultados obtenidos 17
Conclusiones 19
Fortalezas 19
Debilidades 19
Diccionario 20
Adas 20
Cuda 21
GPU 21
Nvidia 21
OpcnCV 21
Bibliografía 22
im2col_kernels.cu 24
activation_kernels.cu 25
convolutional_kernels.cu 27
Martínez, Rodríguez 3
Abstract
Las tecnologías de asistencia en la conducción permiten reducir el margen de error en la toma de
decisiones ante una situación de emergencia que ponga en riesgo la seguridad de una o más
personas dentro o fuera de un vehículo. Es por eso que se están haciendo grandes esfuerzos en
mejorar dichas tecnologías o agregar nuevas funcionalidades en las existentes que ayuden a reducir
las tasas de accidentes de tránsito en el mundo. Pero para lograr este objetivo de manera eficiente y
en tiempo real, se requiere una gran capacidad de cómputo debido a la gran cantidad de información
que tienen que analizar estos sistemas para decidir ejecutar alguna acción o no. Una alternativa para
ello es la programación paralela, la cual se basa en el uso de GPUs. Nvidia, es una compañía que
desarrolla el ecosistema tecnológico que se puede utilizar para este fin. El resultado deseado de esta
combinación de tecnologías es la seguridad a la hora de conducir eliminando el error humano.
Martínez, Rodríguez 4
Introducción
Actualmente, los sistemas de asistencia de conducción avanzados (ADAS por sus siglas en inglés)
están adquiriendo cada vez más relevancia en la fabricación de vehículos, especialmente en áreas
donde la seguridad es crítica. Ha habido mejoras significativas en el desarrollo de sensores, radares y
sistemas de visión por computadora para determinar la distancia a otros vehículos u objetos así como
mejorar el campo de visión para alertar a los conductores sobre riesgos potenciales que pueden
poner en peligro la vida o integridad física de las personas dentro o fuera del vehículo. Sin embargo,
estos sistemas, en especial los sistemas de visión por computadora, requieren de un procesamiento
de cómputo elevado para poder manejar imágenes en tiempo real.
La computación en paralelo (GPUs) sirve para realizar tareas que necesitan velocidad y uno de
los requisitos es procesar varios cálculos al mismo tiempo. La diferencia de entre esta tecnología y
una CPU es que una GPU es capaz de procesar muchas tareas al mismo tiempo, mientras que la
CPU la forma en que lo realiza es sequencial. ¿Como? La GPU está compuesta por cientos de
procesadores que lo permiten de manera eficiente.
Vehículo autónomo
Para reducir el error humano a la hora de conducir, se ha desarrollado el concepto de vehículo
autónomo (Salaman, 2017). Existen dos tipos de carros autónomos: los semi-autonomos y los
autónomos. Los carros autónomos son completamente manejados a través de sistemas, sensores y
algoritmos mientras que los semi, son los que incluyen sistemas de apoyo al conductor. (Business
insider, 2017). Se utiliza el machine learning para las aplicaciones de manejo autónomo, aprenden a
través de la información que entra por sensores y cámaras, es decir aprendizaje por imitación.
(Innocenti, Linden, Panahandeh, Sevensson, Mohammadiha, 2017)
Motivación
Recientes avances en tecnología han permitido que emerjan soluciones disruptivas en una gran
cantidad de áreas donde había habido un crecimiento lento en décadas anteriores. Este es el caso de
la movilidad urbana, donde algunos de los objetivos incluyen mejorar los servicios de transporte
público y reducir el uso del carro para bajar las emisiones de CO2, reducir los embotellamientos y
minimizar los accidentes de tránsito. Sin embargo, los beneficios de estas tecnologías están lejos de
ser una realidad, especialmente en países de desarrollo donde la flota vehicular continúa en
crecimiento, al igual que los accidentes de tránsito. De acuerdo a la Organización Mundial de la Salud
(OMS), cerca de 1.25 millones de personas mueren cada año como resultado de un choques en la
Martínez, Rodríguez 5
carretera y entre 20 y 50 millones de gente sufre de lesiones no fatales, muchos de ellos incurriendo
en una discapacidad como resultado de dicha lesión. Por esta razón, los accidentes de tráfico
representan la novena causa de muerte en el mundo y la primera causa entre gente entre 15-29 años
de edad (ver figura 1).
Figura 1
Figura 1. Estadísticas globales de muertes relacionadas con accidentes de tráfico. A la izquierda, el número de muertes en el
mundo por accidentes en carreteras, 2013. A la izquierda, el top ten de las causas de muertes en gente entre 15-29 años de
edad, información de 2012. Recuperado el 10 de octubre de 2017 del reporte WHO Global Status Report on Road Safety 2015.
En México, la situación no es muy distinta, 44% de los accidentes son accidentes de tráfico y
alrededor de 15,000 personas mueren cada año como consecuencia de ello. Además, es importante
mencionar que más del 80% de estos accidentes fueron generados en colisiones vehículo a vehículo
donde 9 de 10 fueron responsabilidad del conductor.
En México, la situación no es muy distinta, 44% de los accidentes son accidentes de tráfico y
alrededor de 15,000 personas mueren cada año como consecuencia de ello. Además, es importante
mencionar que más del 80% de estos accidentes fueron generados en colisiones vehículo a vehículo
donde 9 de 10 fueron responsabilidad del conductor (ver figura 2).
Martínez, Rodríguez 6
Figura 2. Reporte de accidentes de tránsito en México para el periodo de 2010-2015. La mayoría (69%) de los accidentes se
generan por colisiones vehículo a vehículo. Recuperado el 11 de octubre de 2017 del portal del INEGI.
Mientras que el uso de ADAS se espera pueda asistir a los conductores en más y más sofisticadas
formas al proveer información acerca de las condiciones o el ambiente de conducción para tratar de
minimizar los accidentes de tránsito, aún se requiere enfocar esfuerzos en el desarrollo de algoritmos
más rápidos y eficientes para dicho propósito.
Martínez, Rodríguez 7
Objetivo
El objetivo de este proyecto es implementar un sistema ADAS por medio de un algoritmo “state of
the art” para reconocimiento y ubicación de objetos utilizando una GPU y una cámara de uso
comercial.
Alcances
Para esta investigación se tiene como propósito encontrar un algoritmo ya existente que más se
acerque a resolver el problema que nos estamos planteando que fuera como nuestra base, de ahí
modificar lo que fuera necesario. En este caso se encontró un algoritmo muy utilizado en las
aplicaciones de detección de objetos en tiempo real.
Hipotesis
Patentes
El 13 de julio del 2011, google ingresa la solicitud de patente con número US 8,195,394B1 de
nombre “OBJECT DETECTION AND CLASSIFICATION FOR AUTONOMOUS VEHICLES”, misma
que fue aprobada el 5 de junio del 2012, con el objetivo de generar un sistema ADAS para que un
vehículo autónomo sea capaz de detectar los objetos dentro de su área de visión. De esta manera, se
podrían tomar decisiones de acuerdo al objeto en cuestión, ya sea esquivarlo, disminuir la velocidad o
detener el automóvil por completo.
Martínez, Rodríguez 8
Figura 3.1
La figura 3.1, ilustra el flujo de decisión con el que se construiría el algoritmo para el vehículo
autónomo de google. Desde que ingresa la información del objeto a través de los sensores, se
identifica qué es en caso de estar a una distancia lo suficientemente cercana, de lo contrario solo
identifica el lugar en el que está. El alcance de esta patente no llega a que el algoritmo tome una
decisión de acuerdo al objeto identificado.
Figura 3.2
Martínez, Rodríguez 9
La figura 3.2 demuestra algunos de los objetos que podría detectar el vehículo. Los
señalamientos, las características de la calle, los peatones y cualquier objeto que pudiera
interponerse en el camino del mismo.
La invención que aclama google acerca de la patente es que se se identificará el objeto y todos
sus detalles como su posición en cuanto al campo de visión, así como el área geográfica que lo
rodea. Esta información la podrá comunicar el vehículo con los demás sensores y equipo de cómputo
del vehículo podrá tomar una decisión en cuanto a la dirección y velocidad. Será también capaz de
detallarla en diferentes pantallas de manera más visual.
Investigación
Como aplicaciones, también existen en el mercado diferentes algoritmos que funcionan como
ADAS que al igual que la detección de objetos utiliza la visión computacional. De parte de la
tecnología de NVIDIA, existe un hardware hecho para la detección de los carriles para los coches
autónomos. En la figura 3, se puede observar que información necesita recolectar para funcionar. Las
tres cámaras detectan todo el campo de visión del conductor, evitando cualquier punto ciego, toma en
cuenta cuál es pa posición del volante para predecir cualquier cambio de dirección y finalmente un
disco duro de estado sólido para guardar todos los datos generados y comparar en la información
obtenida en tiempo-real y poder compararla con el histórico. El resultado de este sistema, es un
control total del manejo del vehículo.
Figura 3
Para llegar al punto de saber si el coche se encuentra en el carril correcto y antes de que se
empiece realmente a manejar el cómputo en paralelo, este sistema se necesita entrenar. En la figura
4 se muestra en el diagrama como entro la información, y qué comandos se utilizaron en el volante
para generar datos de comportamiento.
Martínez, Rodríguez 10
Figura 4
El algoritmo que se eligió para la detección de objetos tendría un diagrama similar, con la
diferencia que se utilizó solamente una cámara y no tres para cuestiones de prueba. En cuanto a
sensores externos, no se utilizó ninguno. La figura 5 representa un diagrama más acercado a la forma
en el que se entrenó nuestro sistema, a pesar de que no era el mismo objetivo.
Figura 5
La figura 5 describe cómo hicieron para entrenar la generación de comandos de dirección para
que el vehículo viaje de manera autónoma. La información entra por la cámara central para ser
evaluada por la red neuronal y genere un comando de conducción. Como conclusión a esta
investigación, se demostró que este sistema ADAS, es capaz de aprender a seguir dentro del mismo
carril teniendo total control sobre las decisiones de cambio de ruta y dirección. Para que sea un
algoritmo mucho más robusto necesita de más sesiones de entrenamiento.
Se encontró otro paper similar, “Imitation Learning for Vision-based Lane Keeping Assistance”, en
el que se utiliza tecnología de NVIDIA igualmente para un algoritmo ADAS para que el vehículo
reconozca el carril en el que se encuentra y el evitar los cambios bruscos de dirección. Este como el
anterior, utiliza redes neuronales tanto como para aprender como para hacerlo de manera autónoma.
Pero a diferencia del paper anterior, en este se basó más en modelos matemáticos para calcular los
ángulos en los que se mueve la dirección del carro. Es capaz de aprender y clonar el comportamiento
del vehículo y el modo en el que hace el trayecto.
Martínez, Rodríguez 11
Figura 6
Figura 7
Martínez, Rodríguez 12
Algoritmo elegido
Se eligió un algoritmo basado en Redes Neuronales Convolucionales llamado YOLO que aplica
una sola red neuronal a la imagen completa. Esta red divide la imagen en regiones y predice cuadros
delimitadores del objeto basándose en las probabilidades calculadas para cada región. La red corre a
45 fps (frames por segundo) sin procesamiento de batch en una GPU Titan X y puede correr hasta
150 fps en una versión más rápida. Esto significa que puede procesar video en tiempo real con
menos de 25ms de latencia. Además, alcanza más del doble de la precisión promedio de otros
sistemas en tiempo real.
Metodología implementada
GPU
Para la implementación del algoritmo seleccionado se utilizó una GPU Geforce 820m de NVidia
montada sobre una Laptop Asus X455L, la cual cuenta con las siguientes características:
Cámara web
Para transmitir video en tiempo real, se utilizó una cámara web QuickCam Orbit AF de la marca
Logithech (ver figura X).
Figura X. Cámara web utilizada para la obtención de video en tiempo real para la aplicación de detección de objetos.
Martínez, Rodríguez 14
Código fuente
El código utilizado fue YOLO (Revisar anexo 1), un algoritmo de detección de objetos que puede
ser implementado en cualquier lenguaje. En este caso se implementó en C, para realizarlo en
paralelo. Utiliza una red neuronal que analiza la imagen completa para dividirla en regiones las cuales
de vuelven los cuadros de predicción a las que al final se les agrega un porcentaje de acierto.
Antes de realizar cualquier modificación se corrió el programa en dos versiones: la primera fue
utilizando el CPU, la segunda con los GPUS
Figura 8.1
Figura 8.2
En la figura 8.1 se puede observar que detectar una imagen estática sencilla se tarda 13.69
segundos, mientras que la figura 8.2 demuestra que esa misma tarea la realiza en menos de un
segundo. Es decir, es 16 veces más rápido.
Figura 8.3
Martínez, Rodríguez 15
En la figura 8.3 se puede observar el resultado que da, el algoritmo de detección de objetos que
se encontró.
Figura 8.4
En la figura 8.3 se puede observar de manera gráfica, cómo funciona el algoritmo y cómo detecta
el objeto en la imagen. Se utiliza una red neuronal que analiza toda la imagen generando áreas de
detección. En la figura 8.4 se muestra como se ve todo el programa original al correrse utilizando los
GPUS.
Figura 8.4
Martínez, Rodríguez 16
Este modelo, a diferencia de los papers encontrados, no se entrenó de manera personal, es decir,
estaba ya previamente entrenado. Se utilizó el modelo Darknet entrenado a partir del algoritmo
YOLO.
Para agregar al resultado del algoritmo, la ubicación de los objetos, se necesitaron realizar ciertos
cambios en el código.
/* Se genera una variable en la que se agregaran las coordenadas del objeto */
char *imLabel = malloc(strlen(names[class]) + strlen(" x:") + strlen(tmpBuffx) +
strlen(" y:") + strlen(tmpBuffy) + 1);
sprintf(tmpBuffx, "%.1f", b.x);
sprintf(tmpBuffy, "%.1f", b.y);
/* El nombre de la clase y las coordenadas del objeto se almacenan en imLabel */
strcpy(imLabel, names[class]);
/* Coordenada x */
strcat(imLabel, " x:");
strcat(imLabel, tmpBuffx);
/* Coordenada y */
strcat(imLabel, " y:");
strcat(imLabel, tmpBuffy);
/* ========= added on 3-nov-17 by ARG & EMM ============= */
/* Se manda a imprimir la etiqueta imLabel en el cuadro del objeto detectado */
image label = get_label(alphabet, imLabel, (im.h*.03)/10);
draw_label(im, top + width, left, label, rgb);
free_image(label);
free(imLabel);
}
Martínez, Rodríguez 17
if (masks){
image mask = float_to_image(14, 14, 1, masks[i]);
image resized_mask = resize_image(mask, b.w*im.w, b.h*im.h);
image tmask = threshold_image(resized_mask, .5);
embed_image(tmask, im, left, top);
free_image(mask);
free_image(resized_mask);
free_image(tmask);
}
Resultados obtenidos
Figura 9
En la figura 9 se demuestra el resultado de los cambios realizados. Al cuadro que detecta el objeto
se imprime la etiqueta de la posición de acuerdo al campo de visión, en este caso la cámara web de
la laptop. Las coordenadas por lo tanto, las toma en dos dimensiones siendo el punto de partida u
origen, el lado superior izquierdo de la pantalla en donde se muestre la imagen. El video obtenido de
la cámara web se mostró a una velocidad de 1.4 fps, la cuál era la capacidad máxima permitida por la
GPU.
Martínez, Rodríguez 18
Figura 9.2
En la figura 9.2 se muestra el resultado del profiler generado durante 10 segundos de operación
del programa. En éste se muestran las operaciones ejecutadas por la GPU y el tiempo de cada una
de ellas. Por ejemplo, las operaciones de memcpy se ejecutaron en un total de 813 ms con un total
de 511 invocaciones. El total de bytes utilizados fueron 1.257 GB de memoria a una tasa de
transferencia de 1,544 GB por segundo.
Conclusiones
Durante el desarrollo de este trabajo se aplicaron los conocimientos aprendidos durante la materia
de Computo Paralelo para entender el código del proyecto de detección de objetos elegido y poder
realizar su implementación en la tarjeta GPU que teníamos disponible. Para ello se realizó la
instalación de los drivers Cuda en su versión 8.0 y también las librerías de OpenGL que utiliza la
aplicación para poder mostrar los resultados en el video en tiempo real.
Si bien los resultados mostrados se corrieron a una velocidad de 1.4 fps, esto se debió a que la
capacidad de la GPU elegida no era la óptima para este algoritmo y por lo tanto no significa que éste
no posea el performance esperado, el cual fue probado en una GPU de mayores prestaciones (Titan
X).
Nuestra aportación para este proyecto fue agregarle la localización del objeto en la imagen de
acuerdo a su posición en el eje X y Y respecto a un punto origen (0,0) sobre la esquina superior
izquierda del área de visión de la cámara. Si bien faltaría información de profundidad para detectar
profundidad, esto puede agregarse fácilmente por medio de sensores.
Fortalezas
Este es un código que es ya implementado en varias versiones y la librería con la que cuenta es
tan robusta que puede detectar cualquier objeto. Una de las fortalezas de este algoritmo es que se
puede implementar en varios lenguajes, y la librería tiene distintas versiones de modo que se puede
implementar según la capacidad que se tenga en el Hardware.
Debilidades
Se necesita un equipo igual de robusto que la base de datos, de lo contrario la librería saturaría la
memoria y no podrá correr el programa.
Si bien el algoritmo utilizado permite detectar objetos en tiempo real y conocer su ubicación en el
campo de visión de la cámara, puede agregarse información acerca de la profundidad para
determinar la distancia al objeto y mejorar con ello la información para el sistema ADAS. También
sería importante utilizar una GPU con mayores prestaciones para poder correr el algoritmo a una
velocidad mayor a la alcanzada por nuestra GPU (1.4 fps)
Martínez, Rodríguez 20
Diccionario
Adas
Advanced Driver Assistance Systems, son los algoritmos que ayudan al conductor a manejar un
carro de manera más segura al detectar peligros en el camino, reducir la velocidad en caso de una
posible colisión y apoyo en los puntos ciegos, entre otras cosas.
Los algoritmos están diseñados para entender y aprender del entorno en el que el carro está
rodeado, para de esta manera poder predecir futuras ocurrencias durante el trayecto. Es necesario
que estos se corran en tiempo real, por tal motivo se utiliza el computo paralelo.
Direct Imitation Learning
El buen manejo que se aprenderá se basa en el cumplimiento de dos cosas: mantener el carro en
el carril y manejar sin cambios bruscos. Estos se pueden medir dependiendo del cambio de
aceleración o número de cambios de direcciones. (Innocenti, Linden, Panahandeh, Sevensson,
Mohammadiha, 2017) (2).
Sistema de prevención de colisiones
Este algoritmo entra en el frenado y disminución de la velocidad del carro cuando detecta algún
objeto adelante, el cambio repentino de velocidad de otros conductores, detectar objetos más allá de
la visión en climas difíciles (Kristen Hopper, 2016) Con este algoritmo se detectan tanto la velocidad
de los objetos como la dirección hacía la que van.
Detector de carril
Algoritmo utilizado para detectar que el automóvil este en el carril adecuado y cuando este
comienza a desviarse del mismo. Utiliza una cámara para detectar la anchura del carril, el ancho del
carro, las medidas de las curvas, la orientación del carro, y los caminos laterales. Lussereau,2015)
En este algoritmo, se le da una anchura al carril y al vehiculo de manera que este último tenga que
estar a la mitad de la medida del primero. (Innocenti, Linden, Panahandeh, Sevensson,
Mohammadiha, 2017) (2).
Herramientas de entrada de información: cámara, sensores, radar, mapa GPS
Percepción: Generación de datos a través de la entrada de información acerca de la localización,
el ambiente, el procesamiento de datos y el aprendizaje de datos.
Aplicación: Se planea la trayectoria. Apoyo en la toma de decisiones. Control de funciones.
Acciones realizadas: El cambio de velocidad, la maquina de transmisión, los frenos, cambios de
dirección.
Martínez, Rodríguez 21
Cuda
Es una arquitectura desarrollada por NVIDIA para el procesamiento en paralelo, de esta manera
aumentar el rendimiento de los cálculos realizados. Esta plataforma cuenta con extensiones en
C/C++ para su implementación.
GPU
Es la unidad de procesamiento gráfico compuesta de muchos cores que aumenta la capacidad del
procesamiento en paralelo.
Nvidia
OpcnCV
Es una librería de código abierto desarrollada originalmente por Intel para aplicaciones que
requieren visión computacional en tiempo-real.
Martínez, Rodríguez 22
Bibliografía
Christopher Innocenti∗, Henrik Linde ́n∗, Ghazaleh Panahandeh, Lennart Svensson, Nasser
Mohammadiha. (2017). Imitation Learning for Vision-based Lane Keeping Assistance. 15 de
septiembre del 2017, de arXiv.org Sitio web: https://arxiv.org/pdf/1709.03853.pdf
dSpace. (2017). Typical Setup for Prototyping ADAS and Automated Driving Functions. Octubre del
2017, de dSpace Sitio web:
https://www.dspace.com/en/inc/home/applicationfields/our_solutions_for/driver_assistance_system
s/rapid_prototyping/typical_set-up_for_prototyping.cfm
Jerome Lussereau, Proc ́opio Stein, Jean-Alix David, Lukas Rummelhard, Amaury Ne- gre, et al..
Integration of ADAS algorithm in a Vehicle Prototype. IEEE International Workshop on Advanced
Robotics and its Social Impacts ARSO 2015, Jul 2015, LYON, France. IEEE International
Workshop on Advanced Robotics and its Social Impacts, 2015, <http://arso2015.inria.fr/>.
<hal-01212431>
Joseph Redmon, Ali Farhadi. (2016). YOLO: Real-Time Object Detection. Septiembre del 2017, de
Darknet Sitio web: https://pjreddie.com/darknet/yolo/
Kristen Hopper. (2016). Collision Avoidance Systems. 31 de agosto del 2016, de Micron Sitio web:
https://www.micron.com/about/blogs/2016/september/collision-avoidance-systems
Mariusz Bojarski, Davide Del Testa, Daniel Dworakowski, Bernhard Firner, Beat Flepp, Prasoon
Goyal, Lawrence D. Jackel, Mathew Monfort, Urs Muller, Jiakai Zhang, Xin Zhang, Jake Zhao.
(2016). End to End Learning for Self-Driving Cars. Octubre del 2016, de NVIDIA Sitio web:
http://images.nvidia.com/content/tegra/automotive/images/2016/solutions/pdf/end-to-end-dl-using-p
x.pdf
Nvidia. (2017). Asistencia al conductor conduce de forma más inteligente. conduce de forma más
segura. 29 de agosto del 2017, de Nvidia Sitio web:
http://la.nvidia.com/object/advanced-driver-assistance-systems-la.html
Nvidia. (2017). The AI Car Computer for Autonomous Driving. 20 de agosto del 2017, de Nvidia Sitio
web: http://www.nvidia.com/object/drive-px.html
Nvidia. (2017). ¿QUÉ ES LA COMPUTACIÓN ACELERADA POR GPU?. Septiembre del 2017, de
Nvidia Sitio web: http://la.nvidia.com/object/what-is-gpu-computing-la.html
OBJECT DETECTION AND CLASSIFICATION FOR AUTONOMOUS VEHICLES. (2012). US
8,195,394B1. Patente.
Organización Mundial de la Salud, Global status report on road safety 2015, 2015. Recuperado el
10/10/2017 de: http://www.who.int/mediacentre/factsheets/fs358/en/
Salman, Yasir Dawood. (2017). Distance measurement for self-driving cars using stereo camera. UNIV
UTARI MALAYSIA-UUM, COLL ARTS & SCI, INFOR TECHNOL BLDG, SINTOK, KEDAH 06010,
MALAYSIA, 1, 3. 31 de agosto del 2017, De Web of science Base de datos.
Martínez, Rodríguez 23
im2col_kernels.cu
#include "cuda_runtime.h"
#include "curand.h"
#include "cublas_v2.h"
extern "C" {
#include "im2col.h"
#include "cuda.h"
}
rc: https://github.com/BVLC/caffe/blob/master/src/caffe/util/im2col.cu
// s
// Y ou may also want to read: https://github.com/BVLC/caffe/blob/master/LICENSE
*data_col_ptr = (h >= 0 && w >= 0 && h < height && w < width) ?
data_im_ptr[i * width + j] : 0;
activation_kernels.cu
#include "cuda_runtime.h"
#include "curand.h"
#include "cublas_v2.h"
extern "C" {
#include "activations.h"
#include "cuda.h"
}
case RELIE:
return relie_activate_kernel(x);
case RAMP:
return ramp_activate_kernel(x);
case LEAKY:
return leaky_activate_kernel(x);
case TANH:
return tanh_activate_kernel(x);
case PLSE:
return plse_activate_kernel(x);
case STAIR:
return stair_activate_kernel(x);
case HARDTAN:
return hardtan_activate_kernel(x);
case LHTAN:
return lhtan_activate_kernel(x);
}
return 0;
}
__global__ void gradient_array_kernel(float *x, int n, ACTIVATION a , float *delta)
{
int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + t hreadIdx.x;
if(i < n) delta[i] *= gradient_kernel(x[i], a);
}
convolutional_kernels.cu
#include "cuda_runtime.h"
#include "curand.h"
#include "cublas_v2.h"
extern "C" {
#include "convolutional_layer.h"
#include "batchnorm_layer.h"
#include "gemm.h"
#include "blas.h"
#include "im2col.h"
#include "col2im.h"
#include "utils.h"
#include "cuda.h"
}
check_error(cudaPeekAtLastError());
}
__global__ void binarize_input_kernel(float *input, int n, int size, float *binary)
{
int s = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if (s >= size) return;
int i = 0;
float mean = 0;
for(i = 0; i < n; ++i){
mean += fabsf(input[i*size + s]);
}
mean = mean / n;
for(i = 0; i < n; ++i){
binary[i*size + s] = (input[i*size + s] > 0) ? mean : -mean;
}
}
__global__ void binarize_weights_kernel(float *weights, int n, int size, float *binary)
{
int f = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if (f >= n) return;
int i = 0;
float mean = 0;
for(i = 0; i < size; ++i){
mean += fabsf(weights[f*size + i]);
}
mean = mean / size;
for(i = 0; i < size; ++i){
binary[f*size + i] = (weights[f*size + i] > 0) ? mean : -mean;
//binary[f*size + i] = weights[f*size + i];
}
}
swap_binary(&l);
}
if(l.xnor){
binarize_weights_gpu(l.weights_gpu, l.n, l.c/l.groups*l.size*l.size,
l.binary_weights_gpu);
swap_binary(&l);
binarize_gpu(net.input_gpu, l.c*l.h*l.w*l.batch, l.binary_input_gpu);
net.input_gpu = l.binary_input_gpu;
}
#ifdef CUDNN
float one = 1;
cudnnConvolutionForward(cudnn_handle(),
&one,
l.srcTensorDesc,
net.input_gpu,
l.weightDesc,
l.weights_gpu,
l.convDesc,
l.fw_algo,
net.workspace,
l.workspace_size,
&one,
l.dstTensorDesc,
l.output_gpu);
#else
int i, j;
int m = l.n/l.groups;
int k = l.size*l.size*l.c/l.groups;
int n = l.out_w*l.out_h;
for(i = 0; i < l.batch; ++i){
for(j = 0; j < l.groups; ++j){
float *a = l.weights_gpu + j*l.nweights/l.groups;
float *b = net.workspace;
float *c = l.output_gpu + (i*l.groups + j)*n*m;
if (l.batch_normalize) {
forward_batchnorm_layer_gpu(l, net);
} else {
add_bias_gpu(l.output_gpu, l.biases_gpu, l.batch, l.n, l.out_w*l.out_h);
}
__global__ void s mooth_kernel(float *x, int n, int w, int h, int c
, int size, float rate,
float *delta)
{
int id = (blockIdx.x + blockIdx.y*gridDim.x) * b lockDim.x + threadIdx.x;
if(id >= n ) return;
int w
_offset = -(size/2.f);
int h _offset = -(size/2.f);
int out_index = j + w*(i + h*(k + c*b));
int l, m;
for(l = 0; l < size; ++l){
for(m = 0; m < size; ++m){
int cur_h = h_offset + i + l;
int cur_w = w_offset + j + m;
int index = cur_w + w*(cur_h + h*(k + b*c));
int valid = (cur_h >= 0 && cur_h < h &&
cur_w >= 0 && cur_w < w);
delta[out_index] += valid ? rate*(x[index] - x[out_index]) : 0;
}
}
}
if(l.batch_normalize){
backward_batchnorm_layer_gpu(l, net);
} else {
backward_bias_gpu(l.bias_updates_gpu, l.delta_gpu, l.batch, l.n, l.out_w*l.out_h);
}
float *original_input = net.input_gpu;
if(net.delta_gpu){
if(l.binary || l.xnor) swap_binary(&l);
cudnnConvolutionBackwardData(cudnn_handle(),
&one,
l.weightDesc,
l.weights_gpu,
l.ddstTensorDesc,
l.delta_gpu,
l.convDesc,
l.bd_algo,
net.workspace,
l.workspace_size,
&one,
l.dsrcTensorDesc,
net.delta_gpu);
if(l.binary || l.xnor) swap_binary(&l);
if(l.xnor) gradient_array_gpu(original_input, l.batch*l.c*l.h*l.w, HARDTAN,
net.delta_gpu);
}
#else
int m
= l .n/l.groups;
int n = l .size*l.size*l.c/l.groups;
int k = l .out_w*l.out_h;
if(net.delta_gpu){
if(l.binary || l.xnor) swap_binary(&l);
a = l.weights_gpu + j*l.nweights/l.groups;
b = l.delta_gpu + (i*l.groups + j)*m*k;
c = net.workspace;
gemm_gpu(1,0,n,k,m,1,a,n,b,k,0,c,k);
if(a.adam){
adam_update_gpu(l.weights_gpu, l.weight_updates_gpu, l.m_gpu, l.v_gpu, a.B1, a.B2,
a.eps, decay, learning_rate, l.nweights, batch, a.t);
adam_update_gpu(l.biases_gpu, l.bias_updates_gpu, l.bias_m_gpu, l.bias_v_gpu,
a.B1, a.B2, a.eps, decay, learning_rate, l.n, batch, a.t);
if(l.scales_gpu){
adam_update_gpu(l.scales_gpu, l.scale_updates_gpu, l.scale_m_gpu,
l.scale_v_gpu, a.B1, a.B2, a.eps, decay, learning_rate, l.n, batch, a.t);
}
}else{
axpy_gpu(l.nweights, -decay*batch, l.weights_gpu, 1, l.weight_updates_gpu, 1);
axpy_gpu(l.nweights, learning_rate/batch, l.weight_updates_gpu, 1, l.weights_gpu,
1);
scal_gpu(l.nweights, momentum, l.weight_updates_gpu, 1);
axpy_gpu(l.n, l
earning_rate/batch, l.bias_updates_gpu, 1, l.biases_gpu, 1);
scal_gpu(l.n, m omentum, l.bias_updates_gpu, 1);
if(l.scales_gpu){
axpy_gpu(l.n, learning_rate/batch, l.scale_updates_gpu, 1, l.scales_gpu,
1);
scal_gpu(l.n, momentum, l.scale_updates_gpu, 1);
}
}
}