Включить индексацию кода Cuda в Clion

Я использую Clion для разработки программы cuda. Выделение кода отлично работает, когда расширение .h. Однако, когда он изменяется на .cuh, Clion просто считают новый файл текстовым файлом, и я не смог включить выделение кода. Я понимаю, полный набор инструментов CUDA и речи, поэтому я не буду надеяться Clion для разбора заявления типа файл mykernel>>. Тем не менее, я буду более чем доволен, если он сможет разобрать файл так же, как разбор обычного заголовка / cpp файл.

большое спасибо

6 ответов


щелкните правой кнопкой мыши файл в окне инструмента проекта - > связать с типом файла - > C++

однако Clion официально не поддерживает cuda, он не может анализировать синтаксис cuda.


спасибо! Я добавил больше "поддельных" деклараций, чтобы Клион мог лучше анализировать 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

во-первых, убедитесь, что вы говорите Клион лечить .cu и .cuh файлы как C++, с помощью File Types меню Настройки.

CLion не может анализировать расширения языка CUDA, но он предоставляет макрос препроцессора, который определяется только тогда, когда clion анализирует код. Вы можете использовать это для реализации почти полной поддержки CUDA самостоятельно.

большая часть проблемы заключается в том, что парсер CLion сходит с рельсов по ключевым словам, таким как __host__ или __device__, заставляя его не делать вещи, которые он иначе знает, как делать: Fail

Клион не понял Dtype в этом примере, потому что материал CUDA запутал его разбор.

самое минимальное решение этой проблемы-дать макросам препроцессора clion игнорировать новые ключевые слова, исправляя худшее из сломанности:

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

это исправляет приведенный выше пример:

Yay!

однако, функции CUDA как __syncthreads, __popc все равно не удастся проиндексировать. Так будет CUDA builtins, как threadIdx. Один из вариантов-предоставить бесконечные макросы препроцессора (или даже определения структуры) для них, но это уродливо и жертвует безопасностью типов.

если вы используете интерфейс CUDA Clang, вы можете сделать лучше. Clang реализует неявно определенные встроенные CUDA, определяя их в заголовках, которые затем включаются при компиляции кода. Они дают определения таких вещей, как threadIdx. От притворяясь препроцессором компилятора CUDA и включая device_functions.h, мы можем сделать __popc и друзьям на работу тоже:

#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__

это позволит вам идеально индексировать практически весь код CUDA. Клион даже изящно справляется с <<<...>>> синтаксис. Он помещает маленькую красную линию под одним символом на каждом конце блока запуска, но в остальном рассматривает его как вызов функции - что совершенно нормально:

Launch


Если вы хотите, чтобы Клион проанализировал все ваши .cu файлы as .cpp или любой другой поддерживаемый тип файла, вы можете сделать это:

  1. перейти к файлу - > настройки - > редактор - > типы файлов
  2. выберите тип файла, который вы хотите проанализировать, как в первом столбце (.cpp)
  3. щелкните знак "плюс" второго столбца и писать *.КР

  4. нажмите apply и clion будет анализировать все ваши .cu файлы, поскольку это был тип файла, указанный в верхнем столбец.( cpp)

вы можете увидеть больше документации здесь


я расширил ответ используя метод, найденный в ответ чтобы обеспечить более полный макрос разбора, теперь вы можете иметь .x, .y и .z работайте правильно без проблемы и используйте сетку dim. В дополнение к этому я обновил список, чтобы включить большинство встроенных и значений, найденных в руководство по документации CUDA 8.0. Обратите внимание, что это должно иметь полную совместимость с C++ и, возможно, C. Это не имеет всех функций учитывается (отсутствует атомика, математические функции (просто включают математику.ч для большинства), текстура, поверхность, времени, деформации votie и перемешать, утверждение, запуск по часам, и видео-функции)

#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

я обнаружил, что clion, похоже, индексирует все цели сборки, а не только цель, которую вы выбрали для сборки. Моя стратегия заключалась в том, чтобы сделать .cpp символические ссылки из моего .cu файлы и сделать дочерний clion / cmake c++ целевой сборки (только для индексирования), который ссылается на них .СРР ссылки. Этот подход, похоже, работает над небольшими проектами cuda/thrust c++11 в clion 2017.3.3 в Unbuntu 16.04.3.

Я делаю это:

  • зарегистрировать .cu / cuh файлы с clion, как в другие ответы
  • добавьте макрос вуду cuda/clion в мой .файлы cu, как и в других ответах (позиция Вуду может быть важна, но я еще не сталкивался с какими-либо проблемами)
  • сделать .СРР./HPP символические ссылки на ваш .cu/.cuh файлы в каталоге проекта
  • создайте новую папку с одним файлом с именем clionShadow / CMakeLists.txt, который содержит:
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})
  • добавить зависимость clionShadow / CMakeLists.txt в конце ваших основных CMakeLists.txt с такой строкой:
add_subdirectory(clionShadow)

теперь clion анализирует и индексы кода .cu файлы "через".cpp-файлы.

помните, cudaNoBuild цель не для дома - это использовать C++ компиляторов, которые не будут работать. Если вы внезапно получаете ошибки компиляции, проверьте целевые настройки сборки clion - я заметил, что иногда он смешивает и соответствует текущим настройкам сборки между проект. В этом случае перейдите в диалоговое окно Edit_Configurations в меню Выполнить и убедитесь, что clion не изменил target_executable, чтобы быть из цели cudaNoBuild.

Edit: Гах! После восстановления кэша CMake и ide после обновления до clion 2017.3.3 вещи на самом деле не работают так, как они делали раньше. Индексирование работает только для .cpp-файлы и точки останова работают только для .файлы cu.