【发布时间】:2017-04-12 19:37:16
【问题描述】:
我的项目由五个CUDA文件组成:main.cu jacobian_kernel.cu hermite_kernel.cu cuSolver_LU.cpp Utilities.cu,最后一个改编自this GitHub repo,连同它的Utilities.h头文件;这三个标题是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
现在,我很确定我多次包含标题 helper_cusolver.h,它是 CUDA 工具包提供的,它定义了函数 vec_norminf、mat_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 指令,但我一直收到相同的错误。
如果我应该包含其他信息,请告诉我。
编辑此外,当我在 Utilities.cu 中使用示例的 cudaCheckErrors 或 GitHub 的 cusolveSafeCall 包装 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)));
虽然标题 Utilities.h 已正确包含。我认为这可能是有用的信息,以便找到不正确的指令。
【问题讨论】:
-
include guards 和
#pragma once当你在 2 个不同的编译单元中包含相同的东西时将无济于事。你在哪些模块中真正需要来自helper_cusolver.h的东西? -
cuSolver_LU是唯一需要它的人;顺便说一句,它是改编自 CUDA 示例的 cuSolver 的代码 -
所以重新排列你的头文件,以便
helper_cusolver.h只包含在该模块中。这可以像从任何和所有头文件中删除helper_cusolver.h一样简单,只需将其包含语句:#include <helper_cusolver.h>直接放在cuSolver_LU.cpp文件中。 -
成功了!就这么简单。不过,我认为标题包含正确。仍然无法让“安全电话”工作,也许我会给他们一个新的答案。
-
请添加一个简短的答案来解释您的解决方案。
标签: c++ cuda linker nvcc cusolver