web-dev-qa-db-fra.com

Activer l'indexation du code de Cuda dans Clion

J'utilise Clion pour développer un programme cuda. La surbrillance du code fonctionne bien lorsque l’extension est .h. Cependant, lorsqu'il est modifié en .cuh, Clion considère simplement le nouveau fichier comme un fichier texte brut et je n'ai pas été en mesure d'activer le surlignage de code. Je comprends qu’une chaîne complète d’outils Cuda est hors de question, je n’espère donc pas que Clion analysera des énoncés tels que mykernel <<< 1024, 100 >>>. Néanmoins, je serai plus que satisfait s'il peut analyser le fichier, tout comme l'analyse d'un fichier en-tête/cpp normal.

Merci beaucoup

7
Ran Wang

Cliquez avec le bouton droit sur le fichier dans la fenêtre de l'outil de projet -> Associer à un type de fichier -> C++

Cependant, Clion ne prend pas officiellement en charge cuda, il ne peut pas analyser la syntaxe de cuda.

4
halfelf

Tout d’abord, assurez-vous de dire à CLion de traiter les fichiers .cu et .cuh en tant que C++ à l’aide du menu de configuration File Types.

Clion n'est pas en mesure d'analyser les extensions de langage de CUDA, mais fournit une macro de préprocesseur définie uniquement lorsque Clion analyse le code. Vous pouvez vous en servir pour mettre en place vous-même le support CUDA presque complet.

Une grande partie du problème est que l'analyseur de CLion est déraillé par des mots-clés tels que __Host__ ou __device__, ce qui l'empêche de faire des choses qu'il sait sinon faire:  Fail

CLion n'a pas compris Dtype dans cet exemple, car les éléments CUDA ont confondu son analyse.

La solution la plus simple à ce problème consiste à donner aux macros du préprocesseur clion la possibilité d’ignorer les nouveaux mots-clés, ce qui résoudra le pire des problèmes:

#ifdef __JETBRAINS_IDE__
    #define __Host__
    #define __device__
    #define __shared__
    #define __constant__
    #define __global__
#endif

Cela corrige l'exemple ci-dessus:

 Yay!

Cependant, les fonctions CUDA telles que __syncthreads, __popc ne parviendront toujours pas à indexer. De même que CUDA sera construit comme threadIdx. Une option consiste à fournir une infinité de macros de préprocesseur (ou même de définitions de structure), mais c'est moche et sacrifie la sécurité de type.

Si vous utilisez l'interface CUDA de Clang, vous pouvez faire mieux. Clang implémente les composants CUDA définis de manière implicite en les définissant dans des en-têtes, qu’il inclut ensuite lors de la compilation de votre code. Celles-ci fournissent des définitions d'éléments tels que threadIdx. En prétendant être le préprocesseur du compilateur CUDA et en incluant device_functions.h, nous pouvons également obtenir __popc et des amis au travail:

#ifdef __JETBRAINS_IDE__
    #define __Host__
    #define __device__
    #define __shared__
    #define __constant__
    #define __global__

    // This is slightly mental, but gets it to properly index device function calls like __popc and whatever.
    #define __CUDACC__
    #include <device_functions.h>

    // These headers are all implicitly present when you compile CUDA with clang. Clion doesn't know that, so
    // we include them explicitly to make the indexer happy. Doing this when you actually build is, obviously,
    // a terrible idea :D
    #include <__clang_cuda_builtin_vars.h>
    #include <__clang_cuda_intrinsics.h>
    #include <__clang_cuda_math_forward_declares.h>
    #include <__clang_cuda_complex_builtins.h>
    #include <__clang_cuda_cmath.h>
#endif // __JETBRAINS_IDE__

Vous obtiendrez ainsi une indexation parfaite de pratiquement tout le code CUDA. CLion se comporte même avec grâce avec la syntaxe <<<...>>>. Il met une petite ligne rouge sous un caractère à chaque extrémité du bloc de lancement, mais le traite sinon comme un appel de fonction - ce qui convient parfaitement:

 Launch

11
Chris Kitching

Merci! J'ai ajouté plus de "fausses" déclarations pour permettre à CLion de mieux analyser CUDA:

#ifdef __JETBRAINS_IDE__
#define __CUDACC__ 1
#define __Host__
#define __device__
#define __global__
#define __forceinline__
#define __shared__
inline void __syncthreads() {}
inline void __threadfence_block() {}
template<class T> inline T __clz(const T val) { return val; }
struct __cuda_fake_struct { int x; };
extern __cuda_fake_struct blockDim;
extern __cuda_fake_struct threadIdx;
extern __cuda_fake_struct blockIdx;
#endif
8
Chris Olivier

si vous souhaitez que Clion analyse tous vos fichiers .cu au format .cpp ou tout autre type de fichier pris en charge, vous pouvez procéder comme suit:

  1. Allez dans Fichier -> Paramètres -> Editeur -> Types de fichiers
  2. Sélectionnez le type de fichier que vous souhaitez analyser, comme dans la première colonne (.cpp) 
  3. Cliquez sur le signe plus de la deuxième colonne et écrivez * .cu

  4. Appuyez sur Appliquer et Clion analysera tous vos fichiers .cu comme c’était le type de fichier que vous avez spécifié dans la colonne supérieure (.cpp). 

vous pouvez voir plus de documentation ici

3
Glacier11

J'ai développé cette réponse en utilisant la méthode décrite dans cette réponse pour fournir une macro d'analyse plus complète, vous pouvez maintenant faire fonctionner .x, .y et .z sans problème et utiliser grid dim. En plus de cela, j'ai mis à jour la liste pour inclure la plupart des valeurs intrinsèques et des valeurs trouvées dans le guide de documentation de CUDA 8.0 . Notez que cela devrait avoir une compatibilité totale en C++, et peut-être en C. Cela ne prend pas en compte toutes les fonctions (atomes manquants, fonctions mathématiques (incluez simplement math.h pour la plupart)), texture, surface, minutage, warp votie et shuffle, assertion, limites de lancement et fonction vidéo)

#ifdef __JETBRAINS_IDE__
    #include "math.h"
    #define __CUDACC__ 1
    #define __Host__
    #define __device__
    #define __global__
    #define __noinline__
    #define __forceinline__
    #define __shared__
    #define __constant__
    #define __managed__
    #define __restrict__  
    // CUDA Synchronization
    inline void __syncthreads() {};
    inline void __threadfence_block() {};
    inline void __threadfence() {};
    inline void __threadfence_system();
    inline int __syncthreads_count(int predicate) {return predicate};
    inline int __syncthreads_and(int predicate) {return predicate};
    inline int __syncthreads_or(int predicate) {return predicate};
    template<class T> inline T __clz(const T val) { return val; }
    template<class T> inline T __ldg(const T* address){return *address};
    // CUDA TYPES
    typedef unsigned short uchar;
    typedef unsigned short ushort;
    typedef unsigned int uint;
    typedef unsigned long ulong;
    typedef unsigned long long ulonglong;
    typedef long long longlong;

    typedef struct uchar1{
        uchar x;
    }uchar1;

    typedef struct uchar2{
        uchar x;
        uchar y;
    }uchar2;

    typedef struct uchar3{
        uchar x;
        uchar y;
        uchar z;
    }uchar3;

    typedef struct uchar4{
        uchar x;
        uchar y;
        uchar z;
        uchar w;
    }uchar4;

    typedef struct char1{
        char x;
    }char1;

    typedef struct char2{
        char x;
        char y;
    }char2;

    typedef struct char3{
        char x;
        char y;
        char z;
    }char3;

    typedef struct char4{
        char x;
        char y;
        char z;
        char w;
    }char4;

    typedef struct ushort1{
        ushort x;
    }ushort1;

    typedef struct ushort2{
        ushort x;
        ushort y;
    }ushort2;

    typedef struct ushort3{
        ushort x;
        ushort y;
        ushort z;
    }ushort3;

    typedef struct ushort4{
        ushort x;
        ushort y;
        ushort z;
        ushort w;
    }ushort4;

    typedef struct short1{
        short x;
    }short1;

    typedef struct short2{
        short x;
        short y;
    }short2;

    typedef struct short3{
        short x;
        short y;
        short z;
    }short3;

    typedef struct short4{
        short x;
        short y;
        short z;
        short w;
    }short4;

    typedef struct uint1{
        uint x;
    }uint1;

    typedef struct uint2{
        uint x;
        uint y;
    }uint2;

    typedef struct uint3{
        uint x;
        uint y;
        uint z;
    }uint3;

    typedef struct uint4{
        uint x;
        uint y;
        uint z;
        uint w;
    }uint4;

    typedef struct int1{
        int x;
    }int1;

    typedef struct int2{
        int x;
        int y;
    }int2;

    typedef struct int3{
        int x;
        int y;
        int z;
    }int3;

    typedef struct int4{
        int x;
        int y;
        int z;
        int w;
    }int4;

    typedef struct ulong1{
        ulong x;
    }ulong1;

    typedef struct ulong2{
        ulong x;
        ulong y;
    }ulong2;

    typedef struct ulong3{
        ulong x;
        ulong y;
        ulong z;
    }ulong3;

    typedef struct ulong4{
        ulong x;
        ulong y;
        ulong z;
        ulong w;
    }ulong4;

    typedef struct long1{
        long x;
    }long1;

    typedef struct long2{
        long x;
        long y;
    }long2;

    typedef struct long3{
        long x;
        long y;
        long z;
    }long3;

    typedef struct long4{
        long x;
        long y;
        long z;
        long w;
    }long4;

    typedef struct ulonglong1{
        ulonglong x;
    }ulonglong1;

    typedef struct ulonglong2{
        ulonglong x;
        ulonglong y;
    }ulonglong2;

    typedef struct ulonglong3{
        ulonglong x;
        ulonglong y;
        ulonglong z;
    }ulonglong3;

    typedef struct ulonglong4{
        ulonglong x;
        ulonglong y;
        ulonglong z;
        ulonglong w;
    }ulonglong4;

    typedef struct longlong1{
        longlong x;
    }longlong1;

    typedef struct longlong2{
        longlong x;
        longlong y;
    }longlong2;

    typedef struct float1{
        float x;
    }float1;

    typedef struct float2{
        float x;
        float y;
    }float2;

    typedef struct float3{
        float x;
        float y;
        float z;
    }float3;

    typedef struct float4{
        float x;
        float y;
        float z;
        float w;
    }float4;  

    typedef struct double1{
        double x;
    }double1;

    typedef struct double2{
        double x;
        double y;
    }double2;

    typedef uint3 dim3;

    extern dim3 gridDim;
    extern uint3 blockIdx;
    extern dim3 blockDim;
    extern uint3 threadIdx;
    extern int warpsize;
#endif
3
opa

J'ai constaté que clion semble indexer toutes les cibles de construction, et pas seulement la cible que vous avez sélectionnée. Ma stratégie a consisté à créer des liens symboliques .cpp à partir de mes fichiers .cu et à créer une cible de construction enfant clion/cmake c ++ (pour l'indexation uniquement) faisant référence à ces liens .cpp. Cette approche semble fonctionner sur de petits projets cuda/thrust c ++ 11 de la version 2017.3.3 à Unbuntu 16.04.3.

Je le fais par:

  • enregistrez les fichiers .cu/cuh avec clion, comme dans les autres réponses
  • ajoutez la macro cuda/clion voodoo à mes fichiers .cu, comme dans les autres réponses (la position du voodoo peut être importante, mais je n'ai pas encore rencontré de problèmes)
  • créer des liens symboliques .cpp/.hpp vers vos fichiers .cu/.cuh dans le répertoire de votre projet
  • créez un nouveau dossier avec le fichier unique nommé clionShadow/CMakeLists.txt qui contient:
cmake_minimum_required(VERSION 3.9)
project(cudaNoBuild)
set(CMAKE_CXX_STANDARD 11)
add_executable(cudaNoBuild ../yourcudacode.cpp ../yourcudacode.hpp)
target_include_directories(cudaNoBuild PUBLIC ${CUDA_INCLUDE_DIRS})
  • ajoutez une dépendance à clionShadow/CMakeLists.txt à la fin de votre CMakeLists.txt principal avec une ligne comme celle-ci:
add_subdirectory(clionShadow)

Désormais, clion analyse et indexe les fichiers .cu 'à travers' les fichiers .cpp.

N'oubliez pas que la cible cudaNoBuild n'est pas destinée à la construction - elle utilisera la chaîne d'outils c ++ qui ne fonctionnera pas. Si vous rencontrez soudainement des erreurs de compilation, vérifiez les paramètres de la cible de génération de clion - j'ai remarqué qu'elle mélange et fait parfois correspondre les paramètres de construction actuels entre les projets. Dans ce cas, ouvrez la boîte de dialogue Edit_Configurations du menu Run et assurez-vous que clion n'a pas modifié le fichier target_executable pour qu'il soit issu de la cible cudaNoBuild.

Edit: Gah! Lors de la reconstruction du cache CMake et ide après une mise à jour de clion 2017.3.3, les choses ne fonctionnent pas vraiment comme avant. L'indexation ne fonctionne que pour les fichiers .cpp et les points d'arrêt ne fonctionnent que pour les fichiers .cu.

0
user968363