OpenCL/Wrapper
OclWrap.h
#if !defined( OCLPROJ_COMMON_INCLUDED_OCL_WRAP_H )
# define OCLPROJ_COMMON_INCLUDED_OCL_WRAP_H
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
#include <CL/cl.hpp>
// クラスの前方宣言。 //
namespace CLWRAP {
//========================================================================
//
// ErrCode.
//
/**
** エラーコード型。
**/
typedef enum {
ERR_SUCCESS = 0, /**< 正常終了。 **/
ERR_FAILURE = 1, /**< 異常終了。 **/
ERR_FILE_NOT_FOUND = 2, /**< ファイルが見つからない。 **/
} ErrCode;
//========================================================================
//
// OclWrap class.
//
/**
** ラッパークラス。
**/
class OclWrap
{
//========================================================================
//
// 初期化と終了。
//
public:
//----------------------------------------------------------------
/** インスタンスを初期化する。
**
** @param[out] os ログ出力用ストリーム。
** @return エラーコードを返す。
** - 異常終了時はエラーの種類を示す非ゼロ値を返す。
** - 正常終了の場合はゼロを返す。
**/
const ErrCode
setupInstance(
std::ostream &os);
//----------------------------------------------------------------
/** インスタンスの後始末をする。
**
** @return エラーコードを返す。
** - 異常終了時はエラーの種類を示す非ゼロ値を返す。
** - 正常終了の場合はゼロを返す。
**/
const ErrCode
clearInstance();
//========================================================================
//
// プログラムの読み込みとカーネルの準備。
//
public:
//----------------------------------------------------------------
/** ソースファイルを指定する。
**
** @param [in] filename ファイル名。
** @return エラーコードを返す。
** - 異常終了時はエラーの種類を示す非ゼロ値を返す。
** - 正常終了の場合はゼロを返す。
**/
const ErrCode
readSourceFile(
const std::string &filename);
//----------------------------------------------------------------
/** 読み込んだソースコードからプログラムをビルドする。
**
** @param[out] os ログ出力用ストリーム。
** @return エラーコードを返す。
** - 異常終了時はエラーの種類を示す非ゼロ値を返す。
** - 正常終了の場合はゼロを返す。
**/
const ErrCode
buildPrograms(
std::ostream &os);
//----------------------------------------------------------------
/** ビルドしたプログラムからカーネルを作成する。
**
** @param [in] kname カーネル名。
** @return エラーコードを返す。
** - 異常終了時はエラーの種類を示す非ゼロ値を返す。
** - 正常終了の場合はゼロを返す。
**/
const ErrCode
createKernel(
const std::string &kname);
//========================================================================
//
// メモリ管理。
//
public:
//----------------------------------------------------------------
/** バッファを作成する。
**
**/
cl::Buffer
createBuffer(
cl_mem_flags flags,
::size_t size,
void * ptrHost = NULL,
cl_int * ptrErr = NULL)
{
return ( cl::Buffer(this->m_context, flags, size, ptrHost, ptrErr) );
}
//========================================================================
//
// カーネルの実行。
//
public:
//----------------------------------------------------------------
/** コマンドキューを作成する。
**
**/
cl::CommandQueue
createCommandQueue(
cl_command_queue_properties properties = 0,
cl_int * ptrErr = NULL)
{
return ( cl::CommandQueue(this->m_context, this->m_device, properties, ptrErr) );
}
//========================================================================
//
// Accessors.
//
public:
//----------------------------------------------------------------
/** コンテキストを取得する。
**
** @return コンテキストの参照を返す。
**/
const cl::Context &
getContext() const
{
return ( (this->m_context) );
}
const cl::Device &
getDevice() const
{
return ( this->m_device );
}
//----------------------------------------------------------------
/** ビルドしたプログラムを取得する。
**
** @return プログラムの参照を返す。
**/
const cl::Program &
getProgram() const
{
return ( this->m_program );
}
//========================================================================
//
// Member Variables.
//
private:
cl::Platform m_clPlatform;
cl::Context m_context;
std::vector<cl::Device> m_devices;
cl::Device m_device;
std::vector<std::string> m_srcFiles;
cl::Program m_program;
};
} // End of namespace CLWRAP
#endif
OclWrap.cpp
#include "OclWrap.h"
#pragma comment (lib, "OpenCL.lib")
#include <fstream>
#include <ostream>
namespace CLWRAP {
//========================================================================
//
// OclWrap class.
//
//========================================================================
//
// 初期化と終了。
//
//----------------------------------------------------------------
// インスタンスを初期化する。
//
const ErrCode
OclWrap::setupInstance(
std::ostream &os)
{
cl_int err = CL_SUCCESS;
// プラットフォーム取得。 //
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if ( (platforms.empty()) ) {
throw std::runtime_error("No Platforms!");
return ( ERR_FAILURE );
}
os << "# of Platforms = " << (platforms.size()) << std::endl;
this->m_clPlatform = platforms.at(0);
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM,
reinterpret_cast<cl_context_properties>(this->m_clPlatform()),
0
};
// コンテキスト作成。 //
this->m_context = cl::Context(
CL_DEVICE_TYPE_GPU, properties, NULL, NULL, &err);
if ( err != CL_SUCCESS ) {
throw std::runtime_error("Failed to Create Context");
return ( ERR_FAILURE );
}
cl::Context & context = (this->m_context);
// デバイス取得。 //
std::vector<cl::Device> & devices = (this->m_devices);
devices = context.getInfo<CL_CONTEXT_DEVICES>();
os << "# of Devices = " << (devices.size()) << std::endl;
if ( (devices.empty()) ) {
throw std::runtime_error("No Devices!");
return ( ERR_FAILURE );
}
this->m_device = devices.at(0);
os << "Device Name : " << this->m_device.getInfo<CL_DEVICE_NAME>() << std::endl
<< "Device Vendor : " << this->m_device.getInfo<CL_DEVICE_VENDOR>() << std::endl;
return ( ERR_SUCCESS );
}
//----------------------------------------------------------------
// インスタンスの後始末をする。
//
const ErrCode
OclWrap::clearInstance()
{
return ( ERR_SUCCESS );
}
//========================================================================
//
// プログラムの読み込みとカーネルの準備。
//
//----------------------------------------------------------------
// ソースファイルを指定する。
//
const ErrCode
OclWrap::readSourceFile(
const std::string &filename)
{
// この時点では未だ読み込まずに、ファイル名のリストだけ作成する。 //
this->m_srcFiles.push_back(filename);
return ( ERR_SUCCESS );
}
//----------------------------------------------------------------
// 読み込んだソースコードからプログラムをビルドする。
//
const ErrCode
OclWrap::buildPrograms(
std::ostream &os)
{
cl_int err = CL_SUCCESS;
typedef std::vector<std::string>::const_iterator NameItr;
std::vector<std::string> buffers;
cl::Program::Sources srcs;
ErrCode ret = ERR_SUCCESS;
srcs.clear();
srcs.reserve(this->m_srcFiles.size());
const NameItr itrEnd = this->m_srcFiles.end();
for ( NameItr itr = (this->m_srcFiles.begin()); itr != itrEnd; ++ itr ) {
// 存在しないファイルはまとめて通知した方が良いので、 //
// 途中でファイル読み込みエラーが発生しても、 //
// ファイルの存在チェックだけは最後まで継続して行う。 //
std::ifstream fsSource(itr->c_str());
if ( !fsSource ) {
os << "Source File [" << (*itr) << "] Not Found!" << std::endl;
ret = ERR_FAILURE;
}
if ( ret != ERR_SUCCESS ) {
// 途中でエラーを見つけている場合は、 //
// ファイルの存在チェックのみ行う。 //
continue;
}
// ファイルの内容を読み込む。 //
buffers.push_back( std::string(
std::istreambuf_iterator<char>(fsSource),
(std::istreambuf_iterator<char>()) ));
////os << strSrc << std::endl;
const std::string &strSrc = buffers.back();
srcs.push_back( std::make_pair(strSrc.c_str(), strSrc.length()) );
}
if ( ret != ERR_SUCCESS ) {
throw std::runtime_error("Source File(s) Not Found!");
return ( ret );
}
cl::Context & context = (this->m_context);
cl::Program program = cl::Program(context, srcs, &err);
if ( err != CL_SUCCESS ) {
throw std::runtime_error("Failed to Read Sources!");
return ( ERR_FAILURE );
}
err = program.build(this->m_devices);
std::string log = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(this->m_device);
if ( err != CL_SUCCESS ) {
os << "Build Error ... \n" << log << std::endl;
throw std::runtime_error("Build Error!");
return ( ERR_FAILURE );
}
// ソーステキストはもう要らない。 //
buffers.clear();
this->m_program = program;
return ( ERR_SUCCESS );
}
//----------------------------------------------------------------
// ビルドしたプログラムからカーネルを作成する。
//
const ErrCode
OclWrap::createKernel(
const std::string &kname)
{
return ( ERR_SUCCESS );
}
} // End of namespace CLWRAP
リンク
合計: -
今日: -
昨日: -
トップページの合計: -
最終更新:2014年02月20日 20:02