鲲鹏社区首页
中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

安装KML_LAPACK

操作步骤

KML_LAPACK依赖于开源的Netlib LAPACK以提供完整的LAPACK接口功能。因此需自行获取开源的Netlib LAPACK v3.9.0的源代码包,并与KML_LAPACK适配,具体安装步骤如下所述:

  1. 进入KML_LAPACK源代码根目录,执行编译。
    ./build.sh
    编译完成后,会在“KML_LAPACK/output”中得到以下路径:
    • include
      • include/kml-a.b.c:保存C语言头文件,其中,a.b.c为版本号。
    • lib64
      • lib64/libklapack_xxx.a:KML_LAPACK的静态库文件。
      • lib64/libklapack_xxx.so:KML_LAPACK的动态库文件。
  2. 下载Netlib LAPACK v3.9.0的源代码包。保存在编译机器可访问的路径中,假设位于“/data/lapack-3.9.0.tar.gz”
  3. 编译原始的Netlib LAPACK库。
    1. 解压源码包。

      例如解压到“/data/lapack-3.9.0”中。

      cd /data
      tar zxvf lapack-3.9.0.tar.gz
    2. 进入“/data/lapack-3.9.0”目录,创建“build”目录并在build目录下执行构建。
      cd /data/lapack-3.9.0
      mkdir build
      cd build
      cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
      make -j

      以上命令执行完成后,会在“/data/lapack-3.9.0/build/lib”中生成liblapack.a文件。

  4. 为KML_LAPACK适配Netlib的liblapack.a。

    该步骤通过对Netlib原始liblapack.a的符号重命名实现与KML_LAPACK适配,从而获得完整的LAPACK接口功能。假设原始liblapack.a位于当前目录下,libklapack.a位于$KML_LAPACK_ROOT/lib64中。

    1. 根据KML_LAPACK库的符号表获得需要重命名的符号列表。
      执行以下命令将生成internal.sym和replaced.sym两个文件。分别为KML_LAPACK替换的Netlib LAPACK符号的接口列表,以及需要新增符号别名的Netlib LAPACK接口列表。
      nm -g $KML_LAPACK_ROOT/lib64/libklapack.a | grep -oP '\K\w+(?=_netlib_)' | sort | uniq > netlib.sym
      while read sym; do \
        if nm -g $KML_LAPACK_ROOT/lib64/libklapack.a | grep -q "T $sym"; then \
          echo $sym; \
        fi; \
      done < netlib.sym > replaced.sym
      comm -3 netlib.sym replaced.sym > internal.sym
    2. 复制原LAPACK库作为修改目标。
      cp liblapack.a liblapack_adapt.a
    3. 重命名KML_LAPACK提供的符号。
      while read sym; do \
        ar x liblapack_adapt.a $sym.f.o; \
        objcopy --redefine-sym ${sym}_=${sym}_netlib_ $sym.f.o; \
        ar ru liblapack_adapt.a $sym.f.o; \
        rm $sym.f.o; \
      done < replaced.sym
    4. 增加KML_LAPACK所需的原有符号的别名。
      1. 在当前目录下创建alias.c文件,输入如下内容后,保存并退出文件。
        #define STRINGIFY(x) STRINGIFy(x)
        #define STRINGIFy(x) #x
        #define NEW STRINGIFY(ALIAS)
        #define OLD STRINGIFY(ORIG)
        asm(
            ".section .text." NEW ",\"ax\",%progbits\n"
            ".align 2\n"
            ".global " NEW "\n"
            ".type " NEW ", %function\n"
            NEW ":\n"
            "b " OLD "\n"
            ".size " NEW ", . - " NEW "\n"
        );
      2. 实现新增符号别名。
        while read sym; do \
          gcc -c alias.c -DORIG=${sym}_ -DALIAS=${sym}_netlib_ -o ${sym}_netlib_.o; \
          ar ru liblapack_adapt.a ${sym}_netlib_.o; \
          rm ${sym}_netlib_.o; \
        done < internal.sym

      完成以上步骤后当前目录下的liblapack_adapt.a即为与KML_LAPACK适配的Netlib LAPACK库。

  5. (可选)生成完整功能的单一KML_LAPACK动态库。

    某些应用场景可能只允许链接单个LAPACK动态链接库,此时可采用以下方法将上一节生成的libklapack_xxx.a和liblapack_adapt.a合成单一的libklapack_full.so。

    假设KML_LAPACK库为$KML_LAPACK_ROOT/lib64/libklapack.a,适配后的Netlib LAPACK库为当前目录下的liblapack_adapt.a。
    gcc -o libklapack_full.so -shared -fPIC -Wl,--whole-archive $KML_LAPACK_ROOT/lib64/libklapack.a liblapack_adapt.a -Wl,--no-whole-archive -fopenmp -lpthread -lgfortran -lm

    执行完成后当前目录下会生成libklapack_full.so,可以单独链接此so得到LAPACK-3.9.0的全部接口功能。

    此时仍然需要单独链接KML_BLAS库以及libgfortran等系统库。

安装后验证

  1. 退出当前终端重新登录。
  2. 查看环境变量LD_LIBRARY_PATH是否包含KML_LAPACK的安装路径“/usr/local/kml/lib”
    env | grep LD_LIBRARY_PATH

    如果变量包含安装路径,说明安装成功。

    安装成功后在安装路径(默认路径是“/usr/local/kml”)下生成相应文件,其中,include文件夹包含了头文件,lib文件夹包含了KML_LAPACK动态库文件。

  3. 使用时,假设环境变量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.a,但不再需要Netlib LAPACK中的libblas.a。

    必须使用单线程加锁版本KML_BLAS,KML_LAPACK安装包中提供了单线程加锁版本的KML_BLAS,即/usr/local/kml/lib/kblas/locking/libkblas.so。

    单线程加锁版本KML_BLAS构建方法:在KML_BLAS/build/function.sh构建脚本23行添加-DUSE_LOCKING=1编译选项。

    • 使用动态链接库

      此场景下由于适配的Netlib LAPACK只有静态库liblapack.a,因此总是静态链接到此库。不再需要链接Netlib LAPACK的libblas.a。

      gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L $KML_LAPACK_ROOT/lib64 -lklapack -L $ADAPT_ROOT -l:liblapack.a -L $KML_BLAS_ROOT -lkblas -lgfortran -lm

      运行时需能找到KML_LAPACK所需的这些动态链接库,或者将$KML_LAPACK_ROOT/lib64和$KML_BLAS_ROOT加入LD_LIBRARY_PATH:

      export LD_LIBRARY_PATH=$KML_LAPACK_ROOT/lib64:$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 $KML_LAPACK_ROOT/lib64 -l:libklapack.a -L $ADAPT_ROOT -l:liblapack.a -L $KML_BLAS_ROOT -l:libkblas.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 $KML_LAPACK_ROOT/lib64 -lklapack -L $ADAPT_ROOT -llapack -lblas -lgfortran -lm

      运行时需能找到KML_LAPACK所需的这些动态链接库,或者将$KML_LAPACK_ROOT/lib64和$ADAPT_ROOT加入LD_LIBRARY_PATH:

      export LD_LIBRARY_PATH=$KML_LAPACK_ROOT/lib64:$ADAPT_ROOT:$LD_LIBRARY_PATH
    • 使用静态链接库
      gcc app.c -o app -fopenmp -I $KML_LAPACK_ROOT/include/kml-0.3.0 -L $KML_LAPACK_ROOT/lib64 -l:libklapack.a -L $ADAPT_ROOT -l:liblapack.a -l:libblas.a -l:libgfortran.a -lm