为什么CUDA在bashrc中被变量声明搞乱了?

时间:2013-02-02 19:14:52

标签: linux bash cuda

我最近按照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.0export 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/lib64echo $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)为可能遇到相同问题的其他人发布可能的解决方案,即使遵循了其他可用的优秀指令。非常感谢。

1 个答案:

答案 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.soman ldconfig。如果您需要任何澄清,请随时询问。