为CUDA程序创建makefile

3

我想使用CUDA和C++自动编译一个玩具库。然后我写了下面的Makefile:

CC=g++
NVCC=nvcc
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -c -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
matrix_cuda.o: marix_cuda.cu
     $(NVCC) $(CUDAFLAGS)   matrix_cuda.cu
all: matrix_cuda.o
        $(CC) -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
clean:
    rm -rf test *.o

输入make命令后,我得到以下结果:

make: *** No rule to make target `marix_cuda.cu', needed by `matrix_cuda.o'.  Stop.

我之前从来没有写过Makefile,可能哪里出了问题?


你如何在命令行中构建库,而不使用Make? - Beta
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu 然后 g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11 - pateheo
请尝试从此教程/示例开始:https://docs.google.com/document/d/e/2PACX-1vStJ4SiboX3JeoPpNxnNS6kr8UB-SurWjqvSUUVd9dCmEOcjGZMQGhQicAFItnlwjr165BAEEVU3JQ_/pub - Talgat
4个回答

8
我认为您在CUDA文件名中有一个拼写错误。
matrix_cuda.o: marix_cuda.cu
     $(NVCC) $(CUDAFLAGS)   matrix_cuda.cu

我的观点是应该

matrix_cuda.o: matrix_cuda.cu
     $(NVCC) $(CUDAFLAGS)   matrix_cuda.cu

1
这应该是被接受的答案。很明显有一个打字错误,而且错误信息也确切地指出了这一点! - Aditya Wagh

3
这可能需要几次迭代。
1)首先尝试这个:
nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu

如果成功(并生成matrix_cuda.o,我想),请删除matrix_cuda.o并尝试使用以下makefile:
matrix_cuda.o: matrix_cuda.cu
    nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu

如果这个方法有效,
3) 试试这样做:
g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11

如果这样做可以成功,那么请移除test并执行以下操作:
4)尝试使用此makefile:
test: matrix_cuda.o
    g++ -o test matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o -L/usr/local/cuda-7.5/lib64 -I/usr/local/cuda-7.5/include -lopenblas -lpthread -lcudart -lcublas -fopenmp -O3 -Wextra -std=c++11

matrix_cuda.o: matrix_cuda.cu
    nvcc -std=c++11 -c -arch=sm_20 matrix_cuda.cu

如果这样能行的话,删除testmatrix_cuda.o,然后再试试那个makefile。如果这样可以工作,我们还可以进行进一步的改进。

它停在第2步。我输入了make all,然后出现了make: *** No rule to make target marix_cuda.cu, needed by matrix_cuda.o. Stop.的错误提示。 - pateheo
@pateheo:matrix_cuda.cu 是否在工作目录中(即您所在的目录)? - Beta

1

我想在这个 Makefile 上添加一些注释,以备将来参考和更好的自动化:

1. 环境变量NVCC=nvcc 是多余的。 NVIDIA GPU 只有一个编译器,如果要为其他架构(如 AMD)编译,仍然必须更改很多标志。

  1. -arch=native 更适合在具有不同架构的GPU的多台机器上部署代码。

  2. -dc 是用于分离编译的标志。在-dc之前必须指定架构,请参见(使用通用Makefile):https://developer.nvidia.com/blog/separate-compilation-linking-cuda-device-code/

  3. 您应该添加自动规则以避免出现这些拼写错误:

%.o: %.cu
     nvcc -dc $(CUDAFLAGS) $< -o $@

Makefile将查找所有以.o结尾的依赖项。如果需要构建一个,它会查看是否有相应的.cu文件。实际上,我会从标志中删除-dc,并在此明确表示我要构建对象文件。 $@是规则目标的名称。$<是第一个先决条件。只能使用-dc标志一次传递一个文件给nvcc,因此这里$<比$^更好。

  1. 您可以在变量中添加可执行文件的名称,以便删除生成的相同可执行文件(并简化名称更改)。

  2. 我添加了一个.PHONY规则。这仅消除了每当有人在目录中编写名为clean的文件时发生的混乱。 Makefile无法区分文件和make clean规则。

CC=g++
CXXFLAGS= -fopenmp -O3 -Wextra -std=c++11
CUDAFLAGS= -std=c++11 -arch=sm_20
LIBS= -lopenblas -lpthread -lcudart -lcublas
LIBDIRS=-L/usr/local/cuda-7.5/lib64
INCDIRS=-I/usr/local/cuda-7.5/include
PROGRAM= test
%.o: %.cu
     nvcc -dc $(CUDAFLAGS) $< -o $@
all: matrix_cuda.o
        $(CC) -o $(PROGRAM) matrix_blas.cpp alg.cpp test.cpp matrix_cuda.o $(LIBDIRS) $(INCDIRS) $(LIBS) $(CXXFLAGS)
.PHONY: clean
clean:
    rm -rf $(PROGRAM) *.o

0

另外,你的第一个make规则对应于编译对象文件matrix_cuda.oall make规则应该放在第一位,因为在调用make命令时,make文件中的第一个规则是最先更新的规则。GNU Make有很好的文档,解释如何制作简单到复杂的makefile。你可以在这里查看:

https://www.gnu.org/software/make/manual/make.html

另外,你将遇到的另一个问题是,在all规则的make recipe中,你只需要链接对象文件以创建最终可执行文件。然而,你正在尝试在此链接步骤中包含matrix_blas.cpp alg.cpp test.cpp。这些文件需要是.o版本(已编译的对象),而不是.cpp版本。Make可以为你生成这些对象文件。你只需要为每个对象文件设置一个make规则和recipe。例如:

matrix_blas.o: matrix_blas.cpp
    $(CC) $(CXXFLAGS) -c matrix_blas.cpp -o matrix_blas.o

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接