Libtorch works with g++, but fails with Intel compiler

username: Arsen_Iskhakov
cooked: <p>I want to use a neural network developed in Python (PyTorch) in a Fortran program. My OS is Ubuntu 18.04.</p>
<p>What I am doing:</p>
<ol>
<li>save it as torchscript: TurbNN.pt</li>
<li>call it from c++ program: call_ts.cpp, call_ts.h</li>
<li>call c++ program from Fortran program (using bind©): main.f90</li>
</ol>
<p>I successfully compiled the codes using CMake (3.19.4) and g++ (7.5.0). However, I cannot compile them using Intel compilers (HPCKit 2021.1.0.2684):</p>
<pre><code class="lang-auto"># downloaded torchlib
export Torch_DIR=/home/aiskhak/nn/fortran_calls_torchscript3/build/libtorch/share/cmake/Torch/

# set environment for Intel compilers
. /opt/intel/oneapi/setvars.sh

# cmake
cmake \
-DCMAKE_CXX_COMPILER=icpc \
-DCMAKE_Fortran_COMPILER=ifort ..

# make
make
</code></pre>
<p>After “cmake” everything looks fine (just like for g++):</p>
<pre><code class="lang-auto">-- The CXX compiler identification is Intel 20.2.1.20201112
-- The Fortran compiler identification is Intel 20.2.1.20201112
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/intel/oneapi/compiler/2021.1.1/linux/bin/intel64/icpc - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Check for working Fortran compiler: /opt/intel/oneapi/compiler/2021.1.1/linux/bin/intel64/ifort - skipped
-- Checking whether /opt/intel/oneapi/compiler/2021.1.1/linux/bin/intel64/ifort supports Fortran 90
-- Checking whether /opt/intel/oneapi/compiler/2021.1.1/linux/bin/intel64/ifort supports Fortran 90 - yes
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Found Torch: /home/aiskhak/nn/fortran_calls_torchscript3/build/libtorch/lib/libtorch.so  
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/aiskhak/nn/fortran_calls_torchscript3/build
</code></pre>
<p>However, after “make” I am getting:</p>
<pre><code class="lang-auto">Scanning dependencies of target call_ts_cpp
[ 25%] Building CXX object CMakeFiles/call_ts_cpp.dir/src/call_ts.cpp.o
[ 50%] Linking CXX shared library lib/libcall_ts_cpp.so
[ 50%] Built target call_ts_cpp
Scanning dependencies of target fortran_calls_ts.x
[ 75%] Building Fortran object CMakeFiles/fortran_calls_ts.x.dir/src/main.f90.o
[100%] Linking Fortran executable bin/fortran_calls_ts.x
lib/libcall_ts_cpp.so: undefined reference to `c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;)'
lib/libcall_ts_cpp.so: undefined reference to `torch::jit::load(std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;, c10::optional&lt;c10::Device&gt;, std::unordered_map&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;, std::hash&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, std::equal_to&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, std::allocator&lt;std::pair&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; &gt; &gt;&amp;)'
lib/libcall_ts_cpp.so: undefined reference to `c10::DeviceTypeName[abi:cxx11](c10::DeviceType, bool)'
lib/libcall_ts_cpp.so: undefined reference to `torch::jit::Object::find_method(std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;) const'
lib/libcall_ts_cpp.so: undefined reference to `torch::jit::Method::operator()(std::vector&lt;c10::IValue, std::allocator&lt;c10::IValue&gt; &gt;, std::unordered_map&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;, c10::IValue, std::hash&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, std::equal_to&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, std::allocator&lt;std::pair&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const, c10::IValue&gt; &gt; &gt; const&amp;)'
CMakeFiles/fortran_calls_ts.x.dir/build.make:106: recipe for target 'bin/fortran_calls_ts.x' failed
make[2]: *** [bin/fortran_calls_ts.x] Error 1
CMakeFiles/Makefile2:123: recipe for target 'CMakeFiles/fortran_calls_ts.x.dir/all' failed
make[1]: *** [CMakeFiles/fortran_calls_ts.x.dir/all] Error 2
Makefile:148: recipe for target 'all' failed
make: *** [all] Error 2
</code></pre>
<p>What I am supposed to do with? I fixed similar problem when I had old g++, but my Intel compiler is new.</p>
<p>Below are my codes:</p>
<p>call_ts.cpp</p>
<pre><code class="lang-auto">#include "call_ts.h"
#include &lt;torch/script.h&gt;
#include &lt;iostream&gt;
#include &lt;memory&gt;

// c++ function invariant_nn
//
// takes inputs, reads a neural network TurbNN.pt, do a forward pass
// and returns outputs
//
// inputs: 5 tensor invariants I[0:4] (float)
// outputs: 10 tensor basis coefficients G[0:9] (float)

void invariant_nn(float I[], float G[])
{
    // deserialize scriptmodule from a .pt file
    torch::jit::script::Module module;
    const char *arg;
    arg = "../src/TurbNN.pt";
    module = torch::jit::load(arg);

    // create inputs
    std::vector&lt;torch::jit::IValue&gt; inputs;
    float data[] = {I[0], I[1], I[2], I[3], I[4]};
    inputs.push_back(torch::from_blob(data, {1, 5}));
    //std::cout &lt;&lt; "inputs\n" &lt;&lt; inputs;
    //std::cout &lt;&lt; "\n";

    // do forward pass and turn its output into a tensor
    at::Tensor outputs = module.forward(inputs).toTensor();
    //std::cout &lt;&lt; "outputs\n" &lt;&lt; outputs;
    //std::cout &lt;&lt; "\n";

    // return values
    for (int k = 0; k &lt; 10; k++) {
        G[k] = outputs[0][k].item().to&lt;float&gt;();
        //std::cout &lt;&lt; "G\n" &lt;&lt; G[k];
    }

    return;
}
</code></pre>
<p>call_ts.h</p>
<pre><code class="lang-auto">#pragma once

/* export macros for library generated by CMake */
#ifndef CALL_TS_API
#include "call_ts_export.h"
#define CALL_TS_API CALL_TS_EXPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

CALL_TS_API
void invariant_nn(float I[], float G[]);

#ifdef __cplusplus
}
#endif
</code></pre>
<p>main. f90</p>
<pre><code class="lang-auto">! fortran program main
!
! calls c++ function invariant_nn, which calls a torchscript with
! a neural network
!

program main

    ! define interface to interact with c++
    use, intrinsic :: iso_c_binding, only: c_float
    implicit none
    interface invariant_nn
        subroutine invariant_nn(I, G) bind (c)
            import :: c_float
            real(c_float) :: I(5)
            real(c_float) :: G(10)
        end subroutine
    end interface

    ! fortran program
    real(4) I(5), G(10)

    ! invariants
    I(1) = 1.01
    I(2) = 1.01
    I(3) = 1.01
    I(4) = 1.01
    I(5) = 1.01
    print *, "Tensor invariants ", I

    ! tensor basis coefficients
    call invariant_nn(I, G)    
    print *, "Tensor basis coefficients ", G

end program main
</code></pre>
<p>CMakeLists.txt</p>
<pre><code class="lang-auto"># stop configuration if cmake version is below 3.0
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)

# project name and enabled languages
project(fortran_calls_ts CXX Fortran)

# find libtorch
find_package(Torch REQUIRED)

# if CMAKE_BUILD_TYPE undefined, set it to Release
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()

# compiler flags for release mode
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
set(CMAKE_Fortran_FLAGS_RELEASE "-O3")

# set default build paths
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)

# generated export header will be placed here
include_directories(${PROJECT_BINARY_DIR})

# c library
add_library(call_ts_cpp SHARED src/call_ts.cpp)

# fortran executable
add_executable(fortran_calls_ts.x src/main.f90)

# linked against c library
target_link_libraries(fortran_calls_ts.x call_ts_cpp)
target_link_libraries(call_ts_cpp "${TORCH_LIBRARIES}")

# we let cmake generate the export header
include(GenerateExportHeader)
generate_export_header(call_ts_cpp BASE_NAME call_ts)

install(TARGETS call_ts_cpp LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)

install(FILES src/call_ts.h ${PROJECT_BINARY_DIR}/call_ts_export.h DESTINATION include)

set_property(TARGET fortran_calls_ts.x PROPERTY CXX_STANDARD 14)
</code></pre>

username: Arsen_Iskhakov
cooked: <p>The solution is here: <a href="https://stackoverflow.com/questions/66192285/libtorch-works-with-g-but-fails-with-intel-compiler/66192326?noredirect=1#comment117024722_66192326" class="inline-onebox" rel="noopener nofollow ugc">c++ - Libtorch works with g++, but fails with Intel compiler - Stack Overflow</a></p>