Search code examples
c++linuxtensorflowopenmplinker-errors

tensorflow_cc results in Undefined reference to `omp_in_parallel@VERSION'


I installed tensorflow-opt-cuda on Arch linux, but trying to link as

g++ -fopenmp "CMakeFiles/intro-hello-world.dir/hello-world.cc.o" -o intro-hello-world /usr/lib/libtensorflow_cc.so /usr/lib/libtensorflow_framework.so /usr/lib/libgomp.so -lpthread

results in:

/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `omp_in_parallel@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `GOMP_barrier@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `omp_get_max_threads@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_framework.so: undefined reference to `kmp_set_blocktime@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `omp_get_num_threads@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `omp_get_thread_num@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_cc.so: undefined reference to `GOMP_parallel@VERSION'
/usr/bin/ld: /usr/lib/libtensorflow_framework.so: undefined reference to `omp_set_num_threads@VERSION'
collect2: error: ld returned 1 exit status

while I do have (for example):

readelf --symbols --wide /usr/lib/libgomp.so | grep 'omp_get_num_threads'
    79: 0000000000017110    29 FUNC    GLOBAL DEFAULT   15 omp_get_num_threads@@OMP_1.0
   202: 00000000000241b0     9 FUNC    GLOBAL DEFAULT   15 omp_get_num_threads_@@OMP_1.0
   329: 0000000000017110    29 FUNC    LOCAL  DEFAULT   15 gomp_ialias_omp_get_num_threads
   734: 00000000000241b0     9 FUNC    GLOBAL DEFAULT   15 omp_get_num_threads_
   851: 0000000000017110    29 FUNC    GLOBAL DEFAULT   15 omp_get_num_threads

Note that

readelf --symbols --wide /usr/lib/libtensorflow_cc.so | grep 'omp_get_num_threads'
  1122: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND omp_get_num_threads@VERSION (42)

What is going on? Should this link, or not? And if not then who is to blame?


Solution

  • Should this link, or not?

    The linker errors are valid. When @VERSION is given, the symbol must have a literal "@VERSION" appended; it does not, so the symbols are not found.

    What is going on?

    You are linking against the wrong library. The listed symbols are defined by libiomp5.so, not libomp.so. Install the packages intel-oneapi-openmp and intel-oneapi-compiler-shared-runtime-libs to get it.

    And if not then who is to blame?

    Arch is to blame. First of all the dependency on intel-oneapi-openmp and intel-oneapi-compiler-shared-runtime-libs are missing.

    Note, the latter is only necessary for the symbol link /opt/intel/oneapi/compiler/latest (that in turn is pointed to by the symbolic link /usr/share/pkgconfig/openmp.pc which is owned by intel-oneapi-openmp. So that is another bug).

    Worse, they do

    find "${pkgdir}"/usr/lib -type f -exec patchelf --replace-needed libiomp5.so libomp.so '{}' \; -print
    

    at the end of _package() in the PKGBUILD of tensorflow, see the repository https://gitlab.archlinux.org/archlinux/packaging/packages/tensorflow.git

    This causes the shared libraries to want to link to libomp.so, which is wrong.