我的項目由五個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
。當鏈接可執行文件中的CUDA文件時cuSparse函數的多個定義錯誤
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
Utilities.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另外,當我包裹CUDA和/或cuSolver功能與樣品的cudaCheckErrors或GitHub的cusolveSafeCall在Utilities.cu,它們似乎不被定義:
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。我認爲這可能是有用的信息,以找到不正確的指令。
如果在2個不同的編譯單元中包含相同的內容,則包含警衛和'#pragma once'將無濟於事。你真的需要哪些模塊需要'helper_cusolver.h'中的東西? –
'cuSolver_LU'是唯一需要它的人;順便說一句,它是從CUDA樣本cuSolver – Eugenio
改編的代碼,因此重新排列您的頭文件,以便「helper_cusolver.h」只包含在該模塊中。這可以像從任何和所有頭文件中去除'helper_cusolver.h'一樣簡單,並且直接在'cuSolver_LU.cpp'文件中直接放入include語句:'#include'。 –