1
votes

I'm writing a program on C# using OpenCL (Cloo.dll) and i need to pass the large buffer to OpenCL ComputeDevice. When I pass this buffer to OpenCL ComputeDevice - program crashes without any exception or error.

Code:

    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:

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);}
}

I read about ComputeDevice.MaxParameterSize - maximum size of parameter that can be passed to device. To my mind, the problem is here, because small buffers (size < 1KB) can be passed well. MaxParameterSizes in my devices are 1024 and 4096 bytes, but these values are very small. I need to pass buffers with size over 100 MB.

How can I pass a large buffer to device? Can I pass only a pointer to this buffer?

My OpenCL Devices:

AMD Radeon HD8750M 2048MB,

Intel Core I3 4000M + 6GB RAM

Edited:

Because of kernel works with uchar16 data, i have to set GlobalSize as buffer.size / 16.

I only changed one line of code(buffer size divides by 16):

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

Everything works fine. Thanks everyone!!!)

1
More than 100 MB? I think you should try EnqueueMapBuffer() + EnqueueUnmapMemObject.Blas Soriano
Could you give more detail explanation?Roman Doskoch
I need pass big buffer to encrypt/decrypt data. Maybe, there are other ideas how to do it.Roman Doskoch

1 Answers

2
votes

The MaxParameterSize query specifies that maximum size needed to store the argument values, not the size of the buffers that those arguments might point to.

To find out how large a single buffer can be, you need to check the MaxMemoryAllocationSize query. The OpenCL 1.2 spec mandates that this will be at least 128MB, but it will probably be more, depending on the device.