忍者ブログ

Memeplexes

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

C#でOpenCL入門 (OpenCLNet版) カーネル

カーネル

こちらも合わせてお読みください。

今回は「カーネル」について解説します。
カーネルというとよく意味が取れない方もいらっしゃるかも知れません。
OpenCLでカーネルというと、GPUで動かす関数のことです。

前回登場した「プログラム」との違いを言うと、カーネルは関数であるのに対し、プログラムはカーネルの塊である、といったところでしょうか。

今回することを3つにまとめるとこうなります:

  1. プログラムからカーネル生成
  2. カーネルに引数のセット
  3. カーネルの実行


使うメソッド

今回はすることは3つあります。
それらを行うメソッドを一つ一つ紹介します。

カーネルの生成

まずはカーネルの生成を行うメソッドから。
Program.CreateKenerlメソッドです。

public Kernel CreateKernel(string kernelName);

kernelNameは関数名です。

カーネルに引数をセット

次はカーネルに引数をセットするメソッドです。
Kernel.SetArgメソッドです。

        public void SetArg(int argIndex, byte c);
        public void SetArg(int argIndex, Char16 c);
        public void SetArg(int argIndex, Char2 c);
        public void SetArg(int argIndex, Char3 c);
        public void SetArg(int argIndex, Char4 c);
        public void SetArg(int argIndex, Char8 c);
        public void SetArg(int argIndex, double c);
        public void SetArg(int argIndex, Double16 c);
        public void SetArg(int argIndex, Double2 c);
        public void SetArg(int argIndex, Double3 c);
        public void SetArg(int argIndex, Double4 c);
        public void SetArg(int argIndex, Double8 c);
        public void SetArg(int argIndex, float c);
        public void SetArg(int argIndex, Float16 c);
        public void SetArg(int argIndex, Float2 c);
        public void SetArg(int argIndex, Float3 c);
        public void SetArg(int argIndex, Float4 c);
        public void SetArg(int argIndex, Float8 c);
        public void SetArg(int argIndex, int c);
        public void SetArg(int argIndex, Int16 c);
        public void SetArg(int argIndex, Int2 c);
        public void SetArg(int argIndex, Int3 c);
        public void SetArg(int argIndex, Int4 c);
        public void SetArg(int argIndex, Int8 c);
        public void SetArg(int argIndex, IntPtr c);
        public void SetArg(int argIndex, long c);
        public void SetArg(int argIndex, Long16 c);
        public void SetArg(int argIndex, Long2 c);
        public void SetArg(int argIndex, Long3 c);
        public void SetArg(int argIndex, Long4 c);
        public void SetArg(int argIndex, Long8 c);
        public void SetArg(int argIndex, Mem mem);
        public void SetArg(int argIndex, Sampler sampler);
        public void SetArg(int argIndex, sbyte c);
        public void SetArg(int argIndex, short c);
        public void SetArg(int argIndex, Short16 c);
        public void SetArg(int argIndex, Short2 c);
        public void SetArg(int argIndex, Short3 c);
        public void SetArg(int argIndex, Short4 c);
        public void SetArg(int argIndex, Short8 c);
        public void SetArg(int argIndex, UChar16 c);
        public void SetArg(int argIndex, UChar2 c);
        public void SetArg(int argIndex, UChar3 c);
        public void SetArg(int argIndex, UChar4 c);
        public void SetArg(int argIndex, UChar8 c);
        public void SetArg(int argIndex, uint c);
        public void SetArg(int argIndex, UInt16 c);
        public void SetArg(int argIndex, UInt2 c);
        public void SetArg(int argIndex, UInt3 c);
        public void SetArg(int argIndex, UInt4 c);
        public void SetArg(int argIndex, UInt8 c);
        public void SetArg(int argIndex, ulong c);
        public void SetArg(int argIndex, ULong16 c);
        public void SetArg(int argIndex, ULong2 c);
        public void SetArg(int argIndex, ULong3 c);
        public void SetArg(int argIndex, ULong4 c);
        public void SetArg(int argIndex, ULong8 c);
        public void SetArg(int argIndex, ushort c);
        public void SetArg(int argIndex, UShort16 c);
        public void SetArg(int argIndex, UShort2 c);
        public void SetArg(int argIndex, UShort3 c);
        public void SetArg(int argIndex, UShort4 c);
        public void SetArg(int argIndex, UShort8 c);
        public void SetArg(int argIndex, IntPtr argSize, IntPtr argValue);

多いですね。
しかし今回使うのはSetArg(int argIndex, Mem mem)だけです。

argIndexは引数の位置です。例えば最初の引数なら0です。

カーネルの実行

最後はカーネルの実行を行うCommandQueue.EnqueueTaskメソッドを紹介します。

public void EnqueueTask(Kernel kernel);

kernelは実行するカーネルです。

サンプルコード

Program.cs

using OpenCLNet;

class Program
{
    static void Main()
    {
        var platform = OpenCL.GetPlatform(0);
        var context = platform.CreateDefaultContext();
        var commandQueue = context.CreateCommandQueue(platform.QueryDevices(DeviceType.DEFAULT)[0]);

        var program = context.CreateProgramWithSource(
            System.IO.File.ReadAllText("myKernelProgram.cl")
            );
        program.Build();

        var kernel = program.CreateKernel("myKernelFunction");
        var buffer = context.CreateBuffer(MemFlags.READ_WRITE, 3 * sizeof(float));
        kernel.SetArg(0, buffer);

        commandQueue.EnqueueTask(kernel);
        float[] readBack = new float[3];
        buffer.Read(commandQueue, 0, readBack, 0, readBack.Length);

        foreach (var number in readBack)
        {
            System.Console.WriteLine(number);
        }

        buffer.Dispose();
        kernel.Dispose();
        program.Dispose();
        commandQueue.Dispose();
        context.Dispose();
    }
}

myKernelProgram.cl

__kernel void myKernelFunction(__global float* numbers)
{
    numbers[0] = 3;
    numbers[1] = 4;
    numbers[2] = 5;
}

このプログラムは実行すると次のような結果になります:

3
4
5

拍手[0回]

PR