My project consists of five CUDA files: main.cu jacobian_kernel.cu hermite_kernel.cu cuSolver_LU.cpp Utilities.cu
, the last of which is adapted from this GitHub repo, together with its Utilities.h
header file; the three headers are args.h linear_solver.h Utilities.h
.
nvcc compiles them succesfully, but while building the trbdf2
executable it yells at me multiple definitions errors like:
nvcc -Xcompiler -fopenmp -o obj/trbdf2 obj/jacobian_kernel.o obj/hermite_kernel.o obj/utils.o obj/cusolver_lu.o obj/main.o -I/usr/local/cuda-8.0/targets/x86_64-linux/include -I../include -I/usr/local/cuda-8.0/samples/common/inc/ -L/usr/local/cuda-8.0/targets/x86_64-linux/lib -lgomp -lcublas -lcudart -lcusolver -lcusparse
obj/hermite_kernel.o: In function `vec_norminf(int, double const*)':
tmpxft_00006336_00000000-4_hermite_kernel.cudafe1.cpp:(.text+0xba1): multiple definition of `vec_norminf(int, double const*)'
obj/jacobian_kernel.o:tmpxft_00006312_00000000-4_jacobian_kernel.cudafe1.cpp:(.text+0xba1): first defined here
obj/hermite_kernel.o: In function `mat_norminf(int, int, double const*, int)':
tmpxft_00006336_00000000-4_hermite_kernel.cudafe1.cpp:(.text+0xc20): multiple definition of `mat_norminf(int, int, double const*, int)'
obj/jacobian_kernel.o:tmpxft_00006312_00000000-4_jacobian_kernel.cudafe1.cpp:(.text+0xc20): first defined here
...
obj/main.o: In function `second()':
tmpxft_00006385_00000000-4_main.cudafe1.cpp:(.text+0xf32): multiple definition of `second()'
obj/jacobian_kernel.o:tmpxft_00006312_00000000-4_jacobian_kernel.cudafe1.cpp:(.text+0xf32): first defined here
collect2: error: ld returned 1 exit status
Makefile:17: recipe for target 'obj/trbdf2' failed
make: *** [obj/trbdf2] Error 1
Now, I'm quite sure that I'm including multiple times the header helper_cusolver.h
which is provided with the CUDA Toolkit and which defines the functions vec_norminf
, mat_norminf
, and the like. I couldn't guess how to rewrite my headers, which begin as follows:
args.h:
#if !defined(ARGS_H_)
#define ARGS_H_
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include "Utilities.h"
...
#endif
linear_solver.h:
#ifndef LINEAR_SOLVER_H_
#define LINEAR_SOLVER_H_
#include <cublas_v2.h>
#include <cusparse_v2.h>
#include <cusolverDn.h>
#include <helper_cusolver.h>
...
#endif
Utilities.h:
#ifndef UTILITIES_CUH
#define UTILITIES_CUH
#include "linear_solver.h"
...
#endif
Moreover, the dependencies are:
jacobian_kernel.cu, hermite_kernel.cu -> args.h
cuSolver_LU.cpp -> args.h, linear_solver.h, Utilities.h
main.cu -> args.h, linear_solver.h, Utilities.h
Utilities.cu -> linear_solver.cu
In addition, the Utilities.cu
initial directives are a bit different from those at the beginning of the other cuda files, but it is a recent addition to my project, and I got the same error before adding it; anyway, here it is:
#include "cuda_runtime.h"
#include <cuda.h>
#if defined(__CUDACC__) && (CUDA_VERSION >= 7000)
#include <cusolverDn.h>
#endif
#include <cublas_v2.h>
#include "Utilities.h"
Long story short, the issue appears to be that the helper_cusolver.h
header is being included more than once, though I've even put some header guard within the linear_solver.h
header's first lines; I've tried the #pragma once
directive, which is supported by nvcc
, and I even checked the guard on the helper_cusolver
.
I'm a beginner in C/C++ and I really don't know how to follow from here. I tried to uncomment most of the (apparently multiple) #include
directives, once at a time but I keep getting the same error.
Let me know if I should include other piece of info.
EDIT In addition, when I wrap the CUDA and/or cuSolver functions with the cudaCheckErrors of the samples or the GitHub's cusolveSafeCall in Utilities.cu, they appear not to be defined:
cuSolver_LU.cpp: In function ‘void linearSolverLU(cusolverDnHandle_t, int, const double*, int, const double*, double*)’:
cuSolver_LU.cpp:28:51: error: cannot convert ‘cudaError_t {aka cudaError}’ to ‘cusolverStatus_t’ for argument ‘1’ to ‘void cusolveSafeCall(cusolverStatus_t)’
cusolveSafeCall(cudaMalloc(&info, sizeof(int)));
though the header Utilities.h is correctly included. I thought this could be useful info in order to find the incorrect directive.
It seems like I need to clean up #include
directives. As pointed out by Robert Crovella I removed helper_cusolver.h
from linear_solver.h
and instead I've put it in cuSolver_LU.cpp
, as it is the only file that needs it during compilation, and probably including it in more files caused multiple definition errors; now cuSolver_LU.cpp
begins like this:
#include "args.h"
#include "linear_solver.h"
#include "Utilities.h"
#include <helper_cusolver.h>
extern "C" void cusolveSafeCall(cusolverStatus_t err);
...
Moreover, by declaring cusolveSafeCall()
I managed as well to solve definition errors on wrapper functions, which I pointed out in the edit note. Thanks!