Clionを使用してcudaプログラムを開発しています。拡張子が.hの場合、コードハイライトは正常に機能します。ただし、それを.cuhに変更すると、Clionは新しいファイルをプレーンテキストファイルと見なし、コードの強調表示を有効にすることができませんでした。完全なCudaツールチェーンは問題外であることを理解しているので、Clionがmykernel <<< 1024、100 >>>のようなステートメントを解析することを望みません。それでも、通常のヘッダー/ cppファイルを解析するのと同じようにファイルを解析できれば、私は十分満足します。
どうもありがとう
プロジェクトツールウィンドウでファイルを右クリック->ファイルタイプに関連付け-> C++
ただし、Clionは現在cudaを公式にサポートしていないため、cuda構文を解析できません。
まず、CLionに.cu
設定メニューを使用して.cuh
およびFile Types
ファイルをC++として扱うように指示してください。
CLionはCUDAの言語拡張を解析できませんが、clionがコードを解析しているときにのみ定義されるプリプロセッサーマクロを提供します。これを使用して、ほぼ完全なCUDAサポートを自分で実装できます。
問題の多くは、CLionのパーサーが__Host__
や__device__
のようなキーワードによって脱線しているために、他の方法ではわかっていることを実行できないということです:
この例では、CLionはDtype
を理解できませんでした。CUDAがその解析を混乱させたためです。
この問題の最小の解決策は、clionプリプロセッサマクロに新しいキーワードを無視させ、最悪の不具合を修正することです。
#ifdef __JETBRAINS_IDE__
#define __Host__
#define __device__
#define __shared__
#define __constant__
#define __global__
#endif
これは上記の例を修正します:
ただし、__syncthreads
、__popc
などのCUDA関数は引き続きインデックスに失敗します。 threadIdx
のようなCUDAビルトインも同様です。 1つのオプションは、これらに無限のプリプロセッサマクロ(またはstruct定義)を提供することですが、これは醜く、タイプセーフを犠牲にします。
ClangのCUDAフロントエンドを使用している場合は、もっとうまくできます。 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コードの完全なインデックスが作成されます。 CLionは<<<...>>>
構文にも適切に対応します。起動ブロックの両端にある1文字の下に小さな赤い線が表示されますが、それ以外の場合は関数呼び出しとして扱われます。これはまったく問題ありません。
ありがとう! CLionが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
私は this answer にあるメソッドを使用して拡張しました this answer にあるメソッドを使用して、より包括的な解析マクロを提供し、.x
、.y
および.z
問題なしで適切に動作し、グリッド薄暗くします。それに加えて、 CUDA 8.0ドキュメントガイド にあるほとんどの組み込み関数と値が含まれるようにリストを更新しました。これは完全なC++互換性を持つ必要があることに注意してください。これには、すべての機能が含まれているわけではありません(アトミックがない、数学関数(ほとんどの場合はmath.hが含まれている)、テクスチャ、サーフェス、タイミング、ワープボーティーとシャッフル、アサーション、起動境界、およびビデオ機能)
#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がすべての.cuファイルを.cppまたはその他のサポートされているファイルタイプとして解析するようにしたい場合は、次のようにします。
2番目の列のプラス記号をクリックし、*。cuと書き込みます。
[適用]を押すと、clionがすべての.cuファイルを解析します。これは、上の列(.cpp)で指定したファイルタイプでした。
あなたはより多くのドキュメントを見ることができます ここ
Clionは、ビルドするために選択したターゲットだけでなく、すべてのビルドターゲットのコードインデックスを作成しているようです。私の戦略は、.cuファイルから.cppシンボリックリンクを作成し、それらの.cppリンクを参照する子clion/cmake c ++ビルドターゲット(インデックス作成のみ)を作成することでした。このアプローチは、Unbuntu 16.04.3のclion 2017.3.3の小さなcuda/thrust c ++ 11プロジェクトで機能しているようです。
私はこれをします:
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})
add_subdirectory(clionShadow)
これで、clionは.cppファイルを解析してコードインデックスを付け、.cppファイルを「通し」ます。
CudaNoBuildターゲットはビルド用ではないことに注意してください。動作しないc ++ツールチェーンを使用します。突然コンパイルエラーが発生する場合は、clionのビルドターゲット設定を確認してください。プロジェクト間で現在のビルド設定が混在している場合があることに気付きました。この場合、[実行]メニューの[編集_構成]ダイアログに移動し、clionがtarget_executableをcudaNoBuildターゲットからのものに変更していないことを確認します。
編集:ゲー! clion 2017.3.3へのアップデート後にCMakeおよびideキャッシュを再構築すると、以前のように実際に機能していません。インデックス作成は.cppファイルに対してのみ機能し、ブレークポイントは.cuファイルに対してのみ機能します。