OpenCL在调用clGetPlatformID时崩溃 [英] OpenCL crashes on call to clGetPlatformIDs

查看:310
本文介绍了OpenCL在调用clGetPlatformID时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是OpenCL的新手.在运行Windows 7的具有Intel®HD Graphics 4000的Core i5计算机上工作,我安装了支持OpenCL的最新Intel驱动程序. GpuCapsViewer确认我具有OpenCL支持设置.我使用英特尔OpenCL SDK开发了一个简单的HelloWorld程序.我已经成功编译了该程序,但是在运行时,由于出现分段错误而调用clGetPlatformIDs()时,该程序崩溃了.这是我的代码:

I am new to OpenCL. Working on a Core i5 machine with Intel(R) HD Graphics 4000, running Windows 7. I installed the newest Intel driver with support for OpenCL. GpuCapsViewer confirms I have OpenCL support setup. I Developed a simple HelloWorld program using Intel OpenCL SDK. I successfully compile the program but when run, it crashes upon call to clGetPlatformIDs() with a segmentation fault. This is my code:

#include <iostream>
#include <CL/opencl.h>

int main() {
    std::cout << "Test OCL  without driver" << std::endl;

    cl_int err;
    cl_uint num_platforms;

    err = clGetPlatformIDs(0, NULL, &num_platforms);
    if (err == CL_SUCCESS) {
        std::cout << "Success. Platforms available: " << num_platforms
                << std::endl;
    } else {
        std::cout << "Error. Platforms available: " << num_platforms
                << std::endl;
    }

    std::cout << "Test OCL without driver" << std::endl;
    std::cout << "Press button to exit." << std::endl;
    std::cin.get();
    return 0;
}

GpuCapsViewer如何成功确认OpenCL支持并可以使用它来运行其演示程序,但是我无法运行我的代码?两者必须使用相同的功能,对吧?

How can it be that GpuCapsViewer successfully confirms OpenCL support and can use it to run its demos, but I can't run my code? Both must be using the same functions, right?

为此工作了几天.甚至尝试重新安装驱动程序.有任何想法吗?

Been working on this for days. Even tried re installing the drivers. Any Ideas?

GpuCapsViewer说:

GpuCapsViewer says:

驱动程序:R295.93(r295_00-233)/10.18.10.3496(3-11-2014)
OPENGL:OpenGL 4.2(GeForce GT 630M/PCIe/SSE2,具有290 ext.)
OPENCL:OpenCL 1.1,GeForce GT 630M计算单元:2 @ 950MHz
CUDA:GeForce GT 630M CC:2.1,多处理器:2 @ 950MHz
PHYSX:GPU PhysX(NVIDIA GeForce GT 630M)
多GPU:不支持多GPU(2个物理GPU)

DRIVER: R295.93 (r295_00-233) / 10.18.10.3496 (3-11-2014)
OPENGL: OpenGL 4.2 (GeForce GT 630M/PCIe/SSE2 with 290 ext.)
OPENCL: OpenCL 1.1, GeForce GT 630M compute units:2@950MHz
CUDA: GeForce GT 630M CC:2.1, multiprocessors:2@950MHz
PHYSX: GPU PhysX (NVIDIA GeForce GT 630M)
MULTI-GPU: no multi-GPU support (2 physical GPUs)


更新:


UPDATE:

编译行:

g++ -I"C:\Program Files (x86)\Intel\OpenCL SDK\4.4\include" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"Test3.d" -MT"Test3.d" -o "Test3.o" "../Test3.cpp"
Finished building: ../Test3.cpp

链接器行:

g++ -L"C:\Program Files (x86)\Intel\OpenCL SDK\4.4\lib\x64" -o "TestOpenCL"  ./HelloWorld.o ./HelloWorld2.o ./Test3.o   -lOpenCL
Finished building target: TestOpenCL

OS:Windows 7 Ultimate版本6.1(内部版本7601:Service Pack 1)

OS: Windows 7 Ultimate Version 6.1 (Build 7601: Service Pack 1)

更新2,崩溃信息:

Problem Event Name: APPCRASH
Application Name:   TestOpenCL.exe
Application Version:    0.0.0.0
Application Timestamp:  53bc6ac5
Fault Module Name:  TestOpenCL.exe
Fault Module Version:   0.0.0.0
Fault Module Timestamp: 53bc6ac5
Exception Code: c0000005
Exception Offset:   0000000000002cc0
OS Version: 6.1.7601.2.1.0.256.1
Locale ID:  1033
Additional Information 1:   56e3
Additional Information 2:   56e3743a8a234df3bdeba0b507471c44
Additional Information 3:   8fe0
Additional Information 4:   8fe0ef5706153941955de850e5612393


