生成完整的LAPACK
KML_LAPACK依赖于开源的Netlib LAPACK以提供完整的LAPACK接口功能。因此安装KML_LAPACK后需自行获取开源的Netlib LAPACK v3.12.0的源代码包。
操作步骤
- 下载Netlib LAPACK v3.12.0的源代码包。保存在编译机器可访问的路径中,假设位于“/data/Download/lapack-3.12.0.tar.gz”。
- 假设libklapack.a位于“/usr/local/kml/lib/libklapack.a”,使用以下脚本编译原始的Netlib LAPACK库,并在当前目录的lapack_adapt子目录下生成适配的liblapack_adapt.a。
set -eE echo "LAPACK_SRC_DIR ${LAPACK_SRC_DIR:-<undefined>}" echo "LAPACK_TGZ ${LAPACK_TGZ:=/data/Download/lapack-3.12.0.tar.gz}" echo "LIBKLAPACK_A ${LIBKLAPACK_A:=/usr/local/kml/lib/libklapack.a}" echo "LIBKSERVICE_A ${LIBKSERVICE_A:=${LIBKLAPACK_A/klapack/kservice}}" echo "ADAPT_DIR ${ADAPT_DIR:=./lapack_adapt}" echo "CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE:=Release}" echo "LIBLAPACK_ADAPT_A ${LIBLAPACK_ADAPT_A:=liblapack_adapt.a}" echo "LIBKLAPACK_FULL_SO ${LIBKLAPACK_FULL_SO:=libklapack_full.so}" echo "CC ${CC:=gcc}" echo "FC ${FC:=gfortran}" mkdir -p ${ADAPT_DIR} cd ${ADAPT_DIR} # build netlib lapack if [ ! -r "${LAPACK_SRC_DIR}/CMakeLists.txt" ]; then mkdir -p netlib ( cd netlib ; tar xzpf ${LAPACK_TGZ} ) LAPACK_SRC_DIR=$(cd netlib/l* ; pwd) fi mkdir -p build cmake_flags=( -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_C_COMPILER=${CC} -DCMAKE_Fortran_COMPILER=${FC} -DCMAKE_RULE_MESSAGES=off -DBUILD_DEPRECATED=on -DBUILD_TESTING=off ) ( cd build ; cmake ${cmake_flags[*]} ${LAPACK_SRC_DIR} ) ( cd build ; make -j ) cp build/lib/liblapack.a ${LIBLAPACK_ADAPT_A} # get symbols defined both in klapack and netlib lapack nm -g ${LIBLAPACK_ADAPT_A} | grep 'T ' | grep -oP '\K\w+(?=_$)' | sort | uniq > netlib.sym nm -g ${LIBKLAPACK_A} | grep 'T ' | grep -oP '\K\w+(?=_$)' | sort | uniq > klapack.sym comm -12 klapack.sym netlib.sym > comm.sym # update symbols name of ${LIBLAPACK_ADAPT_A} while read sym; do ( if ! nm ${LIBLAPACK_ADAPT_A} | grep -qe " T ${sym}_\$"; then continue fi ar x ${LIBLAPACK_ADAPT_A} ${sym}.f.o mv ${sym}.f.o ${sym}_netlib.f.o objcopy --redefine-sym ${sym}_=${sym}_netlib_ ${sym}_netlib.f.o ) & done < comm.sym wait ar d ${LIBLAPACK_ADAPT_A} $(sed -ne 's/$/.f.o/p' comm.sym) ar d ${LIBLAPACK_ADAPT_A} xerbla.f.o ar ru ${LIBLAPACK_ADAPT_A} *_netlib.f.o rm *_netlib.f.o
- (可选)生成完整功能的单一KML_LAPACK动态库。
某些应用场景可能只允许链接单个LAPACK动态链接库,此时可采用以下方法将上一节生成的libklapack_xxx.a和liblapack_adapt.a合成单一的libklapack_full.so。
假设KML_LAPACK库为“/usr/local/kml/lib/libklapack.a和/usr/local/kml/lib/libkservice.a”,适配后的Netlib LAPACK库为当前目录下的liblapack_adapt.a。${FC} -o ${LIBKLAPACK_FULL_SO} -shared -fPIC -Wl,--whole-archive ${LIBKLAPACK_A} ${LIBLAPACK_ADAPT_A} -Wl,--no-whole-archive ${LIBKSERVICE_A} -fopenmp -lpthread -lm
执行完成后当前目录下会生成libklapack_full.so,可以单独链接此so得到LAPACK-3.12.0的全部接口功能。
此时仍然需要单独链接KML_BLAS库以及libgfortran等系统库。
安装后验证
使用时,假设环境变量KML_LAPACK_ROOT为libklapack.*所在目录,ADAPT_ROOT为适配后Netlib LAPACK库所在目录。用户应用可以选择使用动态链接库或静态链接库。编译应用源代码时需要链接到KML_LAPACK、Netlib LAPACK、Netlib BLAS和gfortran库并开启OpenMP支持。
- 场景一:协同KML_BLAS场景(高性能)假设KML_BLAS已构建的库(libkblas.a和libkblas.so)位于KML_BLAS_ROOT中,为获得最高性能请使用KML_BLAS单线程版本。当使用KML_BLAS时,仍然需要上一节最后获得Netlib LAPACK适配的liblapack_adapt.a,但不再需要Netlib LAPACK中的libblas.a。
KML_LAPACK多线程调用KML_BLAS,因此不可以使用nolocking版本的KML_BLAS,推荐使用omp版本,即/usr/local/kml/lib/kblas/omp/libkblas.so。
- 使用动态链接库
此场景下由于适配的Netlib LAPACK只有静态库liblapack_adapt.a,因此总是静态链接到此库。不再需要链接Netlib LAPACK的libblas.a。
gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L /usr/local/kml/lib -lklapack -L $ADAPT_ROOT -l:liblapack_adapt.a -L $KML_BLAS_ROOT -lkblas -lgfortran -lm -lkservice
运行时需能找到KML_LAPACK所需的这些动态链接库,或者将/usr/local/kml/lib和$KML_BLAS_ROOT加入LD_LIBRARY_PATH。
export LD_LIBRARY_PATH=/usr/local/kml/lib:$KML_BLAS_ROOT:$LD_LIBRARY_PATH
- 使用静态链接库
此场景不再需要链接Netlib LAPACK的libblas.a。
gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L /usr/local/kml/lib -l:libklapack.a -L $ADAPT_ROOT -l:liblapack_adapt.a -L $KML_BLAS_ROOT -l:libkblas.a -l:libkservice.a -l:libgfortran.a -lm
- 使用动态链接库
- 场景二:无KML_BLAS场景(依赖Netlib LAPACK中自带的BLAS,性能较低)
- 使用动态链接库
gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L /usr/local/kml/lib -lklapack -L $ADAPT_ROOT -l:liblapack_adapt.a -lblas -lgfortran -lm -lkservice
运行时需能找到KML_LAPACK所需的这些动态链接库,或者将/usr/local/kml/lib和$ADAPT_ROOT加入LD_LIBRARY_PATH。
export LD_LIBRARY_PATH=/usr/local/kml/lib:$ADAPT_ROOT:$LD_LIBRARY_PATH
- 使用静态链接库
gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L /usr/local/kml/lib -l:libklapack.a -L $ADAPT_ROOT -l:liblapack_adapt.a -l:libblas.a -l:libkservice.a -l:libgfortran.a -lm
- 使用动态链接库