今回は、以前に「OpenCLをクラスでラップしてみた」で今後の課題に挙げた「OpenCLソースが外部ファイルから読み取れないところ」を何とかしてみようと思う。ついでにOS間のファイルパス表記の違いを吸収するために「Boost::Filesystem」も利用することにした。
「OpenCLをクラスでラップしてみた」でのmain.cppに次の変更を行った。
#define __CL_ENABLE_EXCEPTIONS #include "OpenCL.hpp" #include <iostream> #include <boost/filesystem/fstream.hpp> const int nElements = 9000000; float input1[nElements]; float input2[nElements]; float output[nElements]; int main(int argc, char* argv[]) { namespace bfs = boost::filesystem; bfs::path srcPath("../../opencl_test/addVector.cl"); bfs::ifstream srcFile(srcPath); std::string buf; std::string src; while(std::getline(srcFile, buf)){ src.append(buf); } for(int i = 0; i < nElements; i++){ input1[i] = (float)i * 10.0f; input2[i] = (float)i / 20.0f; output[i] = 0.0f; } try{ DECS::OpenCL ocl; ocl.setSource(src); ocl.buildProgram(); ocl.setKernel(std::string("addVector")); ocl.setKernelInputArgument(0, input1, nElements); ocl.setKernelInputArgument(1, input2, nElements); ocl.setKernelOutputArgument(2, nElements); ocl.enqueueNDRange(nElements); ocl.readBuffer(2, output, nElements); for(int i = 0; i < 20; i++){ std::cout << "input1[" << i << "], input2[" << i << "], output[" << i << "] : "; std::cout << input1[i] << ", " << input2[i] << ", " << output[i] << std::endl; } }catch(cl::Error err){ std::cerr << "ERROR: " << err.what() << "(" << err.err() << ")" << std::endl; } return 0; }
まず、boost::filesystemのうちboost/filesystem/fstream.hppをインクルードする。これで、boost::filesystemに対応したファイル入出力ストリームを使用できる。また、boost::filesystemのnamespaceは長いので、適当に短くした。
次にOpenCLソースファイルのパス文字列を作成し、入力ストリームを生成する。
最後に行単位で読み込み、文字列srcにアペンドしてソース全体の文字列を生成している。
ちなみに読み込みに使用したソースは前回は文字列変数としてソース内に書いていた、次のコードを別ファイルとして保存している。
__kernel void addVector(__global const float *input1, __global const float *input2, __global float *output) { int index = get_global_id(0); output[index] = sin(input1[index]) * sin(input2[index]); output[index] = cos(output[index]); output[index] = pow(output[index], output[index]); }
別ファイルとした方が、変に改行文字を埋め込んだりしなくてもよく、またOpenCLソースのみ変更する際も、本体の再ビルドは不要となり、管理性がとてもよくなった。
後はこれをラップクラスのメソッドに追加すると、使い勝手が少し改善しそう。