Erreur de liaison LNK2005 lors de la tentative de compilation de plusieurs fichiers CUDA

J’ai un programme CUDA qui fonctionne bien, mais cela est actuellement écrit dans un seul fichier. J’aimerais diviser ce gros fichier en plusieurs plus petits, afin de faciliter la maintenance et la navigation.

La nouvelle structure est:

foo.cuh foo.cu bar.cuh bar.cu main.cu 

Les fichiers d’en-tête .cuh contiennent des structures et des prototypes de fonctions, et les fichiers .cu contiennent les définitions de fonctions (comme d’habitude). Le fichier principal inclut bar.cuh et bar.cu inclut foo.cuh . Tous les fichiers .cu incluent cutil_inline.h, afin de pouvoir utiliser les fonctions CUDA.

Par conséquent :

 // main.cu #include "bar.cuh" #include  int main() [...] // bar.cu #include "bar.cuh" #include "foo.cuh" #include  [...] // foo.cu #include "foo.cuh" #include  [...] 

Le problème est que lorsque je comstack mon projet Visual Studio 2008 avec cette nouvelle structure, des erreurs de liaison se multiplient:

 error LNK2005: "void __cdecl __cutilBankChecker(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,char *,int,char *,int)" (?__cutilBankChecker@@YAXIIIIIIPADH0H@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cutilCondition(int,char *,int)" (?__cutilCondition@@YAXHPADH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cutilExit(int,char * *)" (?__cutilExit@@YAXHPAPAD@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "int __cdecl cutGetMaxGflopsDeviceId(void)" (?cutGetMaxGflopsDeviceId@@YAHXZ) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeCallNoSync(enum cudaError,char const *,int)" (?__cudaSafeCallNoSync@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeCall(enum cudaError,char const *,int)" (?__cudaSafeCall@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeThreadSync(char const *,int)" (?__cudaSafeThreadSync@@YAXPBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cufftSafeCall(enum cufftResult_t,char const *,int)" (?__cufftSafeCall@@YAXW4cufftResult_t@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj 

Je comprends ce qu’ils veulent dire (tous les symboles déjà définis font partie de cutil_inline.h) mais je dois inclure cet en-tête dans tous les fichiers, sinon il ne comstack pas. Qu’est-ce que je fais mal ?

UPDATE: Pour clarifier la situation: * avec tout le code dans un seul gros fichier, il comstack, lie et fonctionne bien * avec la nouvelle structure (plusieurs fichiers plus petits) et en incluant cutil_inline.h dans tous les fichiers .cu, il comstack correctement mais échoue la liaison * avec la nouvelle structure et l’inclusion de cutil_inline.h uniquement dans le fichier principal, échouent lors de la compilation, indiquant que la fonction cutil est inconnue dans les fichiers où cutil_inline.h n’était pas inclus (comme prévu, mais j’ai dû tout essayer) – Élément de liste

Cette erreur s’est également produite dans mon programme. Je l’ai résolu en ajoutant le mot clé inline avant __global__ ou __device__ . Ensuite, l’erreur est partie.

D’une manière ou d’une autre, les fonctions de cutil_inline.h ne sont pas marquées comme “inline” lorsqu’elles sont compilées.

Si vous rencontrez cette erreur dans un projet normal non Cuda C ++, la réponse serait simplement que vous avez des définitions de fonction (pas seulement des déclarations) dans le fichier d’en-tête et que le mot clé “inline” est manquant.

Vous devrez peut-être générer la sortie des fichiers .i correspondants (pré-processeur) pour vraiment voir ce qui se passe après le développement de toutes les macros.

EDIT 1/2/2009

Si vous ne pouvez pas comprendre ce qui ne va pas simplement en lisant les fichiers .h, à cause de l’obscurcissement du développement d’une macro, voici comment vous générez le fichier .i:

  1. Dans la fenêtre Visual Studio “Solution Explorer”, cliquez avec le bouton droit de la souris sur le fichier source et choisissez “Propriétés”.

  2. Dans l’arborescence des propriétés, sélectionnez “C / C ++”, “Préprocesseur”.

  3. Remplacez “Non” par “Générer un fichier prétraité” par l’une des autres options.

  4. Puis comstackz le fichier. Le compilateur écrira la sortie du préprocesseur dans un fichier, puis s’arrêtera sans réellement comstackr. Vous pouvez voir dans le fichier .i produit quel est le résultat final de toutes les extensions de macros.

  5. Vous devrez revenir en arrière et réinitialiser cette propriété sur “Non” afin que le projet compilateur fonctionne à nouveau correctement.

Avez-vous besoin de vous connecter à la bibliothèque cutil (par exemple, cutil32D.lib pour le débogage 32 bits, etc.)?

Pour une raison quelconque, vous avez plusieurs définitions. Utilisez-vous le fichier NVIDIA Cuda.rules pour permettre à Visual Studio de comstackr vos fichiers .cu en fichiers .obj? Il semble que vous ayez modifié les règles pour lier avec cutil, alors que vous devez utiliser les règles NVIDIA Cuda.rules pour indiquer à VS comment comstackr .cu en .obj, puis modifier les propriétés standard de l’ éditeur de liens pour extraire la bibliothèque cutil.