【问题标题】:CUDA 8.0 nvcc fatal: single input file required for a non-link phase when an ouputtfile is specifiedCUDA 8.0 nvcc 致命:指定输出文件时,非链接阶段需要单个输入文件
【发布时间】:2017-12-10 17:05:03
【问题描述】:

我正在尝试在我的 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

【问题讨论】:

  • 虽然它不是问题的根源,但在您的编译标志 (NVCCFLAGS) 上,--device-c-rdc-true 的使用是多余的。如果您愿意,只需指定 --device-c 就足够了。但是保留-rdc=true 并不会伤害任何东西。同样,-cudart=shared 是一个链接阶段开关,因此它属于您的 NVCCLFLAGS 变量,但在编译时无关紧要,并且可以安全地从您的 NVCCFLAGS 变量中省略以用于编译阶段。

标签: makefile cuda linker nvidia nvcc


【解决方案1】:

这里的根本问题是您将编译和链接开关混为一谈,试图将同一组开关用于编译和链接。

再加上这一点,您的代码似乎使用或依赖于 CUDA separable compilation with device linking,在这种情况下,不可能对编译和链接使用相同的开关集,除非编译和链接阶段全部组合在一起,它们不在您的示例中。

仔细研究您正在使用的交换机的nvcc manual 会发现问题。

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

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

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

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

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

【讨论】:

  • 谢谢!这让我克服了错误,但我现在面临一个新错误。我在文章末尾添加了一些新的 makefile 行来编辑我的帖子。
  • 现在您需要链接到 cublas 设备库。将 -lcublas_device -lcudadevrt 添加到您的链接规范 (LIBS)。
  • 谢谢!有效。我做了几个更新。最终 Makefile 附加到原始帖子。
  • 大家好,我似乎在 Mint 上使用 Cuda 9.1 时遇到了相同的问题和相同的错误消息。 (如果在带有 Cmake 3.9.1 的 windows7 上使用 Cmake 3.9 和 VC2017 编译该项目,则该项目有效)我不确定如何处理这个问题,因为 Cmake 的行为随着不同的版本而改变,以及 Cuda 对 VS 的支持。我可以简单地重写标志以便删除 -c 选项吗?
猜你喜欢
  • 2013-05-07
  • 2012-08-05
  • 2011-02-27
  • 1970-01-01
  • 2017-06-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
相关资源
最近更新 更多