如何将大缓冲区传递给 OpenCL 设备?
How to pass large buffers to OpenCL devices?
我正在使用 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 - 可以传递给设备的参数的最大大小。在我看来,问题就在这里,因为可以很好地传递小缓冲区(大小 < 1KB)。
我设备中的 MaxParameterSizes 是 1024 和 4096 字节,但这些值非常小。我需要传递大小超过 100 MB 的缓冲区。
如何将大缓冲区传递给设备?我可以只传递指向此缓冲区的指针吗?
我的 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);
一切正常。谢谢大家!!!)
MaxParameterSize
查询指定存储参数 values 所需的最大大小,而不是这些参数可能指向的缓冲区的大小。
要了解单个缓冲区可以有多大,您需要检查 MaxMemoryAllocationSize
查询。 OpenCL 1.2 规范规定这将是至少 128MB,但可能会更多,具体取决于设备。
我正在使用 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 - 可以传递给设备的参数的最大大小。在我看来,问题就在这里,因为可以很好地传递小缓冲区(大小 < 1KB)。 我设备中的 MaxParameterSizes 是 1024 和 4096 字节,但这些值非常小。我需要传递大小超过 100 MB 的缓冲区。
如何将大缓冲区传递给设备?我可以只传递指向此缓冲区的指针吗?
我的 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);
一切正常。谢谢大家!!!)
MaxParameterSize
查询指定存储参数 values 所需的最大大小,而不是这些参数可能指向的缓冲区的大小。
要了解单个缓冲区可以有多大,您需要检查 MaxMemoryAllocationSize
查询。 OpenCL 1.2 规范规定这将是至少 128MB,但可能会更多,具体取决于设备。