It seems that recent changes to Thrust (part of CUDA Toolkit) were made to tag the host_vector class name with the compile time CUDA architecture. This creates an issue (undefined reference) when linking shared objects compiled with nvcc or not (.cu vs .cpp files) that use Thrust objects, even host only ones like host_vector. I am not sure why they would do this.
We have a large application that uses host_vector in many .cpp files, anyone know a good way around this? I don't think compiling everything with nvcc is an option, some of the files need moc (ie Qt).
To reproduce on Ubuntu 20.04.6 LTS with Cuda 12.6:
Main.cpp
#include <cuda_runtime.h>
#include <thrust/host_vector.h>
bool cudaFunc(thrust::host_vector<int> &vec);
int main()
{
thrust::host_vector<int> vec;
cudaFunc(vec);
}
cudaFunc.cu
#include <cuda_runtime.h>
#include <thrust/host_vector.h>
bool cudaFunc(thrust::host_vector<int> &vec)
{
return true;
}
Compile with:
/usr/local/cuda/bin/nvcc -c cudaFunc.cu
g++ -I /usr/local/cuda/include -L /usr/local/cuda/targets/x86_64-linux/lib main.cpp cudaFunc.o -lcudart -ldl
will produce the error:
/usr/bin/ld: /tmp/cc5fFAJC.o: in function \`main':
main.cpp:(.text+0x30): undefined reference to \`cudaFunc(thrust::THRUST_200500___CUDA_ARCH_LIST___NS::host_vector\<int, std::allocator\<int\> \>&)'
collect2: error: ld returned 1 exit status
This will link fine on Ubuntu 20 with Cuda 12.3.
@paleonix Thank you for your reply. I downloaded cccl-2.6.1 and compiled with:
/usr/local/cuda/bin/nvcc -c -Icccl-2.6.1/thrust -Icccl-2.6.1/libcudacxx/include -Icccl-2.6.1/cub cudaFunc.cu
g++ -Icccl-2.6.1/thrust -Icccl-2.6.1/libcudacxx/include -Icccl-2.6.1/cub -I/usr/local/cuda/include main.cpp cudaFunc.o -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -ldl
The error persists:
/usr/bin/ld: /tmp/cc966x8Y.o: in function `main':
main.cpp:(.text+0x30): undefined reference to `cudaFunc(thrust::THRUST_200601___CUDA_ARCH_LIST___NS::host_vector<int, std::allocator<int> >&)'
collect2: error: ld returned 1 exit status
Workaround:
I defined a new namespace for thrust objects, in my case mgxthrust, and replaced all the thrust::host_vector and other thrust names referenced in the application with mgxthrust::host_vector.
Then in a header file:
namespace mgx_thrust { namespace thrust {} }
#define THRUST_WRAPPED_NAMESPACE mgx_thrust
namespace mgxthrust = mgx_thrust::thrust;
Note this needs to be called before other thrust headers.
main). I would rather use a release (they are tagged in Git).