cuando está llamando a la cudaDeviceSynchronize función que realmente se necesita?.

Tal y como yo lo entiendo de la CUDA documentación, núcleos CUDA son asincrónicas, así que parece que deberíamos llamar cudaDeviceSynchronize después de cada núcleo de lanzamiento. Sin embargo, he tratado de que el mismo código (formación de redes neuronales) con y sin ningún cudaDeviceSynchronize, a excepción de uno antes de la medición del tiempo. He encontrado que obtener el mismo resultado, pero con una velocidad de entre 7-12x (según la matriz de tamaños).

Entonces, la pregunta es si hay alguna razones para el uso de cudaDeviceSynchronize aparte de la medición de tiempo.

Por ejemplo:

  • Es necesario antes de copiar los datos de la GPU de vuelta al host con cudaMemcpy?

  • Si hago matriz de multiplicaciones como

    C = A * B
    D = C * F

debo poner cudaDeviceSynchronize entre ambos?

De mi experimento, parece que yo no.

¿Por qué cudaDeviceSynchronize lento el programa tanto?

  • Un ejemplo sería si usted tiene cualquiera de impresión de las declaraciones en el núcleo, el buffer no se imprimirá hasta que un evento de sincronización.
InformationsquelleAutor user1588226 | 2012-08-09

3 Comentarios

  1. 52

    Aunque CUDA núcleo de lanza son asincrónicas, todos los de la GPU para tareas relacionadas con la colocan en una secuencia (que es el comportamiento predeterminado) se ejecutan de forma secuencial.

    Así, por ejemplo,

    kernel1<<<X,Y>>>(...); //kernel start execution, CPU continues to next statement
    kernel2<<<X,Y>>>(...); //kernel is placed in queue and will start after kernel1 finishes, CPU continues to next statement
    cudaMemcpy(...); //CPU blocks until memory is copied, memory copy starts only after kernel2 finishes

    Así que en tu ejemplo, no hay necesidad de cudaDeviceSynchronize. Sin embargo, podría ser útil para la depuración para detectar que su núcleo se ha producido un error (si lo hay).

    cudaDeviceSynchronize puede causar cierta desaceleración, pero 7-12x parece demasiado. Podría ser que hay algún problema con la medición del tiempo, o tal vez los núcleos son realmente rápido, y la sobrecarga de una sincronización explícita es enorme en relación a real el tiempo de cálculo.

    • El «único defecto de la GPU de corriente a menos que se especifique de otra manera» no siempre se celebrará por nvcc. Acabo de depurar un programa en el que me rompió un largo cálculo en un núcleo en una trozos de cálculo que lanzó a los núcleos de una en una en un for() loop. Sucesivas para() loop núcleo lanza la pick up en la que el anterior para() loop núcleo dejó de lado del dispositivo. El error fue que el nvcc compilador no podía ver esto desde el código de host y trató de lanzar cada núcleo al mismo tiempo. Esto significaba que todos los kernels, pero el primer núcleo se computing basura.
    • Que no es la forma CUDA obras.
    • Por favor, lea mi comentario con más cuidado. Yo de manera muy explícita poner «no siempre se celebrará por nvcc». Luego me dio un ejemplo de un error que me persiguió usando cuda-gdb que sirve como un ejemplo demostrando precisamente eso. Definitivamente, me gustaría estar de acuerdo que, basado en Nvidia literatura esta no es la forma de CUDA se supone que funciona… pero lo que yo estaba diciendo no era una opinión: fue una de las observaciones realizadas durante la depuración acerca de cómo ha funcionado en una instancia específica.
    • Lo siento por no creer en usted, pero usted ha descubierto un extremadamente crítica bug, o algo se rompió en su código. ¿Post el problema en ESO?
    • No hay problema. En cuanto a tu pregunta estoy registrado con Nvidia a través de la simulación de trabajo para la física en un clúster de ellos han donado hardware. Cuando veo a los graves problemas que yo publique en su CUDA foro donde las personas que el diseño de la nvcc el compilador en un lugar de solucionarlo.
    • Dicho esto, yo no lo llamaría el de arriba de un error crítico con nvcc de haber trabajado con él el año pasado (he encontrado mucho peor). Sería un error importante en el gcc, pero la memoria/nivel de instrucción de trabajo paralelo es complicado… el compilador tiene que ser un poco exagerada para conseguir mejoras.
    • En realidad, es el tiempo de ejecución no es el compilador que las órdenes de los núcleos. No trate de ser más celoso. Simplemente, los núcleos en la misma secuencia se puso en marcha en orden. Tal vez quiere decir que gcc re-ordenada la biblioteca de llamadas que el lanzamiento de los núcleos? ¿Tienes un enlace al foro de discusión de su problema?
    • No voy a entrar en una «era el programa que hizo el compilador» porque cuando todo está dicho y hecho el nvcc compilador de código creado que no hizo valer un orden estricto en función de host. El código en cuestión era un anfitrión de función (tipo de retorno void) en una .cu archivo que eran, por definición, compilados y enlazados con nvcc. gcc no estaba involucrado, y punto. Me dijo que considera que esto no es un grave error. Además, ya he dicho que yo no publique no graves errores en el foro de Nvidia. No sé por qué usted está solicitando un enlace a un debate que no existe.
    • NVCC no es un compilador de código de host. Es un pre-procesador que manos a la del sistema compilador (gcc). Usted está mal informado sobre muchos aspectos de CUDA. En lugar de publicar la información engañosa y lastimar a otros, usted debe publicar preguntas sobre cosas que no conoce o los problemas que te encuentras. Tal vez alguien podría haber aclarado el por qué de su código parecían ser fijado por la adición de superfluo cudaDeviceSynchronize llamadas.
    • Su actitud está fuera de lugar. A pesar de eso, puedo conceder estás en lo correcto en la corrección de mí en gcc (para linux) estar involucrado después de la .cu archivo preprocesado por nvcc en la compilación independiente de los árboles. Esto no es excusa para generalizar acerca de alguien del conocimiento o hablando a ellos, mientras que en la ley de abordar el punto legítimo (.cu yendo primero a nvcc por definición) por dar un argumento específico (es decir, nvcc sólo en dar el paso de ser un pre-procesador de código de host luego de entregar a la acogida del compilador).
    • Por favor, acepte mi actitud como el resultado de tratar amablemente pedimos que no públicamente hacer improbable reclamos (que podría severamente confundir a un novato que visitas esta página), tales como, «CUDA ignora su especificación y lanzamientos de granos fuera de orden», sin tener suficientemente investigado el escenario más probable que el error es en su propio código, y se reunió con obstinence.
    • Justo lo suficiente. Para mantener las cosas en un productivo nota, yo diría que mi actitud con NVCC después de estudiar la documentación y la construcción de simulaciones es este: asumir la macro «podría» tomar las libertades acerca de lo que debe ser el código de host en una .cu archivo (antes de entregarlos al host compilador). A veces entiendo a hacer programas que están contenidas en una sola .cu/.cuh par de archivos y que nvcc debería, en teoría, no causa problemas para el código de host. Pero he encontrado en la práctica mediante contenedores hecho un MONTÓN de problemas desaparecen al mismo tiempo, realizar las cosas más modular (cuando corresponda).
    • Solo que pensé que me gustaría añadir algunos más de los hallazgos relevantes. He tenido un número significativo de errores de resolver cuando se mueve el código de host de no-CUDA y el encabezado de los archivos de origen. NVCC todavía enlace de ellos, pero no hay ninguna de etiquetado de código de host utilizando el nvcc preprocesador de las banderas .cu o .cuh archivos. Llego a la conclusión de que el punto original gradas. Para reafirmar este punto: Sólo porque NVCC teóricamente manos fuera de las funciones de acogida en .cu/.cuh a GCC no quiere decir que NO funciona de esa manera en la práctica.
    • He tenido el mismo problema, el lanzamiento de los núcleos de una en una en un bucle for. Exactamente el mismo código funciona muy bien en Linux, pero no en Windows. No puedo creer que necesita un cudaDeviceSynchronize para resolverlo.
    • y nadie más. A los lejos, el escenario más probable es opetrenko y user3667089 los problemas son debido a errores de código, y no errores en NVCC y la API de CUDA. Falta de trabajo código de ejemplo que se reproduce, este debate se reduce a opinión.

  2. 15

    Una situación donde el uso de cudaDeviceSynchronize() es apropiado sería cuando usted tiene varios cudaStreams correr, y te gustaría tener ellos el intercambio de información. Un caso de la vida real de esto es templado paralelo en quantum simulaciones de Monte Carlo. En este caso, queremos asegurar que cada arroyo se ha terminado de ejecutar un conjunto de instrucciones y obtenido algunos resultados antes de iniciar el envío de mensajes el uno al otro, o que acabaría pasando a la basura de la información. La razón de usar este comando retarda el programa tanto es que cudaDeviceSynchronize() obliga al programa a esperar a que todos los anteriormente emitidos comandos en todos los flujos de datos en el dispositivo para finalizar antes de continuar (desde el CUDA C Guía de Programación). Como usted ha dicho, el núcleo de ejecución es normalmente asincrónica, así, mientras que la GPU del dispositivo se está ejecutando el núcleo de la CPU puede seguir trabajando en algunos otros comandos, cuestión más instrucciones para el dispositivo, etc., en lugar de esperar. Sin embargo, cuando se utiliza este comando de sincronización, la CPU es lugar obligado a ralentí hasta que todas las GPU de trabajo se ha completado antes de hacer nada. Este comportamiento es útil cuando la depuración, ya que puede haber una violación de segmento que se produzcan en aparentemente «al azar» tiempos debido a la ejecución asíncrona de código de dispositivo (ya sea en uno o varios). cudaDeviceSynchronize() se fuerza el programa para asegurar la secuencia(s)’s kernels/memcpys se complete antes de continuar, que puede hacer que sea más fácil saber dónde los accesos ilegales se están produciendo (ya que el error que se mostrará durante la sincronización).

  3. 4

    Cuando usted quiere que su GPU para iniciar el procesamiento de algunos datos, se suele hacer un kernel de invocación.
    Al hacerlo, El dispositivo (GPU) va a empezar a hacer lo que se le dijo que hiciera. Sin embargo, a diferencia de una normal secuencial del programa en el host (CPU), va a seguir para ejecutar las siguientes líneas de código del programa. cudaDeviceSynchronize hace que el host (CPU) espere hasta que el dispositivo (GPU) han finalizado la ejecución de TODOS los hilos que han comenzado, y por lo tanto su programa continuará como si fuera una normal secuencial del programa.

    En pequeños programas que normalmente uso cudaDeviceSynchronize, cuando se utiliza la GPU para hacer los cálculos, para evitar el momento de los desajustes entre la CPU solicitando el resultado y la GPU finising el cálculo. El uso de cudaDeviceSynchronize hace que sea mucho más fácil para el código de su programa, pero hay un gran inconveniente: la CPU está ociosa todo el tiempo, mientras que la GPU hace el cálculo. Por lo tanto, en computación de alto rendimiento, que a menudo se esfuerzan por lograr tener la CPU haciendo cálculos mientras se espera para la GPU para terminar.

Dejar respuesta

Please enter your comment!
Please enter your name here