2017-08-26 4 views
0

Si j'exécutez la commande suivante:Pourquoi est-ce que je peux ignorer la "liaison de code de périphérique" avec un éditeur de liens non-nvcc?

c++ -c --std=c++11 $(includes) -o src/main.o src/main.cpp 
nvcc -c -m64 -arch=sm_30 --std=c++11 $(includes) -o src/kernels/add.o src/kernels/add.cu 
ar qc src/kernels/libkernels.a src/kernels/add.o 
ranlib src/kernels/libkernels.a 
c++ -o program -L/usr/local/cuda/lib64 src/main.o src/kernels/libkernels.a -lcudart -lcudadevrt 

Il fonctionne. Ne devrait-il pas échouer parce que je n'ai pas effectué une phase -dlink? Le Parallel4All blog entry on separate compilation dit:

Lorsque vous utilisez nvcc pour créer un lien, il n'y a rien de spécial à faire: remplacer votre commande normale du compilateur avec nvcc et il prendra soin de toutes les étapes nécessaires. Toutefois, vous pouvez choisir d'utiliser un pilote de compilateur autre que nvcc (tel que g++) pour l'étape de liaison finale. Puisque votre compilateur de CPU ne saura pas comment lier le code de l'appareil CUDA, vous devrez ajouter une étape dans votre build pour que le code de l'appareil CUDA soit nvcc, en utilisant l'option nvcc –dlink.

nvcc –arch=sm_20 –dlink v3.o particle.o main.o –o gpuCode.o 

Ceci lie tout le code objet de l'appareil et le place dans gpuCode.o. Notez que cela ne lie pas le code objet CPU. En fait, le code d'objet CPU dans v3.o, particle.o et main.o est ignoré dans cette étape. Pour compléter le lien vers un exécutable, nous pouvons utiliser ld ou g ++.

g++ gpuCode.o main.o particle.o v3.o –lcudart –o app 

Est-ce que l'utilisation d'une bibliothèque .a en quelque sorte compenser le manque de « code de dispositif de liaison »?

PS - J'utilise CUDA 8.0.61 sur Linux Mint 18,2

Répondre

3

liaison de code de l'appareil n'est pas nécessaire dans tous les scénarios. (Cela doit être vrai, car avant CUDA 5.0 il n'y avait pas de liaison de code de périphérique.)

La liaison de code de périphérique est requise dans un certain nombre de scénarios, le plus souvent lorsque la liaison du code de périphérique doit se produire entre différentes unités de compilation. Cela signifie que le code de l'appareil dans un module (, fichier, unité de compilation) appelle le code de l'appareil dans un autre module (, fichier, unité de compilation).

Je peux dire pertinemment que ce scénario n'est pas présent dans votre cas, car il y a un seul module (, fichier, unité de compilation) de la vôtre qui contient un code de l'appareil:

nvcc -c -m64 -arch=sm_30 --std=c++11 $(includes) -o src/kernels/add.o src/kernels/add.cu 

                     ^^ 
                   only one file here 

Je sais cela est vrai, car toute tentative de compilation d'un code de périphérique par un compilateur de code hôte ordinaire autre que nvcc lancera des erreurs de syntaxe. Comme cela ne se produit pas dans votre cas, et que vous n'avez qu'un seul fichier pouvant contenir du code de périphérique, vous ne pouvez pas avoir de scénario dans lequel la liaison de code de périphérique est requise, donc votre méthode fonctionne.

Même si vous aviez par exemple plusieurs fichiers .cu, vous n'avez peut-être toujours pas besoin de liaison de périphérique si aucun code de périphérique dans un fichier appelé code de périphérique (ou variables de périphérique référencées) dans un autre fichier.

Le manuel relevant section du manuel nvcc couvre plus en détail le problème de la liaison de code de périphérique.