我最近按照NVidia网站,this网站和this网站上的说明在64位Ubuntu 12.04系统上安装了CUDA 5.0。 (作为一个注释,Ubuntu 12.04不是NVidia网站上列出的支持CUDA 5.0的操作系统之一,但显然其他人已安装它并让它在他们的系统上运行。)正确安装驱动程序和软件包后,我会尝试编译并运行
1)包含的样本中的第一个程序(〜/ NVIDIA_CUDA-5.0_Samples / 1_Utilities / deviceQuery /中的可执行deviceQuery)和
2)第一个支持GPU的程序 - 第03章中的simple_kernel.cu - 包含在NVidia发布的 CUDA By Example 书的源代码(可用here)中。
可执行文件1)我通过在相应目录中运行make
获得;可执行文件2)我用nvcc simple_kernel.cu
获得。两者的结果都是这个输出:
./deviceQuery: error while loading shared libraries: libcudart.so.5.0: cannot open shared object file: No such file or directory
或
./a.out: error while loading shared libraries: libcudart.so.5.0: cannot open shared object file: No such file or directory
为清楚起见,是的,我已将PATH
变量设置为包含/usr/local/cuda-5.0/bin
,并将LD_LIBRARY_PATH
变量设置为包含/usr/local/cuda-5.0/lib
和/usr/local/cuda-5.0/lib64
,是的,有/usr/local/cuda-5.0/lib/libcudart.so
指向/usr/local/cuda-5.0/lib/libcudart.so.5.0
的链接以及指向/usr/local/cuda-5.0/lib/libcudart.so
的{{1}}。但这导致了我的问题......
我通过在〜/ .bashrc文件中添加行修改了我的PATH和LD_LIBRARY_PATH变量
/usr/local/cuda-5.0/lib/libcudart.so.5.0
和
export PATH=${PATH}:/usr/local/cuda-5.0/bin
打开终端窗口并键入export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda-5.0/lib:/usr/local/cuda-5.0/lib64
和echo $PATH
会显示两个变量都已正确设置,但我遇到了运行上述CUDA可执行文件的问题。
然后我在stackoverflow上发现了this,并尝试了sivapal ayyappan nadar提供的建议 - 通过修改echo $LD_LIBRARY_PATH
来设置PATH
和修改/etc/environment
LD_LIBRARY_PATH
(我同时在〜/ .bashrc中注释掉了相应的行)。现在,当我编译并运行我的CUDA样本时,它们可以工作!
所以,现在我的问题是:这里发生了什么?为什么在/etc/ld.so.conf.d/cuda50.conf
中设置LD_LIBRARY_PATH时正确链接libcudart库,而在/etc/ld.so.conf.d/cuda50.conf
中设置时却没有正确链接?那个人做了什么,另一个没有?或者,这不是我问题的真正根源吗?
在回复时,请记住我提出问题的动机。我想1)了解Linux系统的复杂性,2)为可能遇到相同问题的其他人发布可能的解决方案,即使遵循了其他可用的优秀指令。非常感谢。
答案 0 :(得分:3)
这是一个有趣的话题,我会尝试解释。因此,在此示例中,我安装了一个小型库jansson进行测试。我将继续将其配置为安装在非标准目录中:
./configure --prefix=/home/ubuntu/mystuff
现在执行make install
此警告后出现:
Libraries have been installed in:
/home/ubuntu/mystuff/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,--rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
好的,我会继续尝试使用其中一个测试套件程序链接它:
$ gcc test_dump.c -ljansson
test_dump.c:8:21: fatal error: jansson.h: No such file or directory
为了让C知道它可以使用什么,它首先需要了解包含文件。幸运的是,这只需要在编译时发生。我们使用-I
传入include目录,以便gcc
知道在哪里找到包含文件:
$ gcc test_dump.c -I/home/ubuntu/mystuff/include -ljansson
/usr/bin/ld: cannot find -ljansson
好的,现在回到链接问题。所以,在链接时尝试LD_LIBRARY_PATH
:
$ LD_LIBRARY_PATH="/home/ubuntu/mystuff/lib" gcc test_dump.c -I/home/ubuntu/mystuff/include -ljansson
/usr/bin/ld: cannot find -ljansson
这不起作用,其背后的原因是gcc正在寻找不同的目录,如运行所示:
gcc -print-search-dirs
告诉gcc使用我们想要的目录,使用-L
:
$ gcc test_dump.c -I/home/ubuntu/mystuff/include -L/home/ubuntu/mystuff/lib -ljansson
$
现在我们可以使用名为ldd
的程序来查看它链接的内容:
$ ldd a.out
linux-vdso.so.1 => (0x00007fc4c872d000)
libjansson.so.4 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc4c8366000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc4c872e000)
你会发现它对我们想要的图书馆说“找不到”。现在试着解决这个问题:
$ LD_RUN_PATH="/home/ubuntu/mystuff/lib" gcc test_dump.c -I/home/ubuntu/mystuff/include -L/home/ubuntu/mystuff/lib -ljansson
这是一种方式,使用LD_RUN_PATH
。它不是仅链接到库,而是链接到库的完整路径。再次运行ldd
会显示:
$ ldd a.out
linux-vdso.so.1 => (0x00007fff481d7000)
libjansson.so.4 => /home/ubuntu/mystuff/lib/libjansson.so.4 (0x00007fe86b0dd000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe86ad18000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe86b2eb000)
现在,当我们在没有LD_RUN_PATH
的情况下尝试此操作时,我们得到了这个:
$ ./a.out
./a.out: error while loading shared libraries: libjansson.so.4: cannot open shared object file: No such file or directory
要解决此问题,请使用LD_LIBRARY_PATH
:
$ LD_LIBRARY_PATH="/home/ubuntu/mystuff/lib" ./a.out
$
但是,这有点像黑客并且不满意。大卫巴尔有great writeup on that matter。发生的事情是,有一个动态库加载器ld.so/ld-linux.so
“加载程序所需的共享库,准备程序运行,然后运行它”。如果您查看ld.so
联机帮助页,请说明:
The necessary shared libraries needed by the program are searched for in the following order
o Using the environment variable LD_LIBRARY_PATH (LD_AOUT_LIBRARY_PATH for a.out programs). Except if the executable is a setuid/setgid binary, in which case it is ignored.
o From the cache file /etc/ld.so.cache which contains a compiled list of candidate libraries previously found in the augmented library path. Libraries installed in hardware capabilities
directories (see below) are prefered to other libraries.
o In the default path /lib, and then /usr/lib.
/etc/ld.so.cache
是您希望该路径所在的位置。此缓存由ldconfig
使用/etc/ld.so.conf
生成。如果你在Ubuntu上查看该文件:
include /etc/ld.so.conf.d/*.conf
就是这么说的。默认情况下,/etc/ld.so.conf.d
目录是glib,gcc和/usr/local/lib
的目录,因为它在默认路径之外。要将我们想要的目录添加到缓存中,只需在该目录中添加一个文件:
$ sudo vim /etc/ld.so.conf.d/50-jansson.conf
- add /home/ubuntu/mystuff/lib to the file -
$ sudo ldconfig
这将为装载程序重新生成/etc/ld.so.cache
个文件。您可以通过ldconfig
打印出缓存的目录来确认目录已被选中:
$ ldconfig -p | grep "mystuff"
libjansson.so.4 (libc6,x86-64) => /home/ubuntu/mystuff/lib/libjansson.so.4
libjansson.so (libc6,x86-64) => /home/ubuntu/mystuff/lib/libjansson.so
现在,如果我们尝试再次运行ldd
:
$ ldd a.out
linux-vdso.so.1 => (0x00007fff1e510000)
libjansson.so.4 => /home/ubuntu/mystuff/lib/libjansson.so.4 (0x00007f529da67000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f529d6a8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f529dc7b000)
最后运行程序:
$ ./a.out
$
一切正常!这是关于当你进行链接时后端发生的事情。有关详细信息,建议您查看man ld.so
和man ldconfig
。如果您需要任何澄清,请随时询问。