magma既能运行在N卡上,也能跑在A卡上,我们先以N卡为主;
这里主要关注它的 Makefile 系统,并且以依赖于 openblas 的构建为主线;
从项目的READ.me可知,我们应当 cd magma/ && cp make.inc.examples/make.inc.openblas ./make.inc; 并修改其中的OPENBLASDIR变量的值为自己系统安装OpenBLAS的绝对路径;
Bitbuckethttps://bitbucket.org/icl/magma/src/master/
第一层的makefile是:magma/Makefile
它的第一句是:
include make.inc
现在用注释的方式分析一下 make.inc 文件
所以,我们先分析 cp过来的这个 make.inc 文件
// make.inc
#//
# -- MAGMA (version 2.0) --
# Univ. of Tennessee, Knoxville
# Univ. of California, Berkeley
# Univ. of Colorado, Denver
# @date
#//
# --------------------
# configuration
# should MAGMA be built on CUDA (NVIDIA only) or HIP (AMD or NVIDIA)
# enter 'cuda' or 'hip' respectively
BACKEND ?= cuda
# set these to their real paths
#OPENBLASDIR ?= /usr/local/openblas
OPENBLASDIR ?= /usr/local/myOpenblas # openblas 的安装目录路径, make install 时的 prefix 的值; 如果没有指定prefix,那么将会安装在/opt/OpenBLAS/下面;
CUDADIR ?= /usr/local/cuda # 这句一般不用改,cuda的默认安装目录;
HIPDIR ?= /opt/rocm/hip # 由于仅仅运行在N卡上,后端选择了cuda,所以本句在后续内容中将被过滤掉;
# require either hip or cuda
ifeq (,$(findstring $(BACKEND),hip cuda)) # 检测上面第一行的设置,cuda 或 hip 必设其一;
$(error "'BACKEND' should be either 'cuda' or 'hip' (got $(BACKEND))")
endif
# --------------------
# programs
# set compilers
CC ?= gcc
CXX ?= g++
FORT ?= gfortran
HIPCC ?= hipcc
NVCC ?= nvcc
DEVCC ?= NONE # 根据后端是cuda,还是hip,来设置 DEVCC 为 NVCC的值,或者 HIPCC的值;
# set from 'BACKEND'
ifeq ($(BACKEND),cuda)
DEVCC = $(NVCC)
else ifeq ($(BACKEND),hip)
DEVCC = $(HIPCC)
endif
# and utilities
ARCH = ar # 设置备份压缩命令,此处主要用于将目标文件打包为静态链接库
ARCHFLAGS = cr # ar命令的指示,cr中的r表示将新的目标文件插入到原来的打包文件中,既保留包中原来的其他目标文件; a表示建立备存文件;
RANLIB = ranlib # 在完成库成员追加以后让加入的所有 .o 文件中定义的函数(变量)有效,即,对静态库的符号索引表进行更新;
# --------------------
# flags/settings
# set our GPU targets
ifeq ($(BACKEND),cuda)
GPU_TARGET = Volta Turing Ampere
# 指定N卡的具体架构,V100为Volta; Turing为rtx20x0系列显卡; A100为Ampere(或 rtx3060及以上系列显卡); H100为Hopper(或 rtx4060及以上系列);
else ifeq ($(BACKEND),hip)
GPU_TARGET = gfx900 gfx906 gfx908
# 指定A卡的具体架构,不展开了。
endif
# Use -fPIC to make shared (.so) and static (.a) library;
# can be commented out if making only static library.
FPIC = -fPIC
# gcc的生成动态链接库选项,生成地址无关码
# now, generate our flags
CFLAGS = -O3 $(FPIC) -DNDEBUG -DADD_ -Wall -fopenmp -std=c99
# gcc 编译标识, -O3最高级别优化; -DNDEBUG == #define NDEBUG; -Wall 开启警告
CXXFLAGS = -O3 $(FPIC) -DNDEBUG -DADD_ -Wall -fopenmp -std=c++11
# 相反于 -Wunused-dummy-argument Warn about unused dummy arguments.
FFLAGS = -O3 $(FPIC) -DNDEBUG -DADD_ -Wall -Wno-unused-dummy-argument #
F90FLAGS = -O3 $(FPIC) -DNDEBUG -DADD_ -Wall -Wno-unused-dummy-argument -x f95-cpp-input
# fortran编译器的标识
LDFLAGS = $(FPIC) -fopenmp
# 链接标识
DEVCCFLAGS = -O3 -DNDEBUG -DADD_
# nvcc的编译标识; -DADD_ == #define ADD_,是为了给函数名的末尾加一个下划线 func => func_,防止重名之类的;
# DEVCCFLAGS are populated later in `backend-specific`
# --------------------
# libraries
# gcc with OpenBLAS (includes LAPACK)
LIB += -lopenblas
# 需要链接的外库, 提供cpu blas he lapack API lib;
# --------------------
# directories
# define library directories preferably in your environment, or here.
LIBDIR += -L$(OPENBLASDIR)/lib
#追加定义链接库的路径
INC +=
# --------------------
# checks
# check for openblas
-include make.check-openblas # 包含一个新的makefile文件;其中的内容是检查变量 OPENBLASDIR 是否为空;并检查这个文件夹是否存在
# --------------------
# backend-specific
# add appropriate cuda flags
ifeq ($(BACKEND),cuda) # 如果后端是cuda,而不是hip
-include make.check-cuda # 包含一个新的makefile文件进来,检查变量 CUDADIR 是否为空; 如果为空则make尝试执行命令寻找到当前的cudasdk 目录,并提示用户设置方法;
DEVCCFLAGS += -Xcompiler "$(FPIC)" -std=c++11 # nvcc 生成 动态共享链接库的编译选项
# link with cuda specific libraries
INC += -I$(CUDADIR)/include
LIBDIR += -L$(CUDADIR)/lib64
LIB += -lcublas -lcusparse -lcudart -lcudadevrt
endif
# add appropriate HIP flags # hip的,先不管了,检查与追加定义inc和lib等
ifeq ($(BACKEND),hip)
-include make.check-hip
DEVCCFLAGS += $(FPIC) -std=c++11
INC += -I$(HIPDIR)/../include
LIBDIR += -L$(HIPDIR)/../aomp/lib -L$(HIPDIR)/../hipblas/lib -L$(HIPDIR)/../hipsparse/lib
LIB += -lhipblas -lhipsparse
endif
上个文件中又包含了 make.check-openblas 和 make.check-cuda,两个都是检查依赖库的存在
先看文件 make.check-openblas:
# check for OpenBLAS + LAPACK directories and give user hint how to set them
# this assumes LAPACK is part of OpenBLAS library.
ifeq ($(OPENBLASDIR),)# 如果这变量为空,即,没有指定openblas的安装路径,则报错,并提供设置建议
$(error Set $$OPENBLASDIR, preferably in your environment, e.g., run "export OPENBLASDIR=/opt/openblas" in ~/.bashrc, or "setenv OPENBLASDIR /opt/openblas" in ~/.cshrc)
endif
ifeq ($(wildcard $(OPENBLASDIR)),)# 检查所设置的文件夹是否真的存在,若不存在,则报错
$(error $$OPENBLASDIR=$(OPENBLASDIR) does not exist. Please set $$OPENBLASDIR to where OPENBLAS is installed.)
endif
再看文件 make.check-cuda:
# check for CUDA directory and give user hint how to set it
ifeq ($(CUDADIR),)# 如果 变量 CUDADIR为空,则提供设置建议
cuda := $(shell which nvcc | perl -pe 's|/bin/nvcc||')
# 临时变量 cuda,nvcc的路径,去掉后缀 /bin/nvcc 部分
ifeq ($(cuda),)# 如果 nvcc找不到,则直接将cuda 设置为 /usr/local/cuda
cuda := /usr/local/cuda
endif
$(error Set $$CUDADIR, preferably in your environment, e.g., run "export CUDADIR=$(cuda)" in ~/.bashrc, or "setenv CUDADIR $(cuda)" in ~/.cshrc)
endif
ifeq ($(wildcard $(CUDADIR)),)# 如果变量 CUDADIR 所指定的文件夹不存在,则报错;并提供设置建议
$(error $$CUDADIR=$(CUDADIR) does not exist. Please set $$CUDADIR to where CUDA is installed. (normally in /usr/local/cuda))
endif