投稿日
2013/5/20 月曜日
前回ホストコードをC++で書いたが、CのAPIを使っていたためC++らしさはあまり表現出来ていなかった。
あれから、OpenCL APIのC++ Wrapper(OpenCL C++ Bindings)というものの存在を知ったので、それを使って前回のホストコードをさらにC++っぽく書き換えてみた。
ソース(ホストコードのみ)はこの記事の最後に載せてある。
C++で開発する際は、このWrapperがあるとかなり楽になる。
例外が使えるので、エラーチェックのためのコードを逐一挿入する必要がないし、デストラクタで各種リソースが解放されるようになってるため、基本的にその辺りを気にしなくて良い。
カーネルもC++で書けるといいのに。(環境の限定なしで。)
以下ソース。
#include <iostream> #include <vector> #include <string> #define __CL_ENABLE_EXCEPTIONS #include "cl.hpp" int main(int argc, const char * argv[]) { // プラットフォーム一覧を取得 std::vector<cl::Platform> platforms; cl::Platform::get(&platforms); if (platforms.size() == 0) { std::cerr << "No platform.\n"; return EXIT_FAILURE; } // 見つかったプラットフォームの情報を印字 std::cout << platforms.size() << " platform(s) found.\n"; for (auto p : platforms) { std::cout << "Platform: " << p.getInfo<CL_PLATFORM_NAME>() << "\n"; std::cout << "Vendor: " << p.getInfo<CL_PLATFORM_VENDOR>() << "\n"; std::cout << "Version: " << p.getInfo<CL_PLATFORM_VERSION>() << "\n"; std::cout << "Profile: " << p.getInfo<CL_PLATFORM_PROFILE>() << "\n"; std::cout << "\n"; } // デバイス一覧を取得 std::vector<cl::Device> devices; platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices); if (devices.size() == 0) { std::cerr << "No device.\n"; return EXIT_FAILURE; } // 見つかったデバイスの情報を印字 std::cout << devices.size() << " device(s) found.\n"; for (auto d : devices) { std::cout << "Device: " << d.getInfo<CL_DEVICE_NAME>() << "\n"; std::cout << "Vendor: " << d.getInfo<CL_DEVICE_VENDOR>() << "\n"; std::cout << "Version: " << d.getInfo<CL_DEVICE_VERSION>() << "\n"; std::cout << "Profile: " << d.getInfo<CL_DEVICE_PROFILE>() << "\n"; std::cout << "\n"; } // コンテキストの作成 cl::Context ctx(devices); // コンパイル済みclプログラムの読み込み std::string bitcode_path = "OpenCL/kernel.cl.gpu_32.bc"; cl::Program program = cl::Program(ctx, devices, { {bitcode_path.c_str(), bitcode_path.length()} }); // プログラムのビルド program.build(devices); // カーネルの作成 cl::Kernel kernel(program, "addone"); // データを用意 int n = 1000; std::vector<float> h_data(n); for (int i = 0; i < n; i++) { h_data[i] = float(i); } // デバイスメモリを確保しつつデータをコピー cl::Buffer d_data(ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(float) * n, h_data.data()); // カーネルの引数をセット kernel.setArg(0, d_data); kernel.setArg(1, n); // コマンドキューの作成 cl::CommandQueue q(ctx, devices[0]); // カーネルの実行 cl::NDRange global(n, 1, 1); q.enqueueNDRangeKernel(kernel, cl::NullRange, global); // 結果を読み込み q.enqueueReadBuffer(d_data, CL_TRUE, 0, sizeof(float) * n, h_data.data()); // 結果の印字 for (int i = 0; i < n; i++) { std::cout << h_data[i] << ", "; } std::cout << "\n"; std::cout << "Done.\n"; return EXIT_SUCCESS; }
最近のコメント
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
peta_okechan
針金みたいなパーツを引っ張ると外れます。 他の方の…
虎徹ファン交換
虎徹の標準ファンを外す際に、どのようにして外されま…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…