【问题标题】:How to pass large buffers to OpenCL devices?如何将大缓冲区传递给 OpenCL 设备?
【发布时间】:2015-08-13 04:13:46
【问题描述】:

我正在使用 OpenCL (Cloo.dll) 在 C# 上编写程序,我需要将大缓冲区传递给 OpenCL ComputeDevice。当我将此缓冲区传递给 OpenCL ComputeDevice - 程序崩溃,没有任何异常或错误。

代码:

    ComputeBuffer<Byte> dataBuffer = new ComputeBuffer<Byte>(this._context,
        ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, data.LongLength, ptrData);
    ComputeBuffer<Byte> keysBuffer = new ComputeBuffer<Byte>(this._context,
        ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, Keys);
    ComputeBuffer<Byte> resultBuffer = new ComputeBuffer<Byte>(this._context,
        ComputeMemoryFlags.WriteOnly | ComputeMemoryFlags.CopyHostPointer, result.LongLength, ptrResult);


    this._kernel = this._program.CreateKernel("AES_ECB_Encrypt");

    this._kernel.SetMemoryArgument(0, dataBuffer);
    this._kernel.SetMemoryArgument(1, keysBuffer);
    this._kernel.SetValueArgument<int>(2, 10);
    this._kernel.SetValueArgument<long>(3, data.LongLength);
    this._kernel.SetMemoryArgument(4, resultBuffer);

    ComputeDevice bestDevice = this._devices[0];

    this._queue = new ComputeCommandQueue(this._context, bestDevice, ComputeCommandQueueFlags.None);
    this._queue.Execute(this._kernel, null, new long[] {data.LongLength}, null, null); // here is the crash.

OpenCL 内核:

kernel void AES_ECB_Encrypt(__global uchar16* InputData,__global uchar16* Keys,int GRounds,ulong GLength,__global uchar16* Result)
{
    int Index=get_global_id(0);

    int Rounds=GRounds;
    ulong Length=GLength;

    if (Index<Length){
        uchar16 State=TurnData(InputData[Index]);

        State=AddRoundKey(State,Keys[0]);

        for (int round=1;round<Rounds;round++){
            State=SubBytes(State);
            State=ShiftRows(State);
            State=MixColumns(State);
            State=AddRoundKey(State,Keys[round]);}


        State=SubBytes(State);
        State=ShiftRows(State);
        State=AddRoundKey(State,Keys[Rounds]);

        Result[Index]=TurnData(State);}
}

我读到了 ComputeDevice.MaxParameterSize - 可以传递给设备的参数的最大大小。在我看来,问题就在这里,因为可以很好地传递小缓冲区(大小

如何将大缓冲区传递给设备?我可以只传递一个指向这个缓冲区的指针吗?

我的 OpenCL 设备:

AMD Radeon HD8750M 2048MB,

英特尔酷睿 I3 4000M + 6GB 内存

已编辑

由于内核使用 uchar16 数据,我必须将 GlobalSize 设置为 buffer.size / 16

我只更改了一行代码(缓冲区大小除以 16):

this._queue.Execute(this._kernel, null, new long[] {data.LongLength/16}, null, null);

一切正常。谢谢大家!!!)

【问题讨论】:

  • 超过 100 MB?我认为你应该尝试 EnqueueMapBuffer() + EnqueueUnmapMemObject。
  • 你能给出更详细的解释吗?
  • 我需要通过大缓冲区来加密/解密数据。也许,还有其他想法如何做到这一点。

标签: c# opencl cloo


【解决方案1】:

MaxParameterSize 查询指定存储参数所需的最大大小,而不是这些参数可能指向的缓冲区的大小。

要了解单个缓冲区的大小,您需要检查MaxMemoryAllocationSize 查询。 OpenCL 1.2 规范要求这将是至少 128MB,但可能会更多,具体取决于设备。

【讨论】:

  • 好的,在我的 CPU 上 MaxParameterSize 是 4096 字节。当我尝试传递小于 4096 字节的缓冲区时 - 一切正常,但是当缓冲区的大小超过 4096 时(我尝试传递大小为 4098 字节的缓冲区),程序崩溃。你有什么想法?谢谢。
  • 我在考虑。我不知道出了什么问题。请帮帮我)
  • 您对 MaxParametrSize 的看法是正确的。我已经纠正了我的错误。我编辑的答案中有新代码。
猜你喜欢
  • 2013-06-19
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
相关资源
最近更新 更多