2

由于此处无法解释的原因,我需要在“C”中创建一个可在 Python 中调用的共享库(称为 libA)。这个共享库需要调用另一个自定义共享库(我们将其命名为 libCuda)。此外,libA 还调用了许多其他外部共享库,例如 MySQL 等。

在包含 libCuda 之前,在 Python 中调用的所有 C 函数都可以正常工作,MySQL 子调用也可以正常工作,等等。但是,一旦将 libCuda 添加到 libA,Python 就会抱怨:

caughtError c process - [directory]/libA.so: undefined symbol: cudaFunction1

libCuda,正如您可能已经猜到的那样,是使用 nvcc 编译的 nVidia Cuda 代码并设置为可 C 链接(即在函数原型中导出“C”)我已经使用独立测试台测试了这个共享库(libCuda)(编写在 C) 中,一切都按预期工作。这是用于编译 Cuda 库的指令:

nvcc -arch=sm_30 -shared -o libCuda.so *.cu -Xcompiler -fPIC

如果我使用:

$ ldd libA

我没有看到任何信息表明 libA 需要加载 libCuda(或 MySQL)

用于编译 libA 的命令如下(libCuda 位于本地目录中):

gcc *.c -c -L. -lCuda -lmysqlclient [many other shared libraries] -fPIC
gcc -shared -Wl,-soname,libA.so -lCuda -lmysqlclient [many other shared libraries] -o libA.so *.o

我尝试将两个库文件都放在 /usr/lib 中并显式导出 LD_LIBRARY_PATH。没运气。任何帮助将不胜感激!

4

2 回答 2

0

当您链接 libA.so 时,您使用的共享库应指定为依赖项 ( -L$somedirectory -lCuda)。然后依赖项变得可见ldd ./libA.so,正如它们应该的那样,然后LD_LIBRARY_PATH会有所帮助。

共享库中允许使用未定义的符号,因此在构建时提供足够的依赖关系取决于您。如果 没有发生同样的事情libmysqlclient,那可能是因为libmysqlclient由于某些其他依赖项而被加载(或动态地使用RTLD_GLOBAL之前 libA.so)。那么它可能不是你想要的,即使问题不是立即可见的。

附言

  1. 您可能想阅读有关sonames的内容(从man ld? 开始),以确定您是否真的要链接反对libCuda.so(而不是libCuda.so.N我希望的反对)。
  2. 对于快速而肮脏的解决方法(如果你还在这个地方和我在一起:),请尝试LD_PRELOAD=/full/path/to/libCuda.so your-program.
于 2013-01-09T21:07:03.547 回答
0

好的,所以没有赢,但我能够改变规则。

以此为参考,我首先用 nvcc 编译了 CUDA 代码,从而创建了几个对象 ( *.o ) 文件。然后在创建库 libA 时将这些目标文件添加到由 gcc 链接的目标文件列表中。此外,以下链接器参数已添加到 gcc 命令“-L/usr/local/cuda/lib64 -lcudart”中(我使用的是 x64 机器)。

指出您必须将任何库依赖项放在需要它的目标文件之后,这一点非常重要。如果你不这样做,gcc 会抱怨未定义的引用。一个好的经验法则是将所有库放在 gcc 行的末尾。详情见下文。

简而言之,这是有效的:

CUDA:

nvcc -arch=sm_30 -c *.cu -Xcompiler -fPIC

C:

gcc *.c -c -fPIC -L/usr/local/cuda/lib64 -lcudart -lmysqlclient [many other shared libraries]
gcc -shared -Wl,-soname,libA.so -o libA.so *.o [cuda_obj_file_dir]/*.o -L/usr/local/cuda/lib64 -lcudart -lmysqlclient [many other shared libraries]

非常感谢 Anton Kovalenko 的建议。不幸的是,我无法解决我的最终目标,但也许这将作为其他人的中间体,就像现在对我一样。

于 2013-01-15T21:27:32.747 回答