更新3:


UPDATE 3:

使用DependencyWalker( http://dependencywalker.com/)代替dumpbin.它生成以下警告:

Used DependencyWalker(http://dependencywalker.com/) as a substitute for dumpbin. It generates the following warnings:

Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

警告似乎是指以下所有标有错误打开文件.系统找不到指定的文件(2)"错误消息的DLL.

The warnings seem to refer to the following DLLs which are all marked with a "Error opening file. The system can not find the file specified(2)" error message.

API-MS-WIN-CORE-COM-L1-1-0.DLL
API-MS-WIN-CORE-WINRT-ERROR-L1-1-0.DLL
API-MS-WIN-CORE-WINRT-L1-1-0.DLL
API-MS-WIN-CORE-WINRT-ROBUFFER-L1-1-0.DLL
API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL
API-MS-WIN-SHCORE-SCALING-L1-1-0.DLL
DCOMP.DLL
IESHIMS.DLL


更新4,GDB BACKTRACE:


UPDATE 4, GDB BACKTRACE:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000402cc0 in clGetPlatformIDs ()
(gdb) backtrace full
#0  0x0000000000402cc0 in clGetPlatformIDs ()
No symbol table info available.
#1  0x0000000000402af3 in main () at ../Test3.cpp:11
        err = 0
        num_platforms = 0
        platform = 0x0

(gdb) backtrace
#0  0x0000000000402cc0 in clGetPlatformIDs ()
#1  0x0000000000402af3 in main () at ../Test3.cpp:11


更新5,GDB失败:


UPDATE 5, GDB DISASS:

(gdb) disass
Dump of assembler code for function clGetPlatformIDs:
=> 0x0000000000402cc0 <+0>:     jmpq   *0x4b74e8(%rip)        # 0x8ba1ae
   0x0000000000402cc6 <+6>:     nop
   0x0000000000402cc7 <+7>:     nop
End of assembler dump.


更新6,共享了GDB信息:


UPDATE 6, GDB INFO SHARED:

(gdb) INFO SHARED
From                To                  Syms Read   Shared Object Library
0x0000000077191000  0x00000000773384e0  Yes (*)     C:\Windows\system32\ntdll.dll
0x0000000077071000  0x000000007718eab4  Yes (*)     C:\Windows\system32\kernel32.dll
0x000007fefc081000  0x000007fefc0eb13c  Yes (*)     C:\Windows\system32\KernelBase.dll
0x000007fedf8d1000  0x000007fedf8e96aa  Yes (*)     C:\Windows\system32\OpenCL.dll
0x000007fefe101000  0x000007fefe1da628  Yes (*)     C:\Windows\system32\advapi32.dll
0x000007fefe061000  0x000007fefe0fe4bc  Yes (*)     C:\Windows\system32\msvcrt.dll
0x000007fefdcc1000  0x000007fefdcde39a  Yes (*)     C:\Windows\SYSTEM32\sechost.dll
0x000007fefc6a1000  0x000007fefc7cc914  Yes (*)     C:\Windows\system32\rpcrt4.dll
(*): Shared library is missing debugging information.

二进制文件x64和包含文件夹:

Binary file, x64 and include folders:

https://drive.google.com/file/d/0BxKA63T2GnKMRW02QWZnam5lSGM/edit?usp=sharing


更新7,GPUcaps情况:


UPDATE 7, GPUcaps situation:

GPUcaps检测到2个GPU:

GPUcaps detects 2 GPUs:

  • GPU 1:Intel(R)HD Graphics 4000
  • GPU 2:NVIDIA GeForce GT 630M

您可以在此处查看屏幕截图:

You can see the screenshot here:

https://drive.google.com/file/d/0BxKA63T2GnKMa00tU1gydGNJeXc/edit?usp=sharing


更新8:


UPDATE 8:

每个@antiduh的答案,我一直试图直接针对Windows \ System32文件夹中存在的OpenCL.dll进行链接.我正在使用mingw64.我明白了:

Per @antiduh 's answer, I have been trying to link directly against OpenCL.dll present in Windows\System32 folder. I am using mingw64. I get this:

Invoking: Cross G++ Linker
g++ -L"C:\Windows\System32" -o "TestOpenCL"  ./HelloWorld.o ./HelloWorld2.o ./Test3.o   -lOpenCL
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/OpenCL.dll when searching for -lOpenCL
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/OpenCL.dll when searching for -lOpenCL
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lOpenCL
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/msvcrt.dll when searching for -lmsvcrt
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/advapi32.dll when searching for -ladvapi32
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/shell32.dll when searching for -lshell32
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/user32.dll when searching for -luser32
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/kernel32.dll when searching for -lkernel32
d:/ws/apps_inst/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.7.1/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:\Windows\System32/msvcrt.dll when searching for -lmsvcrt


更新9: 现在,我可以使用以下代码行手动编译,链接和运行示例代码.


UPDATE 9: I can now compile, link and run the sample code manually with the following line.

g++ -I. s.cpp -L. -lOpenCL

我简化了所有工作,并且一切正常.这显然与Eclipse使用的compile和link命令有很大的不同.知道eclipse使用哪个参数会导致问题吗?而且,为什么eclipse首先在两个单独的步骤中编译为目标文件,然后尝试链接它们?

I simplified everything and it just worked. This is obviously very different from the compile and link commands used by Eclipse. Any idea which of the parameters used by eclipse cause the problem? And also, why is it that eclipse first compiles to object files and then attempts to link them, in two separate steps?

推荐答案

程序使用外部库的共有三种方式:

There are three total ways for a program to use external library:

  • 静态链接:将库直接插入可执行文件中.外部库以.lib文件形式提供,仅包含打包的.obj文件.您的程序照常从库中调用函数.编译器从lib中提取可执行代码,将其插入,并对其执行完整,完整的链接.就像您对导入的函数进行编译一样,就像它们是来自您自己的源代码一样.
  • 加载时动态链接,也称为隐式链接":启动程序时加载库.外部库以包含可执行代码的.dll和包含.dll导出内容的.lib文件的形式提供,由编译器和链接器临时链接.链接器使用.lib理解如何在运行时调用.dll,以及将延迟的绑定放入程序中.当操作系统启动程序时,它会执行加载时"链接-查找所有延迟绑定,尝试查找.dll文件,完成程序中延迟绑定的链接,并允许您运行文件.
  • 纯"运行时动态链接,也称为显式链接":直接调用LoadLibrary.您的程序没有对任何.lib,.dll或其他文件的特定引用.您的程序开始运行,它本身使用.dll的字符串路径调用LoadLibrary. LoadLibrary将.dll合并到您的虚拟内存中,然后您的程序调用GetProcAddress以获取指向您要调用的函数的函数指针.然后,您可以使用该函数指针进行调用.

没有.lib,通常无法链接到dll.编译器希望将这些函数调用引用解析为真实地址,但是我们不想放入真实地址,因为我们希望将DLL加载到任意内存地址中(DLL是可重定位的").

You can't normally link against a dll without the .lib. The compiler wants to resolve those function call references to real addresses, but we don't want to put in real addresses since we want DLLs to be loaded into any arbitrary memory address (DLLs are 'relocatable').

据我了解,用作导入库的.lib包含主程序直接链接到的存根-因此程序中的所有调用都通过存根.然后,存根具有对导入地址表"的引用.当OS将DLL加载到进程的内存中时,它通过填写IAT来完成.然后存根仅通过进行间接跳转来调用DLL,该间接跳转引用了右边的IAT中的广告位.

From my understanding, a .lib used as an import library contains stubs that the main program links directly against - so all calls in the program go through the stubs. The stubs then have references to an 'Import Address Table". When the OS loads a DLL into memory for a process, it does so by filling out the IAT. The stub then just calls the DLL by making an indirect jump that references the right slot in the IAT.

因此,如果DLL MathLib具有我的exe导入的导出函数Factorial,则import .lib文件具有实际功能,我的exe静态针对该因数进行编译.该.lib中的那个阶乘看起来像下面的伪代码:

So if a DLL MathLib has an exported function Factorial that my exe is importing, then the import .lib file has an actual function Factorial that my exe statically compiles against. That Factorial in that .lib looks like the following psuedo code:

int Factorial( int value ) { 
   // Read MathLib's IAT which should always be at address 0x8ba100.
   // Factorial's real address gets stored in slot 2, so add 8 to the address
   // to read from.
   __asm jmp *0x8ba108; // nb this is an indirect jump.
}

然后,我们希望当操作系统加载该DLL时,IAT正确填写,否则我们会陷入一片空白.

And then we hope that when the OS loads that DLL, that IAT is filled out correctly, else we jump into nothingness.

所以我认为发生的事情是您正在针对一个.lib进行编译,但是针对错误的opencl.dll进行了加载时"链接. IAT从来没有创建过,或者在错误的地方创建了,因此您陷入了虚无.这就是为什么此行创建段错误的原因:

So I think what happened is that you were compiling against one .lib, but 'load-time' linking against the wrong opencl.dll. The IAT was never created, or was created in the wrong place, and so you jumped into nothingness; that's why this line created a segfault:

0x0000000000402cc0 <+0>: jmpq *0x4b74e8(%rip) # 0x8ba1ae

所以让我们弄清楚为什么链接错误.您的计算机上可能有3套opencl.dll/opencl.lib文件:

So lets figure out why we linked wrong. There could be 3 sets of opencl.dll/opencl.lib files on your computer:

  • 来自Kronos的opencl.lib/dll,实际上只是一个存根/加载程序库,它可以弄清楚您计算机上的真正提供程序,并确实将函数调用分派到实际的正确lib.
  • 英特尔通过其SDK和驱动程序提供的opencl.lib/dll.
  • 来自Nvidia的驱动程序中的opencl.lib/dll.

您实际上有哪些这些文件?因此,我的估计是:

Which of these files did you actually have? My estimate is thus:

  • 来自kronos的opencl.dll已安装到c:\windows\system32.
  • 没有来自Kronos的opencl.lib
  • nvidia可能没有opencl.lib,因为您没有安装他们的SDK.
  • 您可能已经从Intel获得了opencl.lib和opencl.dll,因为您确实安装了它们的SDK.
  • The opencl.dll that came from kronos got installed into c:\windows\system32.
  • There is no opencl.lib from Kronos
  • There was probably no opencl.lib from nvidia, since you didn't have their SDK installed.
  • You probably had an opencl.lib and opencl.dll from Intel since you did have their SDK installed.

您肯定是在针对Intel opencl.lib进行链接,但似乎是在c:\windows\system32中加载了Kronos opencl.dll.一种解决方案是通过在程序运行时将其dll放入程序目录中,以使该程序加载Intel opencl.dll.

You were definitely linking against the Intel opencl.lib, but appeared to be loading the Kronos opencl.dll in c:\windows\system32. One solution would be to get the program to load the Intel opencl.dll when you run the program by putting their dll in your program's directory.

但是,您声明可以使用此编译行使事情正常工作

However, you state that you were able to make things work using this compilation line:

g++ -I. s.cpp -L. -lOpenCL

在Windows上,关于gcc的东西很整洁-要链接到库,请不要需要拥有.lib . Gcc通过检查dll为您找出问题;其他人已经弄清楚了当有人给他们一个dll但没有lib时该怎么做.在大多数其他编译器中,尤其是Visual Studio,您需要具有.lib和.dll才能链接到某些对象.这就是Win SDK安装数百个.lib(例如,kernel32.lib)的原因.事实证明,编译器确实可以根据需要进行推断,但是libs是一种古老的机制.

There's something neat about gcc on Windows - in order to link against a library, you don't need to have the .lib. Gcc figures it out for you by inspecting the dll; other people have figured out how to do the same when someone gives them a dll but no lib. In most other compilers, especially Visual Studio, you need to have a .lib and a .dll to link against something. That's why the Win SDK installs hundreds of .lib (kernel32.lib, eg). Turns out that the compiler can actually infer it if it wanted to, but libs exist as an archaic mechanism.

无论如何,您在gcc链接行上方运行它,它使用搜索路径找到了一个合适的opencl.dll,并为其创建了自己的.lib并对其进行了编译;您启动了程序,它使用相同的搜索路径来获取一个opencl.dll,它与您针对它进行编译的对象相同,因此您的程序可以运行.哇.

Anyway, you ran that above gcc link line, it found a suitable opencl.dll using the search path, invented its own .lib for it, and compiled against it; you launched your program, it used that same search path to get an opencl.dll, it was the same one you compiled against, so your program runs. Whew.

我还有一些建议:

  • 找到来自Kronos的可安装的客户端驱动程序" ICD Loader .然后,该加载程序将弄清楚如何在运行时绑定到特定的提供程序(nvidia,intel等).
  • 将Kronos opencl.dll与您的应用程序一起分发,这样您就永远不会意外地对错误的文件进行运行时链接.
  • 假定提供了特定于Intel的opencl.lib/opencl.dll文件,请卸载Intel SDK.
  • Find an opencl.lib and opencl.dll pair that come from Kronos's "Installable Client Driver" ICD Loader. That loader will then figure out how to bind to a particular provider (nvidia, intel, etc) at runtime.
  • Distribute the Kronos opencl.dll with your application so that you will never accidentally run-time-link against the wrong file.
  • Uninstall the Intel SDK, assuming it's providing opencl.lib/opencl.dll files that are specific to Intel.

关于lib和dll的其他一些相关问题:

Some more relevant questions on libs and dlls:

  • When building a DLL file, does the generated LIB file contain the DLL name?
  • Why are LIB files beasts of such a duplicitous nature?

这篇关于OpenCL在调用clGetPlatformID时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