"undefined symbol: cuInit" and related problems on Linux

Hi!

I just ran into a similar error as some others here with JCuda under Linux (Ubuntu 12.04 32bit):

Cuda toolkit and Cuda SDK are properly installed in the correct version (and the Cuda SDK examples work well), and JCublas does work (e.g., JCublasSample.java), BUT whenever I invoke via JCuda a cuda driver API function, e.g., cuInit() within KernelLauncherSample.java, I get the following error:


/usr/lib/jvm/java-6-openjdk-i386/bin/java: symbol lookup error: (...)/lib/jcuda-0.4.2/libJCudaDriver-linux-x86.so: undefined symbol: cuInit

I.e., all the JCuda’s jars and directly accessed native libraries are found, but the internal call to libcuda.so cannot be resolved at runtime. The strange about it: libcublas.so does exist (uniquely on my system), and can be found at compile-time when compiling on my own, and is on the LD_LIBRARY_PATH, and in fact contains cuInit - but for some reason it cannot be accessed via JNI. It seems as if it is not loaded before accessing it.

I tried for >8 hours to find a solution, incl. compiling JCuda on my own, creating some own shared libraries for accessing libcuda.so, re-installing different graphic driver versions, playing around with LD_LIBRARY_PATH, tracing and inspecting with ldd, ltrace, nm, objdump and so on… all without luck. In fact, I even registered to this forums because I wanted to give up. Then, more by luck than intended, I found a corresponding hint which gave rise to the following simple yet effective solution:

Before starting the JVM, set the LD_PRELOAD environment variable to point to your libcuda.so.

For example, if you start your application from a terminal, you might do so by calling

export LD_PRELOAD=/usr/lib/nvidia-common-update/libcuda.so

once before starting your application for the first time from that terminal (of course libcuda.so might stay somehwere else on your system, e.g., /usr/lib/nvidia-common/libcuda.so or /usr/lib/libcuda.so, …).

Or if you start your application from within eclipse, then add this environment variable to the RunConfiguration (Run -> Run Configurations… -> [Your Main Class] -> Environment -> New…).

The ‘trick’ is: by forcing libcuda.so to be pre-loaded, it is ensured that its symbols can be found from all later loaded libraries.

In fact, I do not understand the exact reason for why this solution works, but as far as I understood it might have to do with some pthread issues within Cuda.

However, it works for me and the LD_PRELOAD trick hopefully (and quite likely) also works for similar problems. In fact, now I can even use the pre-compiled JCuda binaries and the official newest nvidia-driver from the ubuntu repositories, although it is more recent than required for this Cuda toolkit.

If some others can confirm this as a solution to their problem, then it might be a good idea to add this as a hint to the official README.

btw @authors: thank you very much for your great work on JCuda!!

Hello

Thank you very much for sharing these insights! This problem was reported once or twice, and I did not have an idea waht might be wrong there.

The way that the CUDA functions are resolved at the moment is not perfect. As I recently pointed out: The necessity to have a strict 1:1 correspondence between the CUDA version and the JCuda version is undesirable. This is due to the CUDA functions being called directly via JNI. This should be solved in a more flexible way, by using function pointers to the CUDA functions, which then are resolved at runtime. I have just introduced this mechanism for the next version of JOCL, but still verifying it. For JCuda, this would imply a considerable effort, but I hope that I’ll be able to do this in one of the next version.

Thanks again for your support! I’m not a Linux expert, and have no possibility to really run tests on Linux at all, so am grateful for any hints that may help to solve Linux-related problems!

bye
Marco