InvalidKernelArgs для enqueueNDRange, в то время как аналогичный вызов работает нормально - PullRequest
0 голосов
/ 03 марта 2019

Я использую JavaCL для обработки изображений.Я продолжаю получать

com.nativelibs4java.opencl.CLException $ InvalidKernelArgs: InvalidKernelArgs

При вызове enqueueNDRange вызов в этом (часть)функция:

FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*XYZ.length).order(context.getByteOrder()).asFloatBuffer();
CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);

CLFloatBuffer cl_inBuffer = context.createFloatBuffer(CLMem.Usage.Input,XYZ.length);
FloatBuffer inBuffer = cl_inBuffer.map(queue, CLMem.MapFlags.Write).put(XYZ);
inBuffer.rewind();
event = cl_inBuffer.unmap(queue, inBuffer);

XYZ2RGBKernel.setArgs(cl_inBuffer, XYZ.length/4,cl_outBuffer);
event = XYZ2RGBKernel.enqueueNDRange(queue, new int[]{XYZ.length/4}, event);

event = cl_outBuffer.read(queue, outBuffer, true, event);

XYZ - массив пикселей с 4 числами на пиксель (закодированный как RGBARGBARGBA ....)

Связанный заголовок ядра:

__kernel void XYZ2RGB(  __constant float3* inputXYZ,
                    int numberOfPixels,
                    __global float* output
                    )

Я не могу понять, почему это не работает, так как этот вызов enqueueNDRange:

        CLFloatBuffer cl_Rbuffer = context.createFloatBuffer(CLMem.Usage.Input, R.length);
        FloatBuffer R_buffer = cl_Rbuffer.map(queue, CLMem.MapFlags.Write).put(R);
        R_buffer.rewind();
        event = cl_Rbuffer.unmap(queue, R_buffer);

        CLFloatBuffer cl_Gbuffer = context.createFloatBuffer(CLMem.Usage.Input, G.length);
        FloatBuffer G_buffer = cl_Gbuffer.map(queue, CLMem.MapFlags.Write, event).put(G);
        G_buffer.rewind();
        event = cl_Gbuffer.unmap(queue, G_buffer);

        CLFloatBuffer cl_Bbuffer = context.createFloatBuffer(CLMem.Usage.Input, B.length);
        FloatBuffer B_buffer = cl_Bbuffer.map(queue, CLMem.MapFlags.Write, event).put(B);
        B_buffer.rewind();
        event = cl_Bbuffer.unmap(queue, B_buffer);

        FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*4*R.length).order(context.getByteOrder()).asFloatBuffer();
        CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);

        RGB2XYZKernel.setArgs(cl_Rbuffer, cl_Gbuffer, cl_Bbuffer, cl_outBuffer);

        event = RGB2XYZKernel.enqueueNDRange(queue, new int[]{R.length}, event);
        event = cl_outBuffer.read(queue, outBuffer, true, event);

Со связанным заголовком ядра:

__kernel void RGB2XYZ(     __constant float* inputR,
                        __constant float* inputG,
                        __constant float* inputB,
                        __global float3* output)

Работает без проблем.

Прежде чем кто-либо спросит, float3 или float4 будут работать одинаково, потому что спецификации OpenCL используют 4 * sizeof (float) выравнивание для обоих.И я пробовал переключаться между ними.Я также попытался передать ввод как float *, но он тоже не работает.Оба вызова происходят один за другим.

Обновление

Я исправил это после нескольких часов:

  • __ константа, кажется, имеет ограничение размера (не удалось найтичто в спецификации хотя).XYZ в 4 раза больше R, G или B, он завис во время выполнения.
  • У меня были проблемы с float3.Кажется, что библиотека, которую я вынужден использовать, не обновлена, и поэтому она не была достаточно хорошо поддержана, поэтому я перешел на float4

Однако, если у кого-то из вас есть какие-тобольше информации о __constant ограничение размера и прочее, дайте мне знать, я уверен, что это будет полезно для людей, которые столкнутся с этой темой.

1 Ответ

0 голосов
/ 06 марта 2019

__ константа, похоже, имеет ограничение по размеру (хотя это не удалось найти в спецификации).

Пределы зависят от устройства.Постоянные буферы имеют ограничение размера каждого буфера (CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, мин. 64 КБ), а также существует ограничение на количество постоянных аргументов, которые вы можете передать ядру (CL_DEVICE_MAX_CONSTANT_ARGS, мин. 8).Графические процессоры AMD и Nvidia обычно близки к минимумам, поэтому общий объем данных, которые можно передавать как __constant, может быть очень маленьким.пользовательские данные для ядер (как вы, кажется, используете их);Дело в том, чтобы хранить специфичные для алгоритма константы (справочные таблицы, коэффициенты матрицы / полинома / фильтра и т. д.).Если вы хотите передать входные данные только для чтения, обычным способом является объявление аргумента ядра как __global const <type>* и создание соответствующего буфера с CL_MEM_READ_ONLY.

Здесь еще немногопонимание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...