1

我最近按照NVidia站点、本站点和本站点上的说明在 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 的程序 - 第 3 章中的 simple_kernel.cu - 包含在NVidia 出版 的CUDA By Example一书的源代码中(可在此处获得) 。

make1)我在对应目录下运行得到的可执行文件;可执行文件 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变量设置为 include /usr/local/cuda-5.0/bin,并将变量设置为同时LD_LIBRARY_PATH包含/usr/local/cuda-5.0/liband /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指向的链接/usr/local/cuda-5.0/lib/libcudart.so.5.0。但这导致了我的问题......

我通过在 ~/.bashrc 文件中添加行来修改我的 PATH 和 LD_LIBRARY_PATH 变量

export PATH=${PATH}:/usr/local/cuda-5.0/binexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda-5.0/lib:/usr/local/cuda-5.0/lib64

打开一个终端窗口并输入echo $PATHecho $LD_LIBRARY_PATH会显示两个变量都已正确设置,但我在运行上述 CUDA 可执行文件时遇到了问题。

然后我在stackoverflow上找到了这个帖子,并尝试了sivapal ayyappan nadar提供的建议——PATH通过修改/etc/environmentLD_LIBRARY_PATH修改来设置/etc/ld.so.conf.d/cuda50.conf(我同时注释掉了~/.bashrc中的相应行)。现在,当我编译并运行我的 CUDA 示例时,它们就可以工作了!

所以,现在我的问题是:这里发生了什么?为什么在设置 LD_LIBRARY_PATH 时 libcudart 库被正确链接,但在设置/etc/ld.so.conf.d/cuda50.conf时却没有~/.bashrc?一个做什么而另一个不做什么?或者,这不是我问题的真正根源吗?

回复时,请记住我提出问题的动机。我想 1) 了解 Linux 系统的复杂性,以及 2) 为其他可能遇到相同问题的人发布一个可能的解决方案,即使遵循了其他可用的优秀说明。非常感谢。

4

1 回答 1

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因此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
$

然而,这有点像黑客和皱眉。大卫巴尔在这件事上写了一篇很棒的文章。发生的事情是有一个动态库加载器,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.soand man ldconfig。如果您需要任何澄清,请随时询问。

于 2013-03-03T22:05:50.597 回答