CUDA 8.0 nvcc致命错误:指定ouputtfile时非链接阶段所需的单个输入文件

时间:2017-07-06 15:26:45

标签: makefile cuda linker nvidia nvcc

我试图在我的CUDA项目中链接目标文件。下面是我的makefile:

CUDA_PATH := /usr/local/cuda
NVCC := $(CUDA_PATH)/bin/nvcc

NVCCFLAGS := -arch=sm_37 --device-c -std=c++11 -cudart=shared -rdc=true

LIBS := -lcutil -lcudpp -lcuda -lcudart -lcurand

LIBPATH := $(CUDA_PATH)/lib64
SOLIBS := $(LIBPATH)/*.so

OBJS := main.o mtx.o mpamp_for_loop_funs.o cuBLAS_funs.o sparsify_threshold.o

########################################################################

# link
all: $(OBJs)
    $(NVCC) $(NVCCFLAGS) $(OBJS) $(SOLIBS) $(LIBS) -o mpamp
#--output-file mpamp.o

########################################################################

# compile individually
main.o: main.cu header.h
    $(NVCC) $(NVCCFLAGS) -c main.cu

mtx.o: mtx.cu header.h
    $(NVCC) $(NVCCFLAGS) -c mtx.cu

mpamp_for_loop_funs.o: mpamp_for_loop_funs.cu header.h
    $(NVCC) $(NVCCFLAGS) -c mpamp_for_loop_funs.cu

cuBLAS_funs.o: cuBLAS_funs.cu header.h
    $(NVCC) $(NVCCFLAGS) -c cuBLAS_funs.cu

sparsify_threshold.o: sparsify_threshold.cu header.h
    $(NVCC) $(NVCCFLAGS) -c sparsify_threshold.cu

########################################################################

run: build
    $(EXEC) ./mpamp

clean:
    \rm *.o *~ mpamp

########################################################################

我尝试删除$(SOLIBS),它会返回相同的错误:

ece$ make all
/usr/local/cuda/bin/nvcc -arch=sm_37 --device-c -std=c++11 -cudart=shared -rdc=true main.o mtx.o mpamp_for_loop_funs.o cuBLAS_funs.o sparsify_threshold.o /usr/local/cuda/lib64/*.so -lcutil -lcudpp -lcuda -lcudart -lcurand -o mpamp
nvcc fatal   : A single input file is required for a non-link phase when an outputfile is specified
make: *** [all] Error 1

此外,当我删除-o mpamp时,make all命令有效,但不生成输出文件然后执行。

有没有人有任何关于通过此错误的提示?

我最近从Windows中的Visual Studio迁移到Linux机器。 VS自动编译和链接' (我添加了斜线和换行符):

nvcc -dlink -o x64\Debug\MPAMP.device-link.obj -Xcompiler "/EHsc /W3 /nologo /Od /Zi /RTC1 /MTd " \
-L"\lib\x64" cublas.lib cublas_device.lib cudadevrt.lib curand.lib 
cudart.lib cudart_static.lib \
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \
odbc32.lib odbccp32.lib  -gencode=arch=compute_35,code=sm_35 -G \
--machine 64 x64\Debug\cuBLAS_funs.cu.obj x64\Debug\inner_loop.cu.obj x64\Debug\main.cu.obj \
x64\Debug\mpamp_for_loop_funs.cu.obj x64\Debug\mtx.cu.obj x64\Debug\sparsify_threshold.cu.obj

更新:根据以下答案,相关的makefile行现在是:

NVCCFLAGS := -arch=sm_37 --device-c -std=c++11

NVCCLFLAGS := -arch=sm_37 -std=c++11 -cudart=shared -rdc=true

LDFLAGS := -I$(CUDA_PATH)/include -L$(CUDAPATH)/lib64

LIBPATH := $(CUDA_PATH)/lib64
SOLIBS := $(LIBPATH)/libcublas.so $(LIBPATH)/libcurand.so $(LIBPATH)/libcudart.so

OBJS := main.o mtx.o mpamp_for_loop_funs.o cuBLAS_funs.o sparsify_threshold.o

LIBS := -lcutil -lcudpp -lcuda -lcudart -lcurand -lcublas

########################################################################

# link
all: $(OBJs)
    $(NVCC) $(NVCCLFLAGS) $(LDFLAGS) -o mpamp $(OBJS) $(SOLIBS) $(LIBS)

但是,我收到以下错误:

ece$ make all
/usr/local/cuda/bin/nvcc -arch=sm_37 -std=c++11 -cudart=shared -rdc=true -I/usr/local/cuda/include -L/lib64 -o mpamp main.o mtx.o mpamp_for_loop_funs.o cuBLAS_funs.o sparsify_threshold.o /usr/local/cuda/lib64/libcublas.so /usr/local/cuda/lib64/libcurand.so /usr/local/cuda/lib64/libcudart.so -lcutil -lcudpp -lcuda -lcudart -lcurand -lcublas
nvlink error   : Undefined reference to 'cublasDgemm_v2' in 'cuBLAS_funs.o'
make: *** [all] Error 255

我已尝试按照this question重新排列链接语句中的标记,但无济于事。

解决了!感谢您的帮助。这是最后的改变:

LIBPATH := $(CUDA_PATH)/lib64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64
SOLIBS := $(LIBPATH)/libcublas.so $(LIBPATH)/libcurand.so

OBJS := main.o mtx.o mpamp_for_loop_funs.o cuBLAS_funs.o sparsify_threshold.o

LIBS := -lcuda -lcurand -lcublas -lcublas_device

1 个答案:

答案 0 :(得分:2)

这里的根本问题是你将编译和链接开关混杂在一起,尝试使用同一组开关进行编译和链接。

与此相关,您的代码似乎使用或依赖于CUDA separable compilation with device linking,并且在这种情况下不可能对编译和链接使用相同的开关集,除非编译和链接阶段是所有组合,他们不在你的例子中。

仔细研究您正在使用的开关的nvcc manual将确定问题。

当您指定--device-c时,您向编译器(nvcc)指示这只是一个编译阶段/步骤(就像指定-c一样将用于gnu编译器工具链)。因此,为任何类型的链接过程指定该开关是不明智的。

具有最小更改次数的解决方案是从链接阶段命令中删除该解决方案。一种可能的方法是创建一个额外的Makefile变量:

NVCCLFLAGS := -arch=sm_37 -std=c++11 -cudart=shared -rdc=true

并修改您的链接阶段命令以使用:

# link
all: $(OBJs)
    $(NVCC) $(NVCCLFLAGS) $(OBJS) $(SOLIBS) $(LIBS) -o mpamp