我要评分
获取效率
正确性
完整性
易理解

Generating a Complete LAPACK Library

Procedure

  1. Download the Netlib LAPACK v3.12.0 source package. Save the package in a path that can be accessed by the compilation device, for example, /data/Download/lapack-3.12.0.tar.gz.
  2. Assume that libklapack.a is in the /usr/local/kml/lib/libklapack.a directory. Run the following script to compile the original Netlib LAPACK library. Then the adapted file liblapack_adapt.a will be generated in the lapack_adapt subdirectory of the current directory.
    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
  3. (Optional) Generate a standalone KML_LAPACK dynamic library with complete functions.

    In some application scenarios, only a single LAPACK dynamic link library can be linked. In this case, you can use the following method to combine libklapack_xxx.a and liblapack_adapt.a generated previously into a single libklapack_full.so.

    For example, if KML_LAPACK is /usr/local/kml/lib/libklapack.a and /usr/local/kml/lib/libkservice.a, then the adapted Netlib LAPACK library is liblapack_adapt.a in the current directory.
    ${FC} -o ${LIBKLAPACK_FULL_SO} -shared -fPIC -Wl,--whole-archive ${LIBKLAPACK_A} ${LIBLAPACK_ADAPT_A} -Wl,--no-whole-archive ${LIBKSERVICE_A} -fopenmp -lpthread -lm

    After the execution is complete, the libklapack_full.so file is generated in the current directory. You can link the libklapack_full.so file to obtain all interface functions of LAPACK-3.12.0.

    The KML_BLAS library and system libraries such as libgfortran need to be linked separately.

Verifying the Installation

Assume that the environment variable KML_LAPACK_ROOT is the directory of libklapack.*. Then ADAPT_ROOT is the directory of the adapted Netlib LAPACK library. User applications can use dynamic link libraries or static link libraries. When compiling the application source code, you need to link to the KML_LAPACK, Netlib LAPACK, Netlib BLAS, and GFortran libraries and enable OpenMP support.

  • Scenario 1 with KML_BLAS (high performance)
    Assume that the libraries (libkblas.a and libkblas.so) constructed by KML_BLAS are located in KML_BLAS_ROOT. To achieve optimal performance, use the KML_BLAS single-thread version. Using KML_BLAS requires the adapted file liblapack_adapt.a but does not require libblas.a in Netlib LAPACK.

    KML_LAPACK uses multiple threads to call KML_BLAS. Therefore, KML_BLAS of the nolocking version cannot be used. You are advised to use the omp version, that is, /usr/local/kml/lib/kblas/omp/libkblas.so.

    • Using the dynamic link library

      In this scenario, the Netlib LAPACK has only the static library liblapack_adapt.a. Therefore, the library is always statically linked. The libblas.a file of the Netlib LAPACK does not need to be linked.

      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

      The dynamic link libraries required by KML_LAPACK must be found, or /usr/local/kml/lib and $KML_BLAS_ROOT must be added to LD_LIBRARY_PATH.

      export LD_LIBRARY_PATH=/usr/local/kml/lib:$KML_BLAS_ROOT:$LD_LIBRARY_PATH
    • Using the static link library

      In this scenario, libblas.a of Netlib LAPACK does not need to be linked.

      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
  • Scenario 2 without KML_BLAS (depending on BLAS in Netlib LAPACK, low performance)
    • Using the dynamic link library
      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

      The dynamic link libraries required by KML_LAPACK must be found, or /usr/local/kml/lib and $ADAPT_ROOT must be added to LD_LIBRARY_PATH.

      export LD_LIBRARY_PATH=/usr/local/kml/lib:$ADAPT_ROOT:$LD_LIBRARY_PATH
    • Using the static link library
      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