2012-05-09 5 views
6

Estoy comenzando mi diario para aprender Cuda. Estoy jugando con un código de tipo cuda hello world pero no funciona, y no estoy seguro de por qué.Agregación simple de dos int en Cuda, resultado siempre el mismo

El código es muy simple, tome dos ints y agréguelos a la GPU y devuelva el resultado, pero no importa lo que cambie los números para obtener el mismo resultado (Si las matemáticas funcionaran de esa manera, lo hubiera hecho mucho mejor en el tema de lo que realmente hice).

Aquí está el código de ejemplo:

// CUDA-C includes 
#include <cuda.h> 
#include <stdio.h> 

__global__ void add(int a, int b, int *c) { 
    *c = a + b; 
} 

extern "C" 
void runCudaPart(); 

// Main cuda function 

void runCudaPart() { 

    int c; 
    int *dev_c; 

    cudaMalloc((void**)&dev_c, sizeof(int)); 
    add<<<1,1>>>(1, 4, dev_c); 

    cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost); 

    printf("1 + 4 = %d\n", c); 
    cudaFree(dev_c); 

} 

La salida parece un poco fuera: 1 + 4 = -1065287167

estoy trabajando en la creación de mi entorno y sólo quería saber si había un problema con el código de lo contrario, es probable que sea mi entorno.

Actualización: Intenté agregar un código para mostrar el error pero no obtengo una salida pero el número cambia (¿está produciendo códigos de error en lugar de respuestas? Incluso si no hago ningún trabajo en la kernal aparte de asignar una variable, sigo obteniendo los resultados de simlair).

// CUDA-C includes 
#include <cuda.h> 
#include <stdio.h> 

__global__ void add(int a, int b, int *c) { 
    //*c = a + b; 
    *c = 5; 
} 

extern "C" 
void runCudaPart(); 

// Main cuda function 

void runCudaPart() { 

    int c; 
    int *dev_c; 

    cudaError_t err = cudaMalloc((void**)&dev_c, sizeof(int)); 
    if(err != cudaSuccess){ 
     printf("The error is %s", cudaGetErrorString(err)); 
    } 
    add<<<1,1>>>(1, 4, dev_c); 

    cudaError_t err2 = cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost); 
    if(err2 != cudaSuccess){ 
     printf("The error is %s", cudaGetErrorString(err)); 
    } 


    printf("1 + 4 = %d\n", c); 
    cudaFree(dev_c); 

} 

Código parece estar bien, tal vez su relación con mi configuración. Ha sido una pesadilla instalar Cuda en OSX lion, pero pensé que funcionaba, ya que los ejemplos del SDK parecían estar bien. Los pasos que he dado hasta ahora son ir al sitio web de Nvida y descargar los últimos lanzamientos de Mac para el controlador, el kit de herramientas y el SDK. Luego añade export DYLD_LIBRARY_PATH=/usr/local/cuda/lib:$DYLD_LIBRARY_PATH y 'PATH =/usr/local/CUDA/bin: $ path` hice un deviceQuery y pasó con la siguiente información sobre mi sistema:

[deviceQuery] starting... 

/Developer/GPU Computing/C/bin/darwin/release/deviceQuery Starting... 

CUDA Device Query (Runtime API) version (CUDART static linking) 

Found 1 CUDA Capable device(s) 

Device 0: "GeForce 320M" 
    CUDA Driver Version/Runtime Version   4.2/4.2 
    CUDA Capability Major/Minor version number: 1.2 
    Total amount of global memory:     253 MBytes (265027584 bytes) 
    (6) Multiprocessors x ( 8) CUDA Cores/MP: 48 CUDA Cores 
    GPU Clock rate:        950 MHz (0.95 GHz) 
    Memory Clock rate:        1064 Mhz 
    Memory Bus Width:        128-bit 
    Max Texture Dimension Size (x,y,z)    1D=(8192), 2D=(65536,32768), 3D=(2048,2048,2048) 
    Max Layered Texture Size (dim) x layers  1D=(8192) x 512, 2D=(8192,8192) x 512 
    Total amount of constant memory:    65536 bytes 
    Total amount of shared memory per block:  16384 bytes 
    Total number of registers available per block: 16384 
    Warp size:          32 
    Maximum number of threads per multiprocessor: 1024 
    Maximum number of threads per block:   512 
    Maximum sizes of each dimension of a block: 512 x 512 x 64 
    Maximum sizes of each dimension of a grid:  65535 x 65535 x 1 
    Maximum memory pitch:       2147483647 bytes 
    Texture alignment:        256 bytes 
    Concurrent copy and execution:     Yes with 1 copy engine(s) 
    Run time limit on kernels:      Yes 
    Integrated GPU sharing Host Memory:   Yes 
    Support host page-locked memory mapping:  Yes 
    Concurrent kernel execution:     No 
    Alignment requirement for Surfaces:   Yes 
    Device has ECC support enabled:    No 
    Device is using TCC driver mode:    No 
    Device supports Unified Addressing (UVA):  No 
    Device PCI Bus ID/PCI location ID:   4/0 
    Compute Mode: 
    < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > 

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 4.2, CUDA Runtime Version = 4.2, NumDevs = 1, Device = GeForce 320M 
[deviceQuery] test results... 
PASSED 

ACTUALIZACIÓN: ¿cuál es realmente extraño es incluso si Elimino todo el trabajo en el kernel. ¿Todavía tengo un resultado para c? He reinstalado cuda y usé make en los ejemplos y todos ellos pasan.

+0

Para los principiantes, tanto cudaMalloc como cudaMemcpy devuelven los códigos de resultado. Puede ser educativo imprimir cualquier cosa que no sea cudaSuccess. –

+0

@HenkHolterman sin suerte ... Soy realmente nuevo en Cuda, por lo que podría estar completamente equivocado, pero traté de crear un resultado si hay un error y no hay un mensaje sobre el error, pero los números han cambiado (incluso si puse un específico número en el núcleo, no se devuelve.) Actualicé el código, parece que el kernel ni siquiera se está utilizando. – Lostsoul

+0

Normalmente soy un creyente en "si ves huellas de pezuñas, piensas en caballos, no en cebras", pero no puedo encontrar nada de malo en esto ... ¿Cómo estás? GPU, versión CUDA, compilador, etc.? – trycatch

Respuesta

8

Básicamente hay dos problemas aquí:

  1. No está compilando el kernel para la arquitectura correcta (obtenida de comentarios)
  2. Su código contiene la comprobación de errores imperfecta que le falta el punto cuando el error de tiempo de ejecución está ocurriendo, dando lugar a síntomas misteriosos e inexplicables.

En la API de tiempo de ejecución, la mayoría de las acciones relacionadas con el contexto se realizan "de forma perezosa". Cuando se lanza un kernel por primera vez, la API de tiempo de ejecución invocará el código para encontrar inteligentemente una imagen CUBIN adecuada dentro de la imagen binaria grasa emitida por la cadena de herramientas para el hardware de destino y cargarla en el contexto. Esto también puede incluir la recopilación JIT de PTX para una arquitectura compatible hacia atrás, pero no al revés. Por lo tanto, si compiló un kernel para un dispositivo con capacidad informática 1.2 y lo ejecuta en un dispositivo de capacidad informática 2.0, el controlador puede compilar JIT el código PTX 1.x que contiene para la arquitectura más nueva. Pero lo contrario no funciona. Entonces, en su ejemplo, la API de tiempo de ejecución generará un error porque no puede encontrar una imagen binaria utilizable en la imagen de fatbinary de CUDA incrustada en el ejecutable. El mensaje de error es bastante críptico, pero obtendrá un error (consulte this question para obtener un poco más de información).

Si su código contenido de comprobación de errores como este:

cudaError_t err = cudaMalloc((void**)&dev_c, sizeof(int)); 
if(err != cudaSuccess){ 
    printf("The error is %s", cudaGetErrorString(err)); 
} 

add<<<1,1>>>(1, 4, dev_c); 
if (cudaPeekAtLastError() != cudaSuccess) { 
    printf("The error is %s", cudaGetErrorString(cudaGetLastError())); 
} 

cudaError_t err2 = cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost); 
if(err2 != cudaSuccess){ 
    printf("The error is %s", cudaGetErrorString(err)); 
} 

el error de las comprobaciones después del lanzamiento del kernel debe coger el API error de tiempo de ejecución generado por el fallo de la carga del núcleo/lanzamiento.

+1

Probablemente esta sea la mejor práctica para principiantes. Verifique el error en cada paso mientras aprende. Debería obtener un error con respecto a la arquitectura del dispositivo. – pQB

+3

También es la mejor práctica para profesionales :) Definitivamente para compilaciones de depuración, pero también dejaría los controles en versiones de lanzamiento. Si no se desean las comprobaciones en la compilación de lanzamiento, utilice el preprocesador para reemplazarlas con talones. –

1
#include <stdio.h> 
#include <conio.h> 
#include <cuda.h> 
#include <cuda_runtime.h> 
#include <device_launch_parameters.h> 


__global__ void Addition(int *a,int *b,int *c) 
{ 

    *c = *a + *b; 
} 
int main() 
{ 
    int a,b,c; 
    int *dev_a,*dev_b,*dev_c; 
    int size = sizeof(int); 

    cudaMalloc((void**)&dev_a, size); 
    cudaMalloc((void**)&dev_b, size); 
    cudaMalloc((void**)&dev_c, size); 

    a=5,b=6; 

    cudaMemcpy(dev_a, &a,sizeof(int), cudaMemcpyHostToDevice); 
    cudaMemcpy(dev_b, &b,sizeof(int), cudaMemcpyHostToDevice); 

    Addition<<< 1,1 >>>(dev_a,dev_b,dev_c); 
    cudaMemcpy(&c, dev_c,size, cudaMemcpyDeviceToHost); 

    cudaFree(&dev_a); 
    cudaFree(&dev_b); 
    cudaFree(&dev_c); 

    printf("%d\n", c); 
    getch(); 
    return 0; 
} 
Cuestiones relacionadas