recurso no válido en un proyecto de windows cuda

He portado un proyecto cuda de Linux a Windows (básicamente solo agregué algunas definiciones y typedefs en el archivo de encabezado). Estoy usando Visual Studio 2008 y las reglas de compilación personalizadas de cuda runtime api del SDK. El código es c, no c ++ (y estoy compilando / TC no / TP)

Tengo problemas de alcance que no tenía en Linux. Las variables globales en mi archivo de encabezado no se comparten entre los archivos .cy los archivos .cu.

Creé un proyecto simplificado y aquí está todo el código:

main.h:

#ifndef MAIN_H
#define MAIN_H

#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime.h>

cudaEvent_t cudaEventStart;

#if defined __cplusplus
extern "C" void func(void);
#else
extern void func(void);
#endif

#endif

C Principal:

#include "main.h"

int main(void)
{
    int iDevice = 0;

    cudaSetDevice(iDevice);
    cudaFree(0);
    cudaGetDevice(&iDevice);
    printf("device: %d\n", iDevice);

    cudaEventCreate(&cudaEventStart);
    printf("create event: %d\n", (int) cudaEventStart);

    func();

    cudaEventDestroy(cudaEventStart);
    printf("destroy event: %d\n", (int) cudaEventStart);

    return cudaThreadExit();
}

kernel.cu:

#include "main.h"

void func()
{
    printf("event in cu: %d\n", (int) cudaEventStart);
}

salida:

device: 0
create event: 44199920
event in cu: 0
event destroy: 441999920

¿Alguna idea sobre lo que estoy haciendo mal aquí? ¿Cómo necesito cambiar mi configuración para que funcione en Visual Studio? Idealmente, me gustaría una configuración que funcione en múltiples plataformas.

CUDA 3.2, GTX 480, 64 bits Win7, 263.06 general

preguntado el 16 de mayo de 11 a las 19:05

2 Respuestas

Que estas tratando de hacer

  1. No funcionaría incluso sin CUDA: intente cambiar el nombre de kernel.cu a kernel.cy vuelva a compilar. Obtendrá un error del vinculador porque cudaEventStart se definirá de forma múltiple, en cada unidad de compilación (archivo .c) que lo incluya. Debería convertir la variable en estática e inicializarla en una sola unidad de compilación.
  2. Se compila en CUDA porque CUDA no tiene un enlazador y, por lo tanto, el código en las unidades de compilación compiladas por nvcc (archivos .cu) no puede hacer referencia a símbolos en otras unidades de compilación. Actualmente, CUDA no admite variables globales estáticas. En el futuro, CUDA tendrá un enlazador, pero actualmente no lo tiene.

Lo que está sucediendo es que cada unidad de compilación está obteniendo su propia instancia no conflictiva de cudaEventStart.

Lo que puede hacer es deshacerse de la variable global (convertirla en una variable local en main()), agregue los parámetros cudaEvent_t a las funciones que necesitan usar el evento y luego pase la variable de evento.

Por cierto, en su segunda publicación, tiene circular #includes ...

contestado el 17 de mayo de 11 a las 06:05

@harrism gracias por esto. estás insinuando que esta configuración no funcionará pase lo que pase, pero funciona en mi versión de Linux. En segundo lugar, ¿los protectores de inclusión no impiden la inclusión circular? de hecho, en mi proyecto real, el encabezado también incluye guardias. - jmilloy

@harrism ¿es posible que los guardias de inclusión funcionen de manera diferente en linux y visual studio? Quizás en Visual Studio, nvcc no puede ver las definiciones de cl.exe y viceversa, lo que da como resultado dos instancias de cudaEventStart. Mientras que en Linux, el guardia funciona en ambos compiladores, evitando las instancias dobles de todas mis variables globales. - jmilloy

No estoy insinuando, estoy afirmando. :) No puede compartir variables globales entre unidades de compilación CUDA y unidades de compilación C ++ de esta manera actualmente. Si cambia el nombre de kernel.cu a kernel.c como sugerí, obtiene un error del enlazador como: "ld: símbolo duplicado _foo en ..." de g ++. En cuanto a la circular, puede funcionar, pero no es una buena práctica de programación. Además, tenga en cuenta que los guardias de inclusión no funcionan en las unidades de compilación de ningún compilador, solo evitan que el mismo encabezado se incluya dos veces en la misma unidad de compilación. Cada archivo .co .cu es una unidad de compilación independiente. - harrismo

@harrism jaja ahora estamos siendo quisquillosos, pero eso me gusta. Cuando lo dices would not work even without CUDA entonces a mi me estas dando a entender que no funciona con CUDA. Lo que, de hecho, hace. Pero solo en linux. (Además, no estoy usando g ++ porque esto está en c). - jmilloy

Es posible que desee mirar esta respuesta lo que explica por qué las variables globales no estáticas en los encabezados son malas. También puede darte la idea de que puedes declarar las variables extern, pero desafortunadamente, como expliqué, eso no funcionará para el código de dispositivo CUDA ya que no tiene un enlazador. Eso podría trabajar para el código de host en un archivo .cu. - harrismo

Modifiqué mi ejemplo simplificado (con éxito) al incluir el archivo .cu en el encabezado y eliminar las declaraciones de avance de la función de archivo .cu.

main.h:

#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime.h>

#include "kernel.cu"

cudaEvent_t cudaEventStart;

C Principal:

#include "main.h"

int main(void)
{
    int iDevice = 0;

    cudaSetDevice(iDevice);
    cudaFree(0);
    cudaGetDevice(&iDevice);
    printf("device: %d\n", iDevice);

    cudaEventCreate(&cudaEventStart);
    printf("create event: %d\n", (int) cudaEventStart);

    func();

    cudaEventDestroy(cudaEventStart);
    printf("destroy event: %d\n", (int) cudaEventStart);

    return cudaThreadExit();
}

kernel.cu:

#ifndef KERNEL_CU
#define KERNEL_CU

#include "main.h"

void func(void);

void func()
{
    printf("event in cu: %d\n", (int) cudaEventStart);
}

#endif

salida:

device: 0
create event: 42784024
event in cu: 42784024
event destroy: 42784024

A punto de ver si funciona en mi proyecto real y si la solución es portátil para Linux.

contestado el 17 de mayo de 11 a las 02:05

Y la encuesta dice, no ... después de muchas variaciones, el archivo .cu en mi proyecto real no se compila. blockDim undefined idenfifier, __syncthreads undefined, etc - jmilloy

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.