アットウィキロゴ

プログラミング > OpenCL > Wrapper

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