【问题标题】:Opencl clBuildProgram() access violation exceptionOpencl clBuildProgram() 访问冲突异常
【发布时间】:2022-05-04 13:55:19
【问题描述】:

我在执行 opencl 内核时遇到了一个奇怪的错误,当我尝试使用 clBuildProgram() 执行构建 opencl 内核时

err = clBuildProgram(program, 1, &ocl->device, "", NULL, NULL);

我的进程开始使用越来越多的内存,直到达到 13GB(通常它使用大约 400MB),然后产生:

“0xC0000005:访问冲突执行位置”

奇怪的是,只有当我使用集成卡时才会发生这种情况,即 Intel HD 4000。如果选择其他设备,如 GTX 960 或 CPU,它工作正常。

另外一个奇怪的事情是,如果有任何语法错误,clBuildProgram 函数会正常结束,给出编译错误,只有在没有任何错误的情况下才会出现。另外,如果我对我的代码的一部分进行注释,它会继续。

这是我的功能:

__kernel void update(__global struct PhysicsComponent_ocl_t* vecPhy, __constant struct BoxCollider_ocl_t* vecBx, __constant ulong* vecIdx, __constant float* deltaTime) {
    unsigned int i = get_global_id(0);
    unsigned int j = get_global_id(1);

    if (j > i) { //From size_t j = i + 1; i < vec.size()... 
        //Copy data to local memory to avoid race conditions
        struct AuxPhy_ocl_t phy1;
        copyPhyGL(&vecPhy[vecIdx[i]], &phy1);

        struct AuxPhy_ocl_t phy2;
        copyPhyGL(&vecPhy[vecIdx[j]], &phy2);

        if (collide(&phy1, &phy2, &vecBx[i], &vecBx[j])) {
            ////Check speed correction for obj 1
            struct mivec3_t speed1 = phy1.speed;
            struct mivec3_t speed2 = phy2.speed;

            modifySpeedAndVelocityOnCollision(&phy1, &phy2, &vecBx[i], &vecBx[j], *deltaTime);         //Comprobar los dos objetos, por eso se le da la vuelta a los parametros
            modifySpeedAndVelocityOnCollision(&phy2, &phy1, &vecBx[j], &vecBx[i], *deltaTime);

            //Make the objects not move
            struct mivec3_t auxSub;
            multiplyVectorByScalarLL(&speed1, *deltaTime, &auxSub);
            substractVectorsLL(&phy1.position, &auxSub, &phy1.position);

            multiplyVectorByScalarLL(&speed2, *deltaTime, &auxSub);
            substractVectorsLL(&phy2.position, &auxSub, &phy2.position);

            //Copy data back to global
            copyPhyLG(&phy1, &vecPhy[vecIdx[i]]);
            copyPhyLG(&phy2, &vecPhy[vecIdx[j]]);
        }
    }
}

例如。如果我注释最后两个函数,则构建程序。

//Copy data back to global
//copyPhyLG(&phy1, &vecPhy[vecIdx[i]]);
//copyPhyLG(&phy2, &vecPhy[vecIdx[j]]);

但它们不是造成这种情况的原因,因为如果我把这个函数放在身体的注释部分,它也可以工作。

__kernel void update(__global struct PhysicsComponent_ocl_t* vecPhy, __constant struct BoxCollider_ocl_t* vecBx, __constant ulong* vecIdx, __constant float* deltaTime) {
    unsigned int i = get_global_id(0);
    unsigned int j = get_global_id(1);

    if (j > i) { //From size_t j = i + 1; i < vec.size()... 
        //Copy data to local memory to avoid race conditions
        struct AuxPhy_ocl_t phy1;
        copyPhyGL(&vecPhy[vecIdx[i]], &phy1);

        struct AuxPhy_ocl_t phy2;
        copyPhyGL(&vecPhy[vecIdx[j]], &phy2);

        //Removed code was here

        copyPhyLG(&phy1, &vecPhy[vecIdx[i]]);
        copyPhyLG(&phy2, &vecPhy[vecIdx[j]]);
    }
}

我对此感到震惊,我唯一想到的就是代码占用了太多空间。

这是完整的内核code

【问题讨论】:

  • 您是否尝试过添加诸如-Werror-g 之类的编译选项,指定诸如-cl-std=CL1.2-cl-std=CL1.1 之类的OpenCL 版本?您是否还检查过您是否可以在系统中的 Intel HD 4000 上实际运行任何 OpenCL 内核?您的系统报告的 Intel HD 4000 的 OpenCL 版本是什么?也许您需要更新 GPU 驱动程序?您是否尝试过使用英特尔 OpenCL SDK?有很多可能出错的地方......几年前,我曾经使用 Intel HD 4000 在 Windows 上进行 OpenCL 工作,它工作正常。
  • 我尝试使用 -Werror 和 -g 进行编译,还将 opencl 版本设置为 1.2 和 1.1(包括将其传递给 clBuildProgram(program, 1, &ocl->device, "-cl- std=CL1.2", NULL, NULL); ) 但没有运气。是的,我使用的是英特尔 OpenCL SDK。而且我的驱动程序也更新了。
  • 运行简单的 OpenCL 程序来检查是否可以运行,怎么样?
  • 正如我在问题中所说,如果我评论部分代码,它可以正常工作。
  • 如果你删除最后两个函数,那么我会说内核代码是一个死代码 - 优化器很可能会删除其余的内核实现,因此它会构建。但是,如果您在这两个函数之前删除代码并且它可以工作,那么这意味着问题出在某个地方。逐一删除函数调用以缩小可能导致问题的函数。

标签: exception kernel gpu opencl access-violation


【解决方案1】:

我遇到了类似的问题,就我而言,这是我的一个内核中的无限循环。我猜编译器试图在不检查边界的情况下以某种方式展开或优化它。

为了验证我的假设,我构建了关闭优化的 ocl 程序

    int err = program.build("-cl-opt-disable");

并且构建成功如我所料。

当您引入语法错误时,编译过程会提前停止,并且不会到达编译器错误所在的优化部分。

其他设备的编译器没有这个错误,它们会给你一个可执行文件,你可以运行但可能不会(正确地)终止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多