cusparse功能的多个定义错误在链接可执行文件中的cuda文件时

Multiple definition errors of cuSparse functions while linking CUDA files in an executable

本文关键字:可执行文件 cuda 文件 链接 错误 功能 定义 cusparse      更新时间:2023-10-16

我的项目由五个cuda文件组成: main.cu jacobian_kernel.cu hermite_kernel.cu cuSolver_LU.cpp Utilities.cu,其中最后一个是根据此github repo和其 Utilities.h header文件进行的;这三个标题是args.h linear_solver.h Utilities.h

NVCC成功地编译了它们,但是在构建trbdf2时,它会对我大喊大叫,例如:

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

现在,我很确定我多次将带有CUDA工具包提供的标题helper_cusolver.h包括在内,并定义了功能vec_norminfmat_norminf等。我无法猜测如何重写我的标题,这是以下内容:

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

实用程序。H:

#ifndef UTILITIES_CUH
#define UTILITIES_CUH
#include "linear_solver.h"
...
#endif

此外,依赖项是:

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

此外,Utilities.cu初始指令与其他CUDA文件开头的指令有所不同,但这是我项目的最新添加,并且在添加之前,我遇到了相同的错误。无论如何,这里是:

#include "cuda_runtime.h"
#include <cuda.h>
#if defined(__CUDACC__) && (CUDA_VERSION >= 7000)
#include <cusolverDn.h>
#endif
#include <cublas_v2.h>
#include "Utilities.h"

长话短说,问题似乎是helper_cusolver.h标头不止一次,尽管我什至在linear_solver.h标头的第一行中放了一些标头后卫。我已经尝试了#pragma once指令,该指令由nvcc支持,甚至在helper_cusolver上检查了后卫。

我是C/C 的初学者,我真的不知道如何从这里跟随。我试图一次一次(显然是多个)#include指令,但我一次一次都会遇到相同的错误。

让我知道我是否应该包括其他信息。

edit 此外,当我用样品的cudaCheckerrors或github的cusolveservecall in Utilities.cu包装cuda和/或cusolver功能时,它们似乎并未定义:

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)));

虽然已正确包含标题实用程序。我认为这可能是有用的信息,以找到错误的指令。

似乎我需要清理#include指令。正如Robert Crovella指出的那样,我从linear_solver.h中删除了helper_cusolver.h,而我将其放入了cuSolver_LU.cpp中,因为它是汇编过程中唯一需要它的文件,并且可能将其包括在更多文件中的情况下,导致了多个定义错误;现在cuSolver_LU.cpp开始这样开始:

#include "args.h"
#include "linear_solver.h"
#include "Utilities.h"
#include <helper_cusolver.h>
extern "C" void cusolveSafeCall(cusolverStatus_t err);
...

此外,通过声明cusolveSafeCall() i也管理了求解包装函数上的定义错误,我在编辑注释中指出。谢谢!

如果需要" helper_cusolver.h"的一个以上的文件,该解决方案将无法工作。请注意,功能在" Helper_cuda.h"中具有此"静态",这就是为什么可以多次包含它而没有问题的原因。

或更好的是,请参见https://codeyarns.com/2010/08/26/c-static-function-in-header-file/

相关文章: