注: この質問は、OpenCL 自体とは何の関係もありません。私の質問の簡潔な説明については、最後の段落を確認してください。しかし、いくつかの背景を提供するために:
OpenCL を利用する C++ コードを書いています。私は自分の OpenCL カーネルのソースを独自のファイルに保持して、コーディングとメンテナンスを容易にするのが好きです (関連する C++ コードにソースを文字列定数として直接埋め込むのではなく)。これは必然的に、バイナリを配布するときに OpenCL ランタイムにそれらをロードする方法の問題につながります。理想的には、OpenCL ソースがバイナリに含まれているため、バイナリが特定の場所にある必要はありません。 OpenCLソースコードがどこにあるかを知るために、いくつかのディレクトリ構造内で。
OpenCL ファイルを文字列定数としてどこかに含めたいと思います。できれば、追加のビルド手順や外部ツールを使用せずに (クロスコンパイラ/クロスプラットフォームの使いやすさのために...つまり、toxxd
などは使用しません)。このスレッドの 2 番目の回答に基づいて、次のようなテクニックを見つけたと思いました。
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
STRINGIFY
可能であれば、OpenCLコードにマクロを埋め込まないことをお勧めします(上記のSOの質問で行われたように)。現在、これは Clang/LLVM コンパイラで素晴らしく機能しますが、GCC は恐ろしい死に方をします (「マクロ STRINGIFY を呼び出す未終了の引数リスト」と、.cl ファイルの内容に関連するさまざまな構文「エラー」が表示されます)。したがって、明らかに、この正確な手法はコンパイラ間で使用できません (MSVC は試していませんが、そこでも動作するようにしたいと思います)...コンパイラ間で動作するように最小限にマッサージするにはどうすればよいですか?
要約すると、外部ツールを呼び出したり、余分なコードでファイルを汚染したりせずに、ファイルの内容を C/C++ 文字列定数として含めるための標準準拠の手法が必要です。アイデア?
EDIT : Potatoswatter が指摘したように、上記の動作は定義されていないため、文字列化されるファイルに触れることを含まない真のクロスコンパイラ プリプロセッサ手法はおそらく不可能です (凶悪なほとんど/すべてのコンパイラで機能するハックは回答ポイントを取得します)。興味深いことに、ここでの 2 番目の応答で提案されていることを実行することになりました...つまり、STRINGIFY
含めていた OpenCL ファイルにマクロを直接追加しました。
でsomefile.cl
:
STRINGIFY(
... // Lots of OpenCL code
)
でsomefile.cpp
:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
これは、私が試したコンパイラ (マクロ内にプリプロセッサ ディレクティブがないため、Clang と GCC も同様) で機能し、少なくとも私のコンテキストでは負担が大きすぎません (つまり、そうではありません)。 t は、OpenCL ファイルの構文の強調表示/編集を妨げません)。このようなプリプロセッサ アプローチの特徴の 1 つは、隣接する文字列が連結されるため、次のように記述できることです。
inline const char* Kernels() {
static const char* kernels =
#include "utility_functions.cl"
#include "somefile.cl"
;
return kernels;
}
STRINGIFY マクロが両方のファイルにある限り.cl
、文字列が連結され、OpenCL コードをモジュール化できます。