忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

C#でOpenCL入門 チュートリアルその3 コンテキスト


 前回はGPUを司るデバイスを扱いました。
しかし実はOpenCLはデバイスではたいしたことはしません。

GPUで計算をするためにはGPU内に計算に使うデータを格納したバッファを用意しなければならないのですが、デバイスオブジェクトではそれは行わないのです。
その作業はコンテキストを通じて行います。

今回はコンテキストの生成と破棄をメモします。


コンテキストの生成

コンテキストは1つ以上のデバイスをまとめるオブジェクトです。
コマンドキューやメモリ、プログラムなどは全てこれを通して作ります。
(コマンドキュー?メモリって?プログラム?これらは後述します。)

コンテキストの生成にはclCreateContext関数を使います。
参考

cl_context clCreateContext(
    const cl_context_properties *properties,
    cl_uint num_devices,
    const cl_device_id *devices,
    (void CL_CALLBACK *pfn_notify)(
        const char *errinfo,
        const void *private_info,
        size_t cb,
        void *user_data
    ),
    void *user_data,
    cl_int *errcode_ret
)

propertiesはコンテキストを生成するときの情報です。プロパティ名と値のリストからなり、0で終了します。この値はNULLでもよく、その場合の振る舞いは実装が定義します。この引数の中には次のような値が入ります。

cl_context_properties プロパティ値 解説
 CL_CONTEXT_PLATFORM  0x1084 cl_platform_id  使うプラットフォームです。
 CL_CONTEXT_D3D10_DEVICE_KHR  0x4014 ID3D10Device*  cl_khr_d3d10_sharing拡張が有効なときに使えます。Direct3D10との相互運用が可能です。デフォルトではNULLです。
CL_GL_CONTEXT_KHR  0x2008    cl_khr_gl_sharing拡張が有効なときに使えます。
 
 
 
 
CL_EGL_DISPLAY_KHR  0x2009  
CL_GLX_DISPLAY_KHR  0x200A  
CL_WGL_HDC_KHR  0x200B  
CL_CGL_SHAREGROUP_KHR  0x200C  

num_devicesはdevices引数の中に入っているデバイスの個数です。
devicesはこのコンテキストを生成するのに使うデバイスです。コンテキストはこの中に入っているデバイスを使うことになります。重複して同じデバイスが入っている場合は、片方が無視されます。
pfn_notifyはエラー情報を受け取るコールバック関数です。この関数は非同期に呼び出されます。もしこの引数がNULLなら、コールバック関数は登録されません。

このコールバック関数には4つの引数があります。

errinfoはエラー文字列へのポインタです。
private_infocbはデバッグ時に役に立つ情報です。OpenCLの実装がこの値をセットします。
user_dataはユーザー定義の情報です。clCreateContext()のuser_data引数の中身と同じです。

user_dataは、コールバック関数pfn_notifyの引数として渡されるデータです。NULLでも構いません。
errcode_retはエラーコードです。NULLでも構いません。


コンテキストの破棄

生成したコンテキストは使い終わったら破棄しなくてはいけません。
破棄にはclReleaseContext()関数を使います。

正確に言えばこれは破棄のための関数ではなく、参照カウントを減らす関数です。
参照カウントが0になった時そのオブジェクトは破棄されるのです。
が、C#から使うのだったら破棄のための関数も同然ですね。

cl_int clReleaseContext(cl_context context);

contextは破棄するコンテキストです。

戻り値
名前 解説
CL_SUCCESS 0 関数は成功しました。
CL_INVALID_CONTEXT -34 contextが無効な値です。
CL_OUT_OF_RESOURCES -5 デバイスがリソースを作れませんでした。
CL_OUT_OF_HOST_MEMORY -6 メモリが足りません。



コンテキストオブジェクトの生成と破棄

ではコンテキストを作るプログラムを書いてみましょう。
今回はコンテキスト作るだけで何もしません。
真っ暗な画面が一瞬でてそのまま終了するプログラムです。

そういう意味ではサンプルプログラムの意味が無いのですが、ご容赦ください…

Program.cs
using System;

class Program
{
    static void Main()
    {
        Context context = new Context(getDevices(getPlatforms()[0], DeviceType.Default));
        
    }

    private static IntPtr[] getDevices(IntPtr platform, DeviceType deviceType)
    {
        int deviceCount;
        OpenCLFunctions.clGetDeviceIDs(platform, deviceType, 0, null, out deviceCount);
       
        IntPtr[] result = new IntPtr[deviceCount];
        OpenCLFunctions.clGetDeviceIDs(platform, deviceType, deviceCount, result, out deviceCount);
        return result;
    }


    private static IntPtr[] getPlatforms()
    {
        int platformCount;
        OpenCLFunctions.clGetPlatformIDs(0, null, out platformCount);

        IntPtr[] result = new IntPtr[platformCount];
        OpenCLFunctions.clGetPlatformIDs(platformCount, result, out platformCount);
        return result;
    }
}
 

OpenCLWrappers.cs
using System;
 
class Context
{
    public IntPtr InternalPointer { get; private set; }
 
    public Context(IntPtr[] devices)
    {
        int error;
        InternalPointer = OpenCLFunctions.clCreateContext(
            null,
            devices.Length,
            devices,
            null,
            IntPtr.Zero,
            out error
            );
    }
 
    ~Context()
    {
        OpenCLFunctions.clReleaseContext(InternalPointer);
    }
}

OpenCLFunctions.cs
using System;
using System.Runtime.InteropServices;

static class OpenCLFunctions
{
    [DllImport("OpenCL.dll")]
    public static extern int clGetPlatformIDs(int entryCount, IntPtr[] platforms, out int platformCount);

    [DllImport("OpenCL.dll")]
    public static extern int clGetDeviceIDs(
        IntPtr platform,
        DeviceType deviceType,
        int entryCount,
        IntPtr[] devices,
        out int deviceCount
        );

    [DllImport("OpenCL.dll")]
    public static extern IntPtr clCreateContext(
        IntPtr[] properties, 
        int deviceCount,
        IntPtr[] devices,
        NotifyCallback pfnNotify,
        IntPtr userData,
        out int errorCode
        );

    [DllImport("OpenCL.dll")]
    public static extern int clReleaseContext(IntPtr context);
}

delegate void NotifyCallback(string errorInfo, IntPtr privateInfoSize, int cb, IntPtr userData);

enum DeviceType:long
{
    Default = (1 << 0),
    Cpu = (1 << 1),
    Gpu = (1 << 2),
    Accelerator = (1 << 3),
    All = 0xFFFFFFFF
}


このプログラムはデバイスからコンテキストを作り、そのまま破棄します。
画面には何も出力しません。

















拍手[1回]

PR