1

当我尝试 cl::Program.build() 时,该程序崩溃,但我不知道为什么。它在这段代码的最后一行崩溃:

#define __NO_STD_VECTOR 
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hPP>
#include <iostream>
#include <fstream>
#include <string>
#include <CL/cl.h>

using namespace std;
using namespace cl;
int _tmain(int argc, _TCHAR* argv[])
{
    int tmpSize = 1024;
    float **my2D = new float*[tmpSize];
    for(int i = 0; i < tmpSize; i++)
    {
        my2D[i] = new float[tmpSize];
        for(int i2 = 0; i2 < tmpSize; i2++)
        {
            my2D[i][i2] = 5;
        }
    }
    cl::vector <Platform> platforms;
    Platform::get(&platforms);

    cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[1]()), 0};
    Context context(CL_DEVICE_TYPE_ALL, cps);

    cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

    CommandQueue queue = CommandQueue(context, devices[0], 0);

    int W = tmpSize; //i.width();
    int H = tmpSize; //i.height();

    Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float));
    Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float));

    queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), my2D);

    std::ifstream sourceFileName("c:\\users\\me\\desktop\\img_rotate_kernel.cl");
    std::string sourceFile(istreambuf_iterator<char>(sourceFileName), (istreambuf_iterator<char>()));

    Program::Sources rotn_source(1,std::make_pair(sourceFile.c_str(), sourceFile.length() + 1));
    Program rotn_program(context, rotn_source);
    rotn_program.build(devices); // <----- CRASHES HERE
}

使用这个内核

__kernel void img_rotate(__global float* dest_data, __global float* src_data, int W, int H, float sinTheta, float cosTheta)
    const int ix = get_global_id(0);
    const int iy = get_global_id(1);
    float x0 = W/2.0f;
    float y0 = W/2.0f;
    float xOff = ix-x0;
    float yOff = iy - y0;
    int xpos = (int)(xOff*cosTheta + yOff*sinTheta + x0);
    int ypos = (int)(yOff*cosTheta - yOff*sinTheta + y0);
    if(((int)xpos>=0) && ((int)xpos < W) && ((int)ypos>=0) && ((int)ypos<H))
    {
        dest_data[iy*W+ix] = src_data[ypos*W+xpos];
    }
}

这是我在崩溃时得到的异常对话框

在此处输入图像描述

4

1 回答 1

1

来自OpenCL C++ 包装规范

cl::Program::Program 返回一个有效的程序对象,如果程序对象创建成功,则 err 设置为 CL_SUCCESS。否则,它将返回 err [...] 中返回的以下错误值之一

您的程序对象可能未正确创建,请更改您的程序构造调用以使用err此签名后面的参数

cl::Program::Program(const Context& context, const Sources& sources, cl_int * err = NULL)

并确保err == CL_SUCCESS在对您的程序对象进行任何其他操作之前。

大多数 OpenCL 调用允许您将指针传递给错误参数。你真的应该这样做并在你的电话后检查它(至少在我猜的调试版本中)以减少未来的头痛。


好的,所以我稍微修改了您的源代码。在这里,我将在之后解释我的更改。

#define __NO_STD_VECTOR 
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <CL/cl.h>

#define ARRAY_SIZE 128

using namespace std;
using namespace cl;

int main(int, char**)
{
    int err;

    float my2D[ARRAY_SIZE * ARRAY_SIZE] = { 0 };
    for(int i = 0; i < ARRAY_SIZE * ARRAY_SIZE; i++)
    {
        my2D[i] = 5;
    }

    cl::vector <Platform> platforms;
    err = Platform::get(&platforms);

    if(err != CL_SUCCESS) {
        std::cout << "Platform::get failed - " << err << std::endl;
        std::cin.get();
    }

    cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0]()), 0 };
    Context context(CL_DEVICE_TYPE_ALL, cps, nullptr, nullptr, &err);

    if(err != CL_SUCCESS) {
        std::cout << "Context::Context failed - " << err << std::endl;
        std::cin.get();
    }

    cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(&err);

    if(err != CL_SUCCESS) {
        std::cout << "Context::getInfo failed - " << err << std::endl;
        std::cin.get();
    }

    CommandQueue queue = CommandQueue(context, devices[0], 0, &err);

    if(err != CL_SUCCESS) {
        std::cout << "CommandQueue::CommandQueue failed - " << err << std::endl;
        std::cin.get();
    }

    int W = ARRAY_SIZE; //i.width();
    int H = ARRAY_SIZE; //i.height();

    Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float), nullptr, &err);

    if(err != CL_SUCCESS) {
        std::cout << "Buffer::Buffer 1 failed - " << err << std::endl;
        std::cin.get();
    }

    Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float), nullptr, &err);

    if(err != CL_SUCCESS) {
        std::cout << "Buffer::Buffer 2 failed - " << err << std::endl;
        std::cin.get();
    }

    err = queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]);

    if(err != CL_SUCCESS) {
        std::cout << "Queue::enqueueWriteBuffer failed - " << err << std::endl;
        std::cin.get();
    }

    std::ifstream sourceFileName("so_question.cl");
    std::string sourceFile(std::istreambuf_iterator<char>(sourceFileName), (std::istreambuf_iterator<char>()));

    Program::Sources rotn_source(1,std::make_pair(sourceFile.c_str(), sourceFile.length() + 1));
    Program rotn_program(context, rotn_source, &err);

    if(err != CL_SUCCESS) {
        std::cout << "Program::Program failed - " << err << std::endl;
        std::cin.get();
    }

    err = rotn_program.build(devices);

    if(err != CL_SUCCESS) {
        std::cout << "Program::build failed - " << err << std::endl;
        std::cin.get();
    }
}

你会注意到我添加了更多的错误检查。这让我发现在您的初始程序中调用Context::Context实际上确实失败了。问题可能是platforms[1]不存在(向量中有 1 个元素),所以我将其切换为platforms[0].

queue.enqueueWriteBuffer();一旦解决了这个问题,我就会在通话中遇到访问冲突。问题是您的二维数组实际上是堆分配数组的数组。这是一个问题,因为 OpenCL 期望能够从连续内存中读取数据,而在循环中使用 new 进行分配时,情况并非如此。实际上并不能保证您的数组在内存中彼此相邻。

为了解决这一点,我在堆栈上分配了一个一维数组(参见开头的循环)。然后调用变为

queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]);

但是,您可能无法使用 1024 x 1024 数组来执行此操作,float因为您会占用堆栈空间。如果您需要一个那么大的数组,您可能想要new一个足够大的一维数组来包含您的数据并自己执行索引算术。这可确保您将整个存储空间作为一个连续的块。

代码现在CL_BUILD_PROGRAM_FAILUREerr = rotn_program.build()调用时出错,这意味着您的 CL 程序代码中可能存在错误。由于这是一个完全不同的问题,我会让你解决这个问题。

于 2013-07-22T17:55:06.917 回答