c++ - cudnn7 - Maximice el rendimiento tensorflow multi gpu
nvidia deep learning sdk (1)
Me preguntaba si alguien podría aconsejar sobre cómo obtener el máximo rendimiento de tensorflow en una configuración de 4 GPU.
Como prueba, creé dos de la misma red (18 ish layer residual network con pequeños bancos de filtros (que van desde 16 hasta 128) en las entradas 32x32. Batch size 512, 128 por GPU). Uno en MXNet y otro que he modelado del ejemplo inicial .
Mi red MXNet puede entrenar en alrededor de 7k ejemplos por segundo donde tensorflow solo es capaz de 4.2k con datos ficticios y 3.7 con datos reales.
(cuando se ejecuta en 1 GPU, los números son 1.2k ejemplos por segundo frente a 2.1k)
En mi experimento, tengo algunas preguntas con la esperanza de acelerar las cosas.
La utilización de la GPU parece bastante baja cuando se entrena. Noté que en el documento técnico de Tensorflow hay soporte para ejecutar múltiples transmisiones en la misma GPU. ¿Es esto posible en el lanzamiento público?
¿Hay alguna forma de realizar múltiples operaciones de tren en una ejecución de
session.run()
? ¿O tienes una ejecución asincrónica? ¿Esto permitiría que las actualizaciones de peso se hagan al mismo tiempo que pasan los próximos lotes? He intentado usar 2 hilos (tanto del sistema como deQueueRunners
), pero esto solo provocó una desaceleración. MXNet puede aumentar las velocidades ejecutando actualizaciones de peso en la CPU para que las GPU se puedan usar para el siguiente lote.¿El nuevo tiempo de ejecución distribuido solucionará algunos de estos problemas al permitirme ejecutar más de un trabajador en una sola máquina?
¿Hay algo más que se pueda hacer?
Sé que hay una serie de preguntas similares aquí en el desbordamiento de la pila, pero a pesar de mi búsqueda no pude encontrar una solución a mis problemas que no haya probado.
Editar:
Hice un poco de perfil de CUDA para ver cuáles eran los granos caros. De acuerdo con mi ejecución, el 21.4% del tiempo lo paso dentro:
void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorPaddingOp<Eigen::array<std::pair<int, int>,
unsigned long=4> const, Eigen::TensorMap<Eigen::Tensor<float const,
int=4, int=1, long>, int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)
y el 20.0% del tiempo se gastó en
void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorBroadcastingOp<Eigen::array<int, unsigned long=4>
const, Eigen::TensorMap<Eigen::Tensor<float const, int=4, int=1, long>,
int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)
Fuera de la firma, no estoy exactamente seguro de lo que están haciendo. ¿Tienen sentido?
Además de esto, el análisis informa concurrencia de kernel baja, 0%, como se esperaba. Y bajo uso de computación 34.9% (con esto se incluye el tiempo de inicio y un poco de pitón en el ciclo del tren. Alrededor de 32 segundos en total de 91. Esto se traduce en aproximadamente el 50% de utilización dentro de Tensorflow).
Editar 2:
Adjunto una copia del código fuente recortado. En general, sin embargo, estoy más preocupado por la pregunta 1-3 y no quiero tomar demasiado tiempo de mi cuerpo.
Además, estoy ejecutando en tensorflow construido desde: f07234db2f7b316b08f7df25417245274b63342a
Editar 3:
Actualizado al tensorflow más reciente (63409bd23facad471973b110df998782c0e19c06) mismo código, formato de datos predeterminado (NHWC) y que parecía acelerar esto mucho. En datos falsos 6.7k-6.8k (dependencia térmica, ¿no?) Ejemplos de un segundo 4gpu. 1gpu - 2.0k ejemplos por segundo. El rendimiento real de los datos es alrededor de 4,9 mil ejemplos por segundo para 4gpu. 1gpu - 1.7k ejemplos por segundo.
Editar 4:
Además, intenté cambiar los formatos de datos a BCHW. Hice la conversión modelada de los puntos de referencia de Soumith . Las partes de la convolución fueron de hecho más rápidas, pero la norma de lotes parece estar estropeando todo. Con una implementación ingenua (fijar el eje y hacer pesos [1, C, 1, 1] en lugar de [C,]), solo puedo obtener 1.2k ejemplos por segundo en 4 gpu (datos falsos). Mientras que con una transposición antes y después de la norma de lote op, puedo obtener 6.2k ejemplos por segundo (datos falsos). Aún más lento que el NHWC data_format.
Es difícil diagnosticar el problema de rendimiento de su programa sin ver el código. ¿Es posible para nosotros leer su código de prueba de alguna manera?
TensorPadding que se muestra en la parte superior es un poco extraño. Esperaría que las llamadas de cudnn estuvieran en la parte superior del perfil. De todos modos, mostrarnos el código de prueba será útil.