OpenCL 操作


CLHandleType

OpenCL ハンドルの型をENUM_OPENCL_HANDLE_TYPE 列挙の値として返します。

ENUM_OPENCL_HANDLE_TYPE  CLHandleType(
  int  handle     // OpenCL オブジェクトのハンドル
  );

パラメータ

handle

[in]  OpenCL オブジェクトのハンドル、すなわちコンテキスト、カーネルまたは OpenCL プログラム

戻り値

ENUM_OPENCL_HANDLE_TYPE 列挙での OpenCL ハンドル値

ENUM_OPENCL_HANDLE_TYPE

識別子

説明

OPENCL_INVALID

不正なハンドル。

OPENCL_CONTEXT

OpenCL コンテキストのハンドル

OPENCL_PROGRAM

OpenCL プログラムのハンドル

OPENCL_KERNEL

OpenCL カーネルのハンドル

OPENCL_BUFFER

OpenCL バッファのハンドル

CLGetInfoInteger

OpenCL オブジェクトまたはデバイスの整数プロパティ値を返します。

long  CLGetInfoInteger(
  int  handle,                           // OpenCL オブジェクトのハンドルまたはOpenCL デバイスの番号
  ENUM_OPENCL_PROPERTY_INTEGER  prop     // リクエストされたプロパティ
  );

パラメータ

handle

[in]  OpenCL オブジェクトのハンドルまたはOpenCL デバイスの番号。OpenCL デバイス番号はゼロで始まります。

prop

[in]  値の取得に使用されるENUM_OPENCL_PROPERTY_INTEGER 列挙からのリクエストされたプロパティの型

戻り値

成功の場合はプロパティ値、エラーの場合は -1。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

ENUM_OPENCL_PROPERTY_INTEGER

識別子

説明

Type

CL_DEVICE_COUNT

OpenCL をサポートするデバイスの数このプロパティは初めのパラメータの指定を必要としません。つまり handle パラメ—タにはゼロ値を渡すことが出来ます。

int

CL_DEVICE_TYPE

デバイスの種類

ENUM_CL_DEVICE_TYPE

CL_DEVICE_VENDOR_ID

一意のベンダー識別子

uint

CL_DEVICE_MAX_COMPUTE_UNITS

OpenCL のデバイスで並列計算されたタスクの数 1 つのワーキンググループは、1つの計算作業を解決します。最少値は 1 です。

uint

CL_DEVICE_MAX_CLOCK_FREQUENCY

MHz単位でデバイスの最高周波数設定

uint

CL_DEVICE_GLOBAL_MEM_SIZE

バイト単位でデバイスのグローバルメモリのサイズ

ulong

CL_DEVICE_LOCAL_MEM_SIZE

バイト単位での処理されたデータ(シーン)ローカルメモリのサイズ

uint

CL_BUFFER_SIZE

バイト単位での OpenCL バッファの実際のサイズ

ulong

CL_DEVICE_MAX_WORK_GROUP_SIZE

OpenCLデバイスで使用可能なローカルワーキンググループの総数

ulong

CL_KERNEL_WORK_GROUP_SIZE

OpenCLプログラムで使用可能なローカルワーキンググループの総数

ulong

CL_KERNEL_LOCAL_MEM_SIZE

グループ内のすべての並列タスクを解決するためにOpenCLプログラムが使用するローカルメモリのサイズ(バイト単位)。使用可能な最大値を受け取るにはCL_DEVICE_LOCAL_MEM_SIZEを使用します。

ulong

CL_KERNEL_PRIVATE_MEM_SIZE

OpenCLプログラムカーネルの各タスクで使用されるプライベートメモリの最小サイズ(バイト単位)

ulong

 

ENUM_CL_DEVICE_TYPE 列挙は OpenCL をサポートするデバイスの可能な種類を含みます。CLGetInfoInteger(handle_or_deviceN, CL_DEVICE_TYPE) を呼び出すことによって、デバイスの種類の番号や OpenCL オブジェクトのハンドルを受け取ることが出来ます。

ENUM_CL_DEVICE_TYPE

識別子

説明

CL_DEVICE_ACCELERATOR

OpenCL 専用のアクセラレータ(例えば、IBM CELL Blade)。これらのデバイスは PCIe のような周辺機器を使用してホストプロセッサと通信します。

CL_DEVICE_CPU

ホストプロセッサであるOpenCL デバイス。ホストプロセッサは、OpenCLの実装を実行する単一またはマルチコアCPUです。

CL_DEVICE_GPU

GPU であるOpenCL デバイス。

CL_DEVICE_DEFAULT

システムのデフォルト OpenCL デバイス。CL_DEVICE_TYPE_CUSTOM デバイスはデフォルトにはなりません。

CL_DEVICE_CUSTOM

OpenCLのCで書かれたプログラムをサポートしない専用アクセラレータ。

例:

void OnStart()
 {
  int cl_ctx;
//— OpenCL コンテキストを初期化する
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
    {
    Print("OpenCL not found");
    return;
    }
//— OpenCL デバイスの一般的な情報を表示する
  Print("OpenCL type: ",EnumToString((ENUM_CL_DEVICE_TYPE)CLGetInfoInteger(cl_ctx,CL_DEVICE_TYPE)));
  Print("OpenCL vendor ID: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_VENDOR_ID));
  Print("OpenCL units: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_MAX_COMPUTE_UNITS));
  Print("OpenCL freq: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_MAX_CLOCK_FREQUENCY)," MHz");
  Print("OpenCL global mem: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_GLOBAL_MEM_SIZE)," bytes");
  Print("OpenCL local mem: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_LOCAL_MEM_SIZE)," bytes");
//—
 }

CLGetInfoString

OpenCL オブジェクトまたはデバイスのプロパティの string 値を返します。

bool  CLGetInfoString(
  int  handle,                           // OpenCL オブジェクトハンドルまたはOpenCL デバイス番号
  ENUM_OPENCL_PROPERTY_STRING prop,     // リクエストされたプロパティ
  string&  value                         // 参照された文字列
  );

パラメータ

handle

[in]  OpenCL オブジェクトハンドルまたはOpenCL デバイス番号。OpenCL デバイス番号付けはゼロで始まります。

prop

[in]  値の取得に使用される ENUM_OPENCL_PROPERTY_STRING 列挙からのリクエストされたプロパティ

value

[out]  プロパティ値を受け取る文字列

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

ENUM_OPENCL_PROPERTY_STRING

識別子

説明

CL_PLATFORM_PROFILE

CL_PLATFORM_PROFILE – OpenCL プロファイル。プロファイル名は次のうちの 1 つです。

  • FULL_PROFILE – 実装は、OpenCLをサポートします。(機能は OpenCL のサポートのための追加の拡張機能を必要とせずに、カーネル仕様の一部として定義されています。)
  • EMBEDDED_PROFILE – 実装は、サプリメントとしてOpenCL をサポートします。改正されたプロファイルは、各OpenCL のバージョンのサブセットとして定義されています。

CL_PLATFORM_VERSION

OpenCL バージョン

CL_PLATFORM_VENDOR

プラットフォームベンダー名

CL_PLATFORM_EXTENSIONS

プラットフォームでサポートされている拡張機能のリスト。拡張名は、このプラットフォームに関連する全てのデバイスによってサポートされる必要があります。

CL_DEVICE_NAME

デバイス名

CL_DEVICE_VENDOR

ベンダー名

CL_DRIVER_VERSION

major_number.minor_number 形式での OpenCL ドライババージョン

CL_DEVICE_PROFILE

OpenCL デバイスプロファイル。プロファイル名は次のうちの 1 つです。

  • FULL_PROFILE – 実装は、OpenCLをサポートします。(機能は OpenCL のサポートのための追加の拡張機能を必要とせずに、カーネル仕様の一部として定義されています。)
  • EMBEDDED_PROFILE – 実装は、サプリメントとしてOpenCL をサポートします。改正されたプロファイルは、各OpenCL のバージョンのサブセットとして定義されています。

CL_DEVICE_VERSION

「OpenCL<space><major_version.minor_version><space><vendor-specific information>」 形式での OpenCL バージョン

CL_DEVICE_EXTENSIONS

デバイスがサポートしている拡張機能のリストリストは、ベンダーがサポートしている拡張機能ならびに1つ以上の承認された名称を含みます。

   cl_khr_int64_base_atomics

   cl_khr_int64_extended_atomics

   cl_khr_fp16

   cl_khr_gl_sharing

   cl_khr_gl_event

   cl_khr_d3d10_sharing

   cl_khr_dx9_media_sharing

   cl_khr_d3d11_sharing

CL_DEVICE_BUILT_IN_KERNELS

サポートされたカーネルは「;」で区切られます。

CL_DEVICE_OPENCL_C_VERSION

このデバイス用のコンパイラでサポートされている最大バージョン。バージョン形式:

「OpenCL<space>C<space><major_version.minor_version><space><vendor-specific information> 」

例:

void OnStart()
 {
  int cl_ctx;
  string str;
//— OpenCL コンテキストを初期化する
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
    {
    Print("OpenCL not found");
    return;
    }
//— プラットフォームの情報を表示する
  if(CLGetInfoString(cl_ctx,CL_PLATFORM_NAME,str))
    Print("OpenCL platform name: ",str);
  if(CLGetInfoString(cl_ctx,CL_PLATFORM_VENDOR,str))
    Print("OpenCL platform vendor: ",str);
  if(CLGetInfoString(cl_ctx,CL_PLATFORM_VERSION,str))
    Print("OpenCL platform ver: ",str);
  if(CLGetInfoString(cl_ctx,CL_PLATFORM_PROFILE,str))
    Print("OpenCL platform profile: ",str);
  if(CLGetInfoString(cl_ctx,CL_PLATFORM_EXTENSIONS,str))
    Print("OpenCL platform ext: ",str);
//— デバイスの情報を表示する
  if(CLGetInfoString(cl_ctx,CL_DEVICE_NAME,str))
    Print("OpenCL device name: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_PROFILE,str))
    Print("OpenCL device profile: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_BUILT_IN_KERNELS,str))
    Print("OpenCL device kernels: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_EXTENSIONS,str))
    Print("OpenCL device ext: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_VENDOR,str))
    Print("OpenCL device vendor: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_VERSION,str))
    Print("OpenCL device ver: ",str);
  if(CLGetInfoString(cl_ctx,CL_DEVICE_OPENCL_C_VERSION,str))
    Print("OpenCL open c ver: ",str);
//— OpenCL デバイスの一般的な情報を表示する
  Print("OpenCL type: ",EnumToString((ENUM_CL_DEVICE_TYPE)CLGetInfoInteger(cl_ctx,CL_DEVICE_TYPE)));
  Print("OpenCL vendor ID: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_VENDOR_ID));
  Print("OpenCL units: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_MAX_COMPUTE_UNITS));
  Print("OpenCL freq: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_MAX_CLOCK_FREQUENCY));
  Print("OpenCL global mem: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_GLOBAL_MEM_SIZE));
  Print("OpenCL local mem: ",CLGetInfoInteger(cl_ctx,CL_DEVICE_LOCAL_MEM_SIZE));
//—
 }

CLContextCreate

OpenCL コンテキストを作成してハンドルを返します。

int  CLContextCreate(
  int  device     // OpenCL デバイスのシリアル番号またはマクロ
  );

パラメータ

device

[in]  システム内の OpenCL デバイスの序数特定な数の代わりに、次のいずれかの値の指定が可能です。

  • CL_USE_ANY – OpenCL をサポートする使用可能なデバイス
  • CL_USE_CPU_ONLY – CPU での OpenCLのエミュレーションのみが許可されています
  • CL_USE_GPU_ONLY – OpenCL エミュレーションが禁止され、OpenCL をサポートする特定のデバイス(ビデオカード)のみが使用可能です

戻り値

成功の場合は OpenCL コンテキスト、その他の場合は -1。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLContextFree

OpenCL コンテキストを削除します。

void  CLContextFree(
  int  context    // OpenCL コンテンツのハンドル
  );

パラメータ

context

[in]  OpenCL コンテンツのハンドル

戻り値

なし。内部エラーの場合 _LastError の値が変更されます。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLGetDeviceInfo

この関数は、OpenCL ドライバからデバイスプロパティを受け取ります。

bool  CLGetDeviceInfo(
  int    handle,         // OpenCL デバイスハンドル
  int     property_id,     // リクエストされたプロパティ識別子
  uchar& data[],         // データを受け取る配列
  uint&   size             // 配列要素のシフト(デフォルトでは0
  );

パラメータ

handle

[in]  OpenCL デバイスインデックス、または CLContextCreate() 関数で作成されたOpenCL ハンドル。

property_id

[in]  受け取られる OpenCL デバイスプロパティ識別子。値は下記の表に記載されている所定のもの 1 つであることが出来ます。

data[]

[out]  リクエストされたプロパティのデータを受け取る配列

size

[out] data[] 配列での受け取ったデータのサイズ

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

OpenCL バッファへの読み込みのための始まる要素の番号は AS_SERIESフラグを考慮して計算されます。

OpenCL デバイスプロパティに使用可能な識別子のリスト

プロパティの繊細は OpenCL の公式ウェブサイトにて。

識別子

CL_DEVICE_TYPE

0x1000

CL_DEVICE_VENDOR_ID

0x1001

CL_DEVICE_MAX_COMPUTE_UNITS

0x1002

CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS

0x1003

CL_DEVICE_MAX_WORK_GROUP_SIZE

0x1004

CL_DEVICE_MAX_WORK_ITEM_SIZES

0x1005

CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR

0x1006

CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT

0x1007

CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT

0x1008

CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG

0x1009

CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT

0x100A

CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE

0x100B

CL_DEVICE_MAX_CLOCK_FREQUENCY

0x100C

CL_DEVICE_ADDRESS_BITS

0x100D

CL_DEVICE_MAX_READ_IMAGE_ARGS

0x100E

CL_DEVICE_MAX_WRITE_IMAGE_ARGS

0x100F

CL_DEVICE_MAX_MEM_ALLOC_SIZE

0x1010

CL_DEVICE_IMAGE2D_MAX_WIDTH

0x1011

CL_DEVICE_IMAGE2D_MAX_HEIGHT

0x1012

CL_DEVICE_IMAGE3D_MAX_WIDTH

0x1013

CL_DEVICE_IMAGE3D_MAX_HEIGHT

0x1014

CL_DEVICE_IMAGE3D_MAX_DEPTH

0x1015

CL_DEVICE_IMAGE_SUPPORT

0x1016

CL_DEVICE_MAX_PARAMETER_SIZE

0x1017

CL_DEVICE_MAX_SAMPLERS

0x1018

CL_DEVICE_MEM_BASE_ADDR_ALIGN

0x1019

CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE

0x101A

CL_DEVICE_SINGLE_FP_CONFIG

0x101B

CL_DEVICE_GLOBAL_MEM_CACHE_TYPE

0x101C

CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE

0x101D

CL_DEVICE_GLOBAL_MEM_CACHE_SIZE

0x101E

CL_DEVICE_GLOBAL_MEM_SIZE

0x101F

CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE

0x1020

CL_DEVICE_MAX_CONSTANT_ARGS

0x1021

CL_DEVICE_LOCAL_MEM_TYPE

0x1022

CL_DEVICE_LOCAL_MEM_SIZE

0x1023

CL_DEVICE_ERROR_CORRECTION_SUPPORT

0x1024

CL_DEVICE_PROFILING_TIMER_RESOLUTION

0x1025

CL_DEVICE_ENDIAN_LITTLE

0x1026

CL_DEVICE_AVAILABLE

0x1027

CL_DEVICE_COMPILER_AVAILABLE

0x1028

CL_DEVICE_EXECUTION_CAPABILITIES

0x1029

CL_DEVICE_QUEUE_PROPERTIES

0x102A

CL_DEVICE_NAME

0x102B

CL_DEVICE_VENDOR

0x102C

CL_DRIVER_VERSION

0x102D

CL_DEVICE_PROFILE

0x102E

CL_DEVICE_VERSION

0x102F

CL_DEVICE_EXTENSIONS

0x1030

CL_DEVICE_PLATFORM

0x1031

CL_DEVICE_DOUBLE_FP_CONFIG

0x1032

CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF

0x1034

CL_DEVICE_HOST_UNIFIED_MEMORY

0x1035

CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR

0x1036

CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT

0x1037

CL_DEVICE_NATIVE_VECTOR_WIDTH_INT

0x1038

CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG

0x1039

CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT

0x103A

CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE

0x103B

CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF

0x103C

CL_DEVICE_OPENCL_C_VERSION

0x103D

CL_DEVICE_LINKER_AVAILABLE

0x103E

CL_DEVICE_BUILT_IN_KERNELS

0x103F

CL_DEVICE_IMAGE_MAX_BUFFER_SIZE

0x1040

CL_DEVICE_IMAGE_MAX_ARRAY_SIZE

0x1041

CL_DEVICE_PARENT_DEVICE

0x1042

CL_DEVICE_PARTITION_MAX_SUB_DEVICES

0x1043

CL_DEVICE_PARTITION_PROPERTIES

0x1044

CL_DEVICE_PARTITION_AFFINITY_DOMAIN

0x1045

CL_DEVICE_PARTITION_TYPE

0x1046

CL_DEVICE_REFERENCE_COUNT

0x1047

CL_DEVICE_PREFERRED_INTEROP_USER_SYNC

0x1048

CL_DEVICE_PRINTF_BUFFER_SIZE

0x1049

CL_DEVICE_IMAGE_PITCH_ALIGNMENT

0x104A

CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT

0x104B

例:

void OnStart()
 {
//—
  int dCount= CLGetInfoInteger(0,CL_DEVICE_COUNT);
  for(int i = 0; i<dCount; i++)
    {
    int clCtx=CLContextCreate(i);
    if(clCtx == -1)
        Print("ERROR in CLContextCreate");
    string device;
     CLGetInfoString(clCtx,CL_DEVICE_NAME,device);
    Print(i,": ",device);
    uchar data[1024];
    uint size;
    CLGetDeviceInfo(clCtx,CL_DEVICE_VENDOR,data,size);
    Print("size = ",size);
    string str=CharArrayToString(data);
    Print(str);
    }
 }
//— エキスパート操作ログエントリーの例
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      2: Advanced Micro Devices, Inc.
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      size = 32
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      Tahiti
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      Intel(R) Corporation
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      size = 21
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      1:        Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      NVIDIA Corporation
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      size = 19
//  2013.07.24 10:50:48     opencl (EURUSD,H1)      0: GeForce GTX 580

CLProgramCreate

OpenCL プログラムをソースコードから作成します。

int  CLProgramCreate(
  int          context,    // OpenCL コンテキストのハンドル
  const string  source      // ソースコード
  );

オーバーロード関数は OpenCL プログラムを作成し、渡された文字列にコンパイラメッセージを書き込みます。

int  CLProgramCreate(
  int          context,    // OpenCL コンテキストのハンドル
  const string  source,      // ソースコード
  string      &build_log    // コンパイルログを受け取る文字列
  );

パラメータ

context

[in]  OpenCL コンテンツのハンドル

source

[in]  OpenCL プログラムのソースコードを含む文字列

&build_log

[in]  OpenCL コンパイラメッセージを受け取る文字列

戻り値

成功の場合 OpenCL オブジェクトハンドル。エラーの場合は -1。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

現時点では、次のエラーコードが使用されます。

  • ERR_OPENCL_INVALID_HANDLE – 不正な OpenCL コンテキストハンドル
  • ERR_INVALID_PARAMETER – 不正な文字列パラメータ
  • ERR_NOT_ENOUGH_MEMORY – 操作完了に不充分なメモリ
  • ERR_OPENCL_PROGRAM_CREATE – OpenCL 内部エラーまたはコンパイルエラー

グラフィックカードによっては double 型の数の操作はデフォルトでは無効にされています。これはコンパイルエラー5105 につながります。double 型数値のサポートを有効にするには #pragma OPENCL EXTENSION cl_khr_fp64 : enable ディレクティブをお使いのプログラムに追加してください。 グラフィックカードが double をサポートしない場合は、ディレクティブの使用はサポートを有効にしません。

例:

//+——————————————————————+
//| OpenCL カーネル                                                     |
//+——————————————————————+
const string
cl_src=
      //— デフォルトでは double をサポートしない GPU がある
      //— cl_khr_fp64 directive が double の操作を有効にするために使用される
      "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n"
      //— OpenCL カーネル関数
      "__kernel void Test_GPU(__global double *data,      \r\n"
      "                       const    int N,             \r\n"
      "                       const    int total_arrays)  \r\n"
      "  {                                                \r\n"
      "   uint kernel_index=get_global_id(0);             \r\n"
      "   if (kernel_index>total_arrays) return;          \r\n"
      "   uint local_start_offset=kernel_index*N;         \r\n"
      "   for(int i=0; i<N; i++)                          \r\n"
      "     {                                             \r\n"
      "       data[i+local_start_offset] *= 2.0;          \r\n"
      "     }                                             \r\n"
      "  }                                                \r\n";
//+——————————————————————+
//| Test_CPU                                                         |
//+——————————————————————+
bool Test_CPU(double &data[],const int N,const int id,const int total_arrays)
 {
//— 配列サイズをチェックする
  if(ArraySize(data)==0) return(false);
//— 配列インデックスをチェックする
  if(id>total_arrays) return(false);
//— インデックス id の配列のローカルオフセットを計算する
  int local_start_offset=id*N;
//— 要素を二倍にする
  for(int i=0; i<N; i++)
    {
     data[i+local_start_offset]*=2.0;
    }
  return true;
 }
//—
#define ARRAY_SIZE   100 // 配列サイズ
#define TOTAL_ARRAYS 5   // 全ての配列
//— OpenCL ハンドル
int cl_ctx; // OpenCL コンテキストハンドル
int cl_prg; // OpenCL プログラムハンドル
int cl_krn; // OpenCL カーネルハンドル
int cl_mem; // OpenCL バッファハンドル
//—
double DataArray1[]; // CPU 計算のためのデータ配列
double DataArray2[]; // GPU 計算のためのデータ配列
//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
int OnStart()
 {
//— OpenCL オブジェクトを初期化する
//— OpenCL コンテキストを作成する
  if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
    {
    Print("OpenCL not found. Error=",GetLastError());
    return(1);
    }
//— OpenCL プログラムを作成する
  if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)
    {
    CLContextFree(cl_ctx);
    Print("OpenCL program create failed. Error=",GetLastError());
    return(1);
    }
//— OpenCL カーネルを作成する
  if((cl_krn=CLKernelCreate(cl_prg,"Test_GPU"))==INVALID_HANDLE)
    {
    CLProgramFree(cl_prg);
    CLContextFree(cl_ctx);
    Print("OpenCL kernel create failed. Error=",GetLastError());
    return(1);
    }
//— OpenCL バッファを作成する
  if((cl_mem=CLBufferCreate(cl_ctx,ARRAY_SIZE*TOTAL_ARRAYS*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
    {
    CLKernelFree(cl_krn);
    CLProgramFree(cl_prg);
    CLContextFree(cl_ctx);
    Print("OpenCL buffer create failed. Error=",GetLastError());
    return(1);
    }
//— OpenCL カーネルの定数パラメータを設定する
  CLSetKernelArgMem(cl_krn,0,cl_mem);
  CLSetKernelArg(cl_krn,1,ARRAY_SIZE);
  CLSetKernelArg(cl_krn,2,TOTAL_ARRAYS);
//— データ配列を準備する
  ArrayResize(DataArray1,ARRAY_SIZE*TOTAL_ARRAYS);
  ArrayResize(DataArray2,ARRAY_SIZE*TOTAL_ARRAYS);
//— データに配列を書き込む
  for(int j=0; j<TOTAL_ARRAYS; j++)
    {
    //— j 番目の配列のローカル開始オフセットを計算する
    uint local_offset=j*ARRAY_SIZE;
    //— インデックス j の配列を準備する
    for(int i=0; i<ARRAY_SIZE; i++)
       {
        //— MathCos(i+j) の結果を配列に書き込む
        DataArray1[i+local_offset]=MathCos(i+j);
        DataArray2[i+local_offset]=MathCos(i+j);
       }
    };
//— CPU 計算をテストする
  for(int j=0; j<TOTAL_ARRAYS; j++)
    {
    //— インデックス j の配列の計算
     Test_CPU(DataArray1,ARRAY_SIZE,j,TOTAL_ARRAYS);
    }
//— CLExecute パラメータを準備する
  uint  offset[]={0};
//— グローバルワークサイズ
  uint  work[]={TOTAL_ARRAYS};
//— OpenCL バッファにデータを書く
  CLBufferWrite(cl_mem,DataArray2);
//— OpenCL カーネルを実行する
  CLExecute(cl_krn,1,offset,work);
//— OpenCL バッファからデータを読む
  CLBufferRead(cl_mem,DataArray2);
//— エラーの合計
  double total_error=0;
//— 結果を比較してエラーを計算する
  for(int j=0; j<TOTAL_ARRAYS; j++)
    {
    //— j 番目の配列のローカルオフセットを計算する
    uint local_offset=j*ARRAY_SIZE;
    //— 結果を比較する
    for(int i=0; i<ARRAY_SIZE; i++)
       {
        double v1=DataArray1[i+local_offset];
        double v2=DataArray2[i+local_offset];
        double delta=MathAbs(v2-v1);
        total_error+=delta;
        //— 最初と最後の配列を表示する
        if((j==0) || (j==TOTAL_ARRAYS-1))
          PrintFormat("array %d of %d, element [%d]:  %f, %f, [error]=%f",j+1,TOTAL_ARRAYS,i,v1,v2,delta);
       }
    }
  PrintFormat("Total error: %f",total_error);
//— OpenCL オブジェクトを削除する
//— OpenCL バッファを解放する
  CLBufferFree(cl_mem);
//— OpenCL カーネルを解放する
  CLKernelFree(cl_krn);
//— OpenCL プログラムを解放する
  CLProgramFree(cl_prg);
//— OpenCL コンテキストを解放する
  CLContextFree(cl_ctx);
//—
  return(0);
 }

。CLProgramFree

OpenCL プログラムを削除します。

void  CLProgramFree(
  int  program    // OpenCL オブジェクトのハンドル
  );

パラメータ

program

[in]  OpenCL オブジェクトのハンドル

戻り値

なし。内部エラーの場合 _LastError の値が変更されます。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLKernelCreate

OpenCL プログラムカーネルを作成してハンドルを返します。

int  CLKernelCreate(
  int          program,        // OpenCL オブジェクトのハンドル
  const string  kernel_name     // カーネル名
  );

パラメータ

program

[in]  OpenCL プログラムオブジェクトのハンドル

kernel_name

[in]  実行が開始される OpenCL プログラムのカーネル関数の名称

戻り値

成功の場合 OpenCL オブジェクトハンドル。エラーの場合は -1。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

現時点では、次のエラーコードが使用されます。

  • ERR_OPENCL_INVALID_HANDLE – invalid handle to OpenCL program.
  • ERR_INVALID_PARAMETER – 不正な文字列パラメータ
  • ERR_OPENCL_TOO_LONG_KERNEL_NAME – カーネル名が 127 文字を超えます。
  • ERR_OPENCL_KERNEL_CREATE – OpenCL オブジェクト作成時に内部エラーが発生しました。

CLKernelFree

OpenCL start 関数を削除します。

void  CLKernelFree(
  int  kernel    // OpenCL プログラムカーネルのハンドル
  );

パラメータ

kernel_name

[in]  カーネルオブジェクトのハンドル

戻り値

なし。内部エラーの場合 _LastError の値が変更されます。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLSetKernelArg

OpenCL 関数のパラメータを設定します。

bool  CLSetKernelArg(
  int  kernel,        // OpenCL プログラムカーネルのハンドル
  uint arg_index,     // OpenCL 関数の引数の番号
  void  arg_value     // ソースコード
  );

パラメータ

kernel

[in]  OpenCL プログラムカーネルのハンドル

arg_index

[in]  OpenCL 関数の引数の番号(番号付けはゼロから)

arg_value

[in]  関数の引数の値

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

現時点では、次のエラーコードが使用されます。

  • ERR_INVALID_PARAMETER,
  • ERR_OPENCL_INVALID_HANDLE – invalid handle to the OpenCL kernel.
  • ERR_OPENCL_SET_KERNEL_PARAMETER – internal error of OpenCL.

CLSetKernelArgMem

OpenCL バッファを OpenCL 関数のパラメータとして設定します。

bool  CLSetKernelArgMem(
  int  kernel,          // OpenCL プログラムカーネルのハンドル
  uint arg_index,        // OpenCL 関数の引数の番号
  int  cl_mem_handle     // OpenCL バッファハンドル
  );

パラメータ

kernel

[in]  OpenCL プログラムカーネルのハンドル

arg_index

[in]  OpenCL 関数の引数の番号(番号付けはゼロから)

cl_mem_handle

[in]  OpenCL バッファハンドル

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLSetKernelArgMemLocal

ローカルバッファをカーネル関数の引数として設定します。

bool  CLSetKernelArgMemLocal(
  int    kernel,          // OpenCLプログラムのカーネルへのハンドル
  uint   arg_index,        // OpenCL関数の引数の数
  ulong  local_mem_size   // バッファサイズ
  );

パラメータ

kernel

[in]  OpenCL プログラムカーネルのハンドル

arg_index

[in]  OpenCL 関数の引数の番号(番号付けはゼロから)

local_mem_size

[in]  バイト単位でのバッファサイズ

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLBufferCreate

OpenCL バッファを作成してハンドルを返します。

int  CLBufferCreate(
  int  context,    // OpenCL コンテンツのハンドル
  uint size,        // バッファサイズ
  uint  flags       // OpenCL バッファのプロパティを指定するフラグの組み合わせ
  );

パラメータ

context

[in]  OpenCL コンテンツのハンドル

size

[in]  バイト単位でのバッファサイズ

flags

[in]  フラグの組み合わせで指定されるバッファプロパティは CL_MEM_READ_WRITE、CL_MEM_WRITE_ONLY、CL_MEM_READ_ONLY 及び CL_MEM_ALLOC_HOST_PTR です。

戻り値

成功の場合 OpenCL バッファハンドル。エラーの場合は -1。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

現時点では、次のエラーコードが使用されます。

  • ERR_OPENCL_INVALID_HANDLE  – 不正な OpenCL コンテキストハンドル
  • ERR_NOT_ENOUGH_MEMORY – 不充分なメモリ
  • ERR_OPENCL_BUFFER_CREATE – バッファ作成時の内部エラー

 

CLBufferFree

OpenCL バッファを削除します。

void  CLBufferFree(
  int  buffer    // OpenCL バッファハンドル
  );

パラメータ

buffer

[in]  OpenCL バッファハンドル

戻り値

なし。内部エラーの場合 _LastError の値が変更されます。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

CLBufferWrite

OpenCL バッファに書き込み、書かれた要素の数を返します。

uint  CLBufferWrite(
  int          buffer,                   // OpenCL バッファハンドル
  const void&  data[],                   // 値の配列
  uint         buffer_offset=0,           // OpenCL バッファ内のバイト単位のオフセット(デフォルトで 0)
  uint         data_offset=0,             // OpenCL バッファ内の要素数でのオフセット(デフォルトで 0)
  uint        data_count=WHOLE_ARRAY     // 書かれる配列の値の数(デフォルトでは配列全体)
  );

パラメータ

buffer

[in]  OpenCL バッファハンドル

data[]

[in]  OpenCL バッファに書かれる値の配列。参照で引き渡されます。

buffer_offset

[in]  OpenCL バッファ内のバイト単位での読み込みが始まるオフセット。デフォルトでは書き込みはバッファの一番初めから始まります。

data_offset

[in]  OpenCLのバッファに値を書き込むための最初の配列要素のインデックス。デフォルトでは配列の一番初めの値が使用されます。

data_count

[in]  書き込まれる値の数。デフォルトでは配列の値全部。

戻り値

書かれた要素の数。エラーの場合 0 。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

1 次元配列では OpenCL バッファへの書き入れのための読み込みが始まる要素の番号は AS_SERIESフラグを考慮して計算されます。

2 次元以上の配列は1 次元として提示されます。この場合 data_offset は、1 次元目の要素の数ではなく、抜かされるべき要素の数です。

CLBufferRead

OpenCL バッファを配列に読み込んで読まれた要素の数を返します。

uint  CLBufferRead(
  int          buffer,                   // OpenCL バッファハンドル
  const void&  data[],                   // 値の配列
  uint         buffer_offset=0,           // OpenCL バッファ内のバイト単位のオフセット(デフォルトで 0)
  uint         data_offset=0,             // OpenCL バッファ内の要素数でのオフセット(デフォルトで 0)
  uint        data_count=WHOLE_ARRAY     // バッファから読まれる値の数(デフォルトではバッファ全体)
  );

パラメータ

buffer

[in]  OpenCL バッファハンドル

data[]

[in]  OpenCL バッファから値を受け取る配列。参照で引き渡されます。

buffer_offset

[in]  OpenCL バッファ内のバイト単位での読み込みが始まるオフセット。デフォルトでは読み込みはバッファの一番初めから始まります。

data_offset

[in]  OpenCLのバッファの値を書き込むための最初の配列要素のインデックス。デフォルトでは、配列への読み込み値の書き込みはゼロインデックスから始まります。

data_count

[in]  読まれる値の数。デフォルトでは OpenCL バファ全体が読まれます。

戻り値

読まれた要素の数。エラーの場合 0 。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

1 次元配列では OpenCL バッファへの書き入れが始まる要素の番号はAS_SERIES フラグを考慮して計算されます。

2 次元以上の配列は1 次元として提示されます。この場合 data_offset は、1 次元目の要素の数ではなく、抜かされるべき要素の数です。

CLExecute

この関数は OpenCL プログラムを実行します。この関数には 3 つのバージョンがあります。

1. 単数のカーネルを使用してのカーネル関数起動

bool  CLExecute(
  int          kernel                   // OpenCL プログラムカーネルのハンドル
  );

2. 作業空間の記述を使用した複数のカーネル(OpenCL 関数)の起動

bool  CLExecute(
  int          kernel,                  // OpenCL プログラムカーネルのハンドル
  uint        work_dim,                // 作業空間の寸法
  const uint&  global_work_offset[],    // 作業空間の初期オフセット
  const uint&  global_work_size[]        // 作業の数
  );

3. 作業空間の記述とグループのローカル作業サブセットのサイズの指定とともの複数のカーネル(OpenCL関数)の起動

bool  CLExecute(
  int          kernel,                  // OpenCL プログラムカーネルのハンドル
  uint        work_dim,                // 作業空間の寸法
  const uint&  global_work_offset[],    // 作業空間の初期オフセット
  const uint&  global_work_size[],      // 作業の数
  const uint&  local_work_size[]        // ローカルグループの作業数
  );

パラメータ

kernel

[in]  OpenCL カーネルのハンドル

work_dim

[in]  作業空間の寸法

global_work_offset[]

[in]  作業空間の初期オフセット

global_work_size[]

[in]  作業サブセットのサイズ

local_work_size[]

[in]  グループのローカル作業サブセットのサイズ

戻り値

成功の場合は true、それ以外の場合は false。エラー情報を取得するには、GetLastError() 関数が呼ばれます。

注意事項

下記の例でのパラメータの使用の仕方を見てみましょう。

  • work_dim は作業を記述する work_items[] 配列の次元を指定します。work_dim=3 の場合、三次元の配列 work_items[N1, N2, N3] が使用されます。
  • global_work_size[]work_items[] 配列のサイズを設定する値を含みます。work_dim=3 の場合、global_work_size[3] 配列は例えば {40, 100, 320} です。その場合 work_items[40, 100, 320] です。従って、作業数の合計は 40 x 100 x 320 = 1 280 000 です。
  • local_work_size[] は指定された OpenCL プログラムのカーネルで実行される作業のサブセットを設定します。そのサイズは work_items[] のサイズと等しく、除算での残りの部分を失うことなく、一般的なタスクの一部をより小さなサブセットに分割することが出来ます。実際には local_work_size[] 配列のサイズはwork_items[] グローバル作業セットがより小さいサブセットに分けられるように選択されるべきです。この例では work_items[40, 100, 320] は除算のあまりなしで local_items[10, 10, 10] から得られるため local_work_size[3]={10, 10, 10} が可能です。

CLExecutionStatus

OpenCLプログラム実行ステータスを返します。

int  CLExecutionStatus(
  int  kernel           // OpenCLプログラムのカーネルへのハンドル
  );

パラメータ

kernel

[in]  OpenCL プログラムカーネルのハンドル

戻り値

OpenCLプログラム実行ステータスを返します。 可能な値は下記の通りです。

  • CL_COMPLETE=0 – プログラム完了
  • CL_RUNNING=1 – 実行中
  • CL_SUBMITTED=2 – 実行のために提出された
  • CL_QUEUED=3 – キューに入れられた
  • -1 (マイナス1) – CLExecutionStatus()の実行中にエラーが発生した

Originally posted 2019-07-30 09:46:42.

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">