imprimiendo desde cuda kernels

5 minutos de lectura

Estoy escribiendo un programa cuda e intentando imprimir algo dentro de los núcleos cuda usando la función printf. Pero cuando estoy compilando el programa, aparece un error.

error : calling a host function("printf") from a __device__/__global__ function("agent_movement_top") is not allowed


 error MSB3721: The command ""C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.2\bin\nvcc.exe" -gencode=arch=compute_10,code=\"sm_10,compute_10\" --use-local-env --cl-version 2008 -ccbin "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin" -I"C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.2\C\common\inc" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.2\include"  -G  --keep-dir "Debug" -maxrregcount=0  --machine 32 --compile  -g    -Xcompiler "/EHsc /nologo /Od /Zi  /MDd  " -o "Debug\test.cu.obj" "C:\Users\umdutta\Desktop\SANKHA_ALL_MATERIALS\PROGRAMMING_FOLDER\ABM_MODELLING_2D_3D\TRY_NUM_2\test_proj_test\test_proj\test_proj\test.cu"" exited with code 2.

Estoy usando la tarjeta GTX 560 ti que tiene una capacidad de cómputo superior a 2.0 y cuando busqué un poco sobre la impresión de cuda kernels también vi que necesito cambiar el compilador de sm_10 a sm_2.0 para aprovechar al máximo la tarjeta. También algunos sugirieron que cuPrintf sirviera para este propósito. Estoy un poco confundido sobre qué debo hacer y cuál debería ser la forma más simple y rápida de obtener las impresiones en la pantalla de mi consola. Si necesito cambiar el compilador nvcc de 1.0 a 2.0, ¿qué debo hacer? Una cosa más que me gustaría mencionar es que estoy usando Windows 7.0 y programando en Visual Studio 2010. Gracias por toda su ayuda.

  • debería funcionar si (1) compila para la arquitectura de destino sm_21 y (2) se asegura de #include stdio.h. El tiempo de ejecución de CUDA incluye la sobrecarga de dispositivos de printf para kernels, pero la biblioteca de E/S de C stardard debe incluirse explícitamente para que este mecanismo funcione.

    – garras

    31 de diciembre de 2012 a las 23:15

  • ¡HOLA! El archivo de encabezado de E/S estándar siempre se incluyó y la capacidad de cómputo de mi tarjeta es 2.1. Así que creo que debería compilarse con las funciones sm_21 del compilador nvcc. Sin embargo, resolví mis problemas usando la función cuPrintf. Pero todavía quiero saber cómo puedo cambiar mi capacidad de cómputo nvcc 1.0 predeterminada a la capacidad de cómputo 2.1.

    – duttasankha

    31 de diciembre de 2012 a las 23:28

  • @RogerDahl: Eso es perfecto y funciona perfectamente bien. ¿Puede publicarlo como respuesta para que pueda aceptarlo también? Me has alegrado el día. Gracias una tonelada.

    – duttasankha

    1 de enero de 2013 a las 0:56

Avatar de usuario de Heba
Heba

puede escribir este código para imprimir lo que quiera desde el Kernel de CUDA:

# if __CUDA_ARCH__>=200
    printf("%d \n", tid);

#endif  

e incluir

Para permitir el uso de llanura printf() en dispositivos con Compute Capability >= 2.0, es importante compilar para CC de al menos CC 2.0 y deshabilitar el valor predeterminado, que incluye una compilación para CC 1.0.

Haga clic derecho en el .cu archivo en su proyecto, seleccione Propertiesseleccionar Configuration Properties | CUDA C/C++ | Device. Clickea en el Code Generation línea, haga clic en el triángulo, seleccione Edit. En el cuadro de diálogo Generación de código, desmarque Inherit from parent or project defaultstipo compute_20,sm_20 en la ventana superior, haga clic en Aceptar.

  • No funciona. Todavía se queja de printf como indefinido. El mio es CUDA 6.5 + VS2012 + Tesla2050

    – Ono

    11 de marzo de 2015 a las 15:54

avatar de usuario de duttasankha
duttasankha

Una forma de resolver este problema es usar la función cuPrintf que es capaz de imprimir desde los núcleos. Copia los archivos cuPrintf.cu y cuPrintf.cuh de la carpeta

C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.2\C\src\simplePrintf

a la carpeta del proyecto. Luego agregue el archivo de encabezado cuPrintf.cuh a su proyecto y agregue

#include "cuPrintf.cu"

a su código. Entonces su código debe estar escrito en un formato mencionado a continuación:

#include "cuPrintf.cu"
__global__ void testKernel(int val)
{
  cuPrintf("Value is: %d\n", val);
}

int main()
{
  cudaPrintfInit();
  testKernel<<< 2, 3 >>>(10);
  cudaPrintfDisplay(stdout, true);
  cudaPrintfEnd();
  return 0;
}

Siguiendo el procedimiento anterior, se puede obtener una impresión en la ventana de la consola desde la función del dispositivo. Aunque resolví mis problemas de la manera mencionada anteriormente, todavía no tengo la solución de usar printf de la función del dispositivo. Si es cierto y absolutamente necesario actualizar mi compilador nvcc de sm_10 a sm_21 para habilitar el printf entonces sería muy útil si alguien pudiera mostrarme la luz. Gracias por toda su cooperación.

Estoy usando GTX 1650, también GTX1050 y c ++ 11. Para usuarios recientes, esta es mi sugerencia:

En la función de host:

#include<iostream>
using namespace std;

cout<< .....(anything you want) << endl;

En el núcleo:

if(threadIdx.x==0){
    printf("ss=%4.2f \n", ss);
}

Tenga en cuenta que este “si” es bastante importante y noté que nadie lo mencionó. Porque puede usar muchos subprocesos y definitivamente no desea imprimir demasiado de cada subproceso. También 4.2f significa 4 puntos y 2 para decimal. Esto puede evitar que se imprima demasiado 00000. Además, no olvide \n para saltar la línea.

También puede considerar esto para imprimir el valor de la memoria compartida:

if(threadIdx.x==0){
    for(int i=0;i<64;i++){
        for(int j=0;j<8; j++){
            printf("%4.2f  ", ashare[i*8+j]);
        }
        printf("\n");
    }
    printf("\n");
}

Esto puede imprimir maravillosamente la memoria compartida. Tenga en cuenta que también es necesario restringir solo en threadIdx.x==0

¿Ha sido útil esta solución?