【问题标题】:OpenCL crashing while dynamic linking?动态链接时OpenCL崩溃?
【发布时间】:2014-03-08 23:47:10
【问题描述】:

我正在尝试在运行时加载 OpenCL 库,以便相同的 exe 可以在没有 OpenCL 驱动程序的平台上运行而不会找到未解析的符号。我正在使用 Qt 来执行此操作,但我认为我不会因为 Qt 而面临问题。这是我检查是否安装了 OpenCL 1.1 的函数:

QLibrary *MyOpenCL::openCLLibrary = NULL;

bool MyOpenCL::loadOpenCL()
{
    if(openCLLibrary)
        return  true;

    QLibrary *lib = new QLibrary("OpenCL");
    if(!lib->load())
        return false;

    bool result = false;
    typedef cl_int (*MyPlatorms)(cl_uint, cl_platform_id *, cl_uint *);
    MyPlatorms pobj = (MyPlatorms) lib->resolve("clGetPlatformIDs");
    if(pobj)
    {
        cl_uint nplatforms = 0;
        cl_uint myerr = pobj(0, NULL, &nplatforms);
        if((myerr == CL_SUCCESS) && (nplatforms > 0))
        {
            cl_platform_id *mplatforms = new cl_platform_id[nplatforms];
            myerr = pobj(nplatforms, mplatforms, NULL);

            typedef cl_int (*MyPlatformInfo)(cl_platform_id, cl_platform_info, size_t, void *, size_t *);
            MyPlatformInfo pinfoobj = (MyPlatformInfo) lib->resolve("clGetPlatformInfo");
            if(pinfoobj)
            {
                size_t size;
                for(unsigned int i = 0; i < nplatforms; i++)
                {
                    size = 0;
                    myerr = pinfoobj(mplatforms[i], CL_PLATFORM_VERSION, 0, NULL, &size);//size = 27
                    if(size < 1)
                        continue;

                    char *ver = new char[size];
                    myerr = pinfoobj(mplatforms[i], CL_PLATFORM_VERSION, size, ver, NULL);
                    qDebug() << endl << ver;//segmentation fault at this line
...
}

可以看出Qt成功解析了clGetPlatformIDs()。它甚至显示有 1 个平台可用。但是当我传递数组来存储 cl_platform_id 时,它会崩溃。 为什么会这样?

编辑: 我正在使用带有 OpenCL APP SDK 2.9 的 MinGW 编译器的 Qt 4.8.1。 我正在使用来自 Khronos 网站的 OpenCL 1.1 标头。 我的笔记本电脑有 Windows7 64 位也有 ATI Radeon 7670m GPU,它有 OpenCL 1.1 驱动程序。

【问题讨论】:

  • 不相关,但如果您使用 C++ 编程,为什么要使用 calloc?为什么不cl_platform_id *mplatforms = new cl_platform_id[nplatforms];
  • QLibrary *MyOpenCL::openCLLibrary = NULL; -> 这是一个非常非常糟糕的主意。请在源文件中使用Q_GLOBAL_STATIC(QLibrary, myOpenCLLibrary) 代替(注意,不是标题)。更不用说,您应该使用 Q_NULLPTR 而不是“NULL”。
  • @LaszloPapp 为什么?它看起来像一个普通的static 成员变量定义。
  • @JoachimPileborg OpenCL 就像 C 语言的一个子集。到目前为止,我看到的所有教程都在使用 OpenCL 时使用 C 风格的编程。那么如果我在 C++ 中使用 C 风格的编程,将来会有什么问题吗?
  • @Cool_Coder 那么对于使用 C 函数的 C++ 来说,在指针之类的东西方面确实没有区别。指针是指针是指针。 如何分配并不重要。

标签: c++ qt opencl


【解决方案1】:

clGetPlatformIDs 的第一个参数是允许驱动程序写入第二个元素指向的数组的元素数。

如果是第一次调用,则为这些传递 INT_MAX 和 NULL。我预计这里会发生崩溃,因为您正在告诉驱动程序继续并通过您的 NULL 指针进行写入。

您应该为第一个参数传递 0,因为您只关心返回的第三个参数值。

在第二次调用中,您至少传递了第二个参数的有效内存,但您再次传递了 INT_MAX。在这里您应该传递nplatforms,因为这是您分配的内存量。对于第三个参数,请传递 NULL,因为您不需要返回值(再次)。

【讨论】:

  • 感谢您的回答。根据您的建议,我进行了更改并更新了上面的代码。但我仍然遇到分段错误。还有什么问题?
  • 感谢您更新原始问题中的代码。我没有使用 QLibrary “lib->resolve” 技术,但我猜它由于某种原因不起作用。 MyPlatorms 声明在哪里(还要检查拼写)?
  • MyPlatforms 是指向 clGetPlatformIDs 的函数指针。它不需要声明。我也在这里发现了很多可疑的生意。当第一次调用 pobj 完成时,我得到 nplatoforms 为 1。在第二次调用 pinfoobj nplatforms 后,nplatforms 变为 2768。大小也在 ver 的内存分配语句中改变它的值,这绝对没有意义。那么这是否意味着Qt没有正确链接?
  • 考虑到延迟加载的缺点,我想我会将我的 OpenCL 代码添加到一个单独的 dll 中,该 dll 将从 SDK 静态链接到 OpenCL.lib。在我的可执行文件中,我将检查 OpenCL.dll 是否存在。如果是,那么我将加载我的 dll 并使用 OpenCL 功能。这似乎是目前唯一的选择。你在你的应用程序中做什么?
  • 我们在 OpenCL.dll 上使用 /DELAYLOAD。以前我们动态加载 OpenCL.dll 并在每个 API 周围都有一个 GetProcAddress 包装器,但这很麻烦。
猜你喜欢
  • 1970-01-01
  • 2014-05-05
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
相关资源
最近更新 更多