Cómo depurar la función del núcleo del programa CUDA C
Debido a factores como la imperfección de las herramientas de depuración de CUDA, la dificultad para comenzar con las herramientas de depuración de CUDA y la dificultad de depurar la idea paralela en sí, la depuración de CUDA siempre ha sido un dolor de cabeza. He estado escribiendo CUDA durante tres o cuatro años. Hace algún tiempo, vi a alguien en un grupo preguntando sobre la depuración de CUDA y de repente se me ocurrió la idea de escribir un blog sobre la depuración de CUDA. Mi experiencia aún es superficial. Espero que después de leerla, puedas darme algunos consejos en los comentarios y ayudarme a mejorar este blog.
Este blog sólo trata sobre errores de lógica.
1? Localizar errores
El primer pensamiento cuando ocurre un error es, naturalmente, localizarlo. Lo extraño de CUDA es que a veces se informa un error en la línea 500, pero el código en la línea 500 no tiene ningún error, pero la lógica en la línea 1000 es incorrecta, lo cual es muy problemático.
Aquí hay tres métodos para localizar errores que he resumido:
1.1? Dicotomía
La mitad y la mitad del código comentado se utiliza para localizar errores. Un poco torpe y engorroso, pero muy fácil de usar.
1.2 ?Método de posicionamiento de salida
Divida el código general en varios módulos. El código CUDA normal se puede dividir aproximadamente en inicialización de datos, aplicación de memoria, copia de memoria, ejecución de funciones del núcleo y resultados. Copia y otros módulos. Envíe la bandera después de cada módulo, como se muestra en la Figura 1. De esta manera, puede localizar rápidamente la ubicación aproximada del error según el resultado durante la depuración. Como se muestra a continuación:
1.3? Herramientas de depuración
Para algunos errores, puede utilizar herramientas de depuración para localizarlos más rápidamente.
En Linux, para problemas como el acceso a la memoria fuera de los límites, cuda gdb puede localizar directamente la línea de fallo.
En win, es Nsight. No estoy familiarizado con nsight. Por favor, dame algún consejo.
2? Resolver errores
Los errores relativamente simples se pueden resolver básicamente de un vistazo una vez localizados. Pero para errores complejos, es aún más laborioso.
2.1 ?Herramientas de depuración
Depuración en un solo paso, puntos de interrupción. Ya sea cuda gdb o Nsight, puede localizar un determinado hilo para depurar, que se puede decir que es muy poderoso. Tanto cuda gdb como nsight tienen documentos oficiales en inglés. Se recomienda que todos lo aprendan. Una vez que domine la depuración, obtendrá el doble de resultado con la mitad de esfuerzo.
Sin embargo, debido a que una gran cantidad de subprocesos se ejecutan aleatoriamente en paralelo, a veces no se sabe a qué subproceso apuntar; la depuración de subprocesos no es fácil de controlar y el posicionamiento para la depuración de un solo subproceso requiere mucho tiempo; consume; hay pocos tutoriales (aunque hay documentos oficiales), es más difícil comenzar. Estas son las razones por las que las herramientas de depuración CUDA no son ampliamente aceptadas.
2.2? Reducir la cantidad de datos o el número de subprocesos e imprimirlos en la función del kernel.
Una gran cantidad de subprocesos paralelos es la razón principal por la que la depuración de CUDA es difícil. Es una muy buena idea reducir la cantidad de paralelismo tanto como sea posible. Formas de reducir la dificultad de la depuración. "Pequeño paralelismo" o incluso "en serie" pueden facilitar enormemente la depuración.
En Fermi y arquitecturas posteriores, printf se puede utilizar en funciones del kernel.
Reduzca la cantidad de datos dentro de un rango razonable, reduciendo así la cantidad de subprocesos, como cambiar el tamaño de la imagen de entrada a 16 * 16. O modifique el hilo a lt;lt;lt;1,1gt;gt;gt;, printf para ver si el resultado es el mismo que se esperaba.
3? Prevenir errores
Cada usuario de CUDA probablemente tenga la experiencia de pasar horas o incluso días depurando un error. Dado que los errores son tan difíciles de corregir, prevenirlos es particularmente importante.
3.1 ?Asegúrese de concebir completamente la arquitectura antes de escribir el código
La sociedad se está desarrollando rápidamente y los corazones de las personas se han vuelto ansiosos. Antes de escribir código CUDA, debe estar tranquilo, dedicar más tiempo al papel para concebir el código, modularizar el código, dónde es probable que ocurran problemas, dónde escribir el resultado y dónde verificarlo.
3.2? Verificación de resultados de devolución de funciones
La verificación de resultados de devolución de funciones puede localizar errores muy bien y es un conocimiento básico de programación.
Aunque el código puede parecer redundante, el ejemplo es el siguiente; también puede consultar el código en el ejemplo de cuda.
3.3? Verificación de entrada de función
Al llamar a una función más importante, se recomienda utilizar afirmar para verificar si los parámetros de entrada son los mismos que los valores esperados.
3.4? Verificación de funciones en el kernel
Por ejemplo, al copiar memoria fragmentada, la lógica de copia es relativamente complicada. En este momento, puede escribir una función de verificación para garantizar la exactitud de la copia.
El código en la función del kernel es el siguiente: