为什么我在使用enqueueNDRangeKernel时得到 "Invalid kernel arguments "错误信息?

问题描述 投票:1回答:1

我现在的算法会调用 enqueueNDRangeKernel 函数,每次调用多次。在调用它之前,我将使用 enqueueWriteBuffer 来修改一个参数的值。但现在的问题是,有时在调用 enqueueNDRangeKernel,会出现一个 "无效的内核参数 "错误。上次出现是在上个月。昨天又出现了,太随机了。谁能给我一个解决办法?我查了相关资料,说这个错误一般是因为内核参数没有设置,但我查了一下 enqueueWriteBuffer 函数,它没有报告任何错误。我传给GPU的参数是。

cl.setKernelArg(kernel, 0, "double*", d_X);
cl.setKernelArg(kernel, 1, "double*", d_A);
cl.setKernelArg(kernel, 2, "int*", d_A_INDIEX);
cl.setKernelArg(kernel, 3, "int*", d_A_INDICE);
cl.setKernelArg(kernel, 4, "double*", d_CONSTANTS);
cl.setKernelArg(kernel, 5, "int*", d_ourpartitions);
cl.setKernelArg(kernel, 6, "int*", d_INDIEX);
cl.setKernelArg(kernel, 7, "int*", d_hasGreater);
cl.setKernelArg(kernel, 8, "int", xnum);
cl.setKernelArg(kernel, 9, "int", ynum);
cl.setKernelArg(kernel, 10, "int", n);
cl.setKernelArg(kernel, 11, "int", iterations);
cl.setKernelArg(kernel, 12, "double", error);

我调用enqueueNDRangeKernel的方式是这样的:

for (var j = 0; j <partitions.length;j++) {
    INDIEX[0] = INDICE[j];
    State = cl.enqueueWriteBuffer(queue, d_INDIEX, true, 0, intsize, INDIEX);
    if(State != 0){
        console.log("Write INDIEX error! "+ State);
    }
    var localSize = null;
    // This place sometimes gives an error: Error: Invalid kernel arguments ?? (you can look at it again)
    var globalSize=[partitions[j].length];
    State = cl.enqueueNDRangeKernel(queue, kernel, 1,
        null,
        globalSize,
        localSize
    );
    if(State != 0){
        console.log("enqueueNDRangeKernel error! "+ State);
    }
    cl.finish(queue);
}

我的内核函数原型如下:

__kernel void kernelCode(
    __global double* X,
    __global double * A,
    __global int * A_INDIEX,
    __global int * A_INDICE,
    __global double * b,
    __global int* partitions,
    __global int* INDIEX,
    __global int* hasGreater,
    const int xnum,
    const int ynum,
    const int n,
    const int iterations,
    const double error);
javascript node.js c opencl node-opencl
1个回答
0
投票

所以,我从来没有使用过 节点所以我不是使用它的专家。但看起来它处理错误的方式和你的代码预期的不同。具体来说,在 的执行情况 enqueueNDRangeKernel 包皮:

  CHECK_ERR(::clEnqueueNDRangeKernel(
    q->getRaw(),
    k->getRaw(),
    work_dim,
    cl_work_offset.size() ? cl_work_offset.data() : nullptr,
    cl_work_global.size() ? cl_work_global.data() : nullptr,
    cl_work_local.size() ? cl_work_local.data() : nullptr,
    (cl_uint)cl_events.size(), NOCL_TO_CL_ARRAY(cl_events, NoCLEvent),
    eventPtr
  ));
  RETURN_EVENT
}

我们可以看到,对OpenCL的底层调用中的 clEnqueueNDRangeKernel 被包裹在 CHECK_ERR 的宏,它是 这样定义:

#define CHECK_ERR(ret)  { cl_int _err=(ret); \
  if ((_err) != CL_SUCCESS) { \
    return Nan::ThrowError(JS_STR(opencl::getExceptionMessage(_err))); \
  } \
}

RETURN_EVENT meanwhile是这样定义的。

#define RETURN_EVENT                                        \
  if (eventPtr) {                                           \
    info.GetReturnValue().Set(NOCL_WRAP(NoCLEvent, event)); \
  } else {                                                  \
    info.GetReturnValue().Set(JS_INT(CL_SUCCESS));          \
  }

这意味着任何错误都不会通过JS包装函数的返回值返回,而是通过一个抛出的异常来返回。所以,如果我的JavaScript知识没问题的话,如果在一个CL调用过程中遇到了错误,你的 "错误处理 "代码将永远不会真正运行,因为函数因为抛出异常而提前退出。

所以我不知道你的问题的根本原因是什么,但是。

  • State 只有当你的代码为0的时候CL_SUCCESS)或一个事件对象,它永远不会返回错误。
  • 如果你想处理错误,看起来你需要使用一个叫做 trycatch 构造。
  • 我想你需要详细看看你的内核参数是怎么回事。很明显 clEnqueueNDRangeKernel 正在返回 CL_​INVALID_​KERNEL_​ARGS.

由于它 "大部分时间 "都在工作,我怀疑缓冲区的创建以某种方式结束,也许是因为资源耗尽?我不知道node-opencl是如何处理缓冲区的,但如果它使用垃圾回收来代替显式销毁缓冲区,我可以想象你可能需要在处理完缓冲区后强制进行一次清扫。如果缓冲区 明确的创造和毁灭,也许你并不是在毁灭所有的人?

© www.soinside.com 2019 - 2024. All rights reserved.