投稿日
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;
}
最近のコメント
たかたむ
はじめまして。初リアルフォース(R3ですが)で,同…
nokiyameego
ZFS poolのデバイスラベル破損で悩んていたと…
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…