rstsr-kml-ffi

Crates.iorstsr-kml-ffi
lib.rsrstsr-kml-ffi
version0.2.0
created_at2025-07-31 10:08:50.788583+00
updated_at2025-08-26 14:39:49.815771+00
descriptionHuawei Kunpeng Math Library FFI bindings
homepage
repositoryhttps://github.com/RESTGroup/rstsr-ffi
max_upload_size
id1774812
size2,775,610
Zhenyu Zhu ajz34 (ajz34)

documentation

README

Kunpeng Math Library FFI bindings

This crate contains KML (Kunpeng Math Library) FFI bindings.

Current FFI version is KML v24.0.0 (简体中文). If you are using an older version of KML, this crate should still work if you do not explicitly call the function that only occurs in higher version of KML.

KML is freely distributed in binary (along with header), not source code. Please note the license of KML is not fully free software, and there are some strong license restrictions.

This crate is not official bindgen project. It is originally intended to serve rust tensor toolkit RSTSR and rust electronic structure toolkit REST.

  • Audience: Anyone uses KML function may also find it useful, not only RSTSR or REST program developers.
  • Pure Extern or Dynamic Loading: This crate supports either pure extern (usual FFI, requires dynamic or static linking) and dynamic-loading, by cargo feature dynamic_loading.

Dynamic loading

This crate supports dynamic loading.

If you want to use dynamic loading, please enable cargo feature dynamic_loading when cargo build.

The dynamic loading will try to find proper library when your program initializes.

  • This crate will automatically detect proper libraries, if these libraries are in environmental path LD_LIBRARY_PATH (Linux) DYLD_LIBRARY_PATH (Mac OS), PATH (Windows).
  • If you want to override the library to be loaded, please set these shell environmental variable RSTSR_DYLOAD_KML to the dynamic library path.

NOTE: When you call BLAS and LAPACK functions with dynamic loading, please DO NOT USE other crates (such as rstsr_lapack_ffi). Please make sure you are only using rstsr_kml_ffi::blas, rstsr_kml_ffi::kblas and rstsr_kml_ffi::lapack. Sticking to using rstsr_kml_ffi will make sure you are calling BLAS and LAPACK functions from KML, instead of other BLAS vendors.

If you encountered large compile time or disk consumption, you may consider add these lines in your Cargo.toml:

[profile.dev.package.rstsr-kml-ffi]
opt-level = 0
debug = false

Cargo features

Default features:

  • blas: Inclulde BLAS bindgens.
  • kblas: Include KML CBLAS bindgens.
  • lapack: Include LAPACK bindgens.

Optional features:

  • dynamic_loading: Supports dynamic loading.
  • ilp64: Use int64_t for dimension specification, or lapack error code types if this feature specified. Otherwise, use int32_t.
    • Please note that in module blas, error code is returned by c_int; in module cblas, KML utility functions use c_int for input or output.
  • lapacke: Include LAPACKE bindgens.
  • quad_precision and ex_precision: Specify type extra-precision xdouble type in module blas. Probably few people will require these features.

Crate structure

  • header: Header files copied (or renamed) from original source.
  • scripts: Script to generate FFI bindgens.
  • src: FFI bindings:
    • service: Corresponds to kml_service.h header.
    • kblas: Corresponds to kblas.h header.
    • blas, lapack: Corresponds to Netlib LAPACK bindings.
  • In each bindgens, the following files are usually automatically generated by scripts:
    • ffi_base.rs: Basic type, enum, struct definitions.
    • ffi_extern.rs: Unsafe extern "C" bindgen functions. Only activated when not dynamic loading.
    • dyload_struct.rs: Struct Lib for dynamic loading.
    • dyload_initializer.rs: The initialization function of Lib for dynamic loading.
    • dyload_compatible.rs: Unsafe bindgen function that is compatible to that of ffi_extern.rs. Only activated when dynamic loading.
    • special case of cblas::ffi_base: the enums CBLAS_TRANSPOSE, CBLAS_UPLO, etc comes from crate rstsr_lapack_ffi for convenience. This crate depends on rstsr_lapack_ffi for those definitions of enums.

Note on licenses

Kunpeng BoostKit License Agreement is a relatively restrictive license. Even usual scientific computation user can breach license in some cases, for example:

  • 3.1 Without Huawei's prior written consent, you shall not sell, rent, lend, share, disclose, sublicense, or distribute all or part of the Kunpeng BoostKit to third parties for profit purposes.
    • Please do not use rstsr-kml-ffi for profiting products, unless consented by Huawei.
  • 3.2.7 Disclosing Kunpeng BoostKit-related data, including but not limited to performance evaluation data, without Huawei's written consent;
    • Do not perform efficiency benchmark with rstsr-kml-ffi, unless consented by Huawei.

Note on Installation of KML libklapack_full.so

By KML's yum or deb binary, you just installed libkblas.so (openmp version recommended) and libklapack.so (not linked with kblas, nor full lapack that covers all Netlib's version).

To use KML properly, it is better to generate full lapack (instead of the libklapack.so that only contains a few optimized subroutines). The guide for generating full lapack to libklapack_full.so is here (in simplified Chinese).

The guide above mentioned is sufficient if you are not using dynamic loading. However, if you are using dynamic loading, it is advised to also link libkblas.so into libklapack_full.so.

To also link to libkblas.so, an example script can be the following:

Example script to generate libklapack_full.so and also linked with libkblas.so
set -eE

echo "LAPACK_SRC_DIR         ${LAPACK_SRC_DIR:-<undefined>}"
echo "LAPACK_TGZ             ${LAPACK_TGZ:=${HOME}/Downloads/lapack-3.12.0.tar.gz}"
echo "LIBKLAPACK_A           ${LIBKLAPACK_A:=/usr/local/kml/lib/neon/libklapack.a}"
echo "LIBKSERVICE_A          ${LIBKSERVICE_A:=/usr/local/kml/lib/neon/libkservice.a}"
echo "LIBKBLAS_DIR           ${LIBKBLAS_DIR:=/usr/local/kml/lib/neon/kblas/omp}"
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

${FC} -o ${LIBKLAPACK_FULL_SO} -shared -fPIC -Wl,--whole-archive ${LIBKLAPACK_A} ${LIBLAPACK_ADAPT_A} -Wl,--no-whole-archive ${LIBKSERVICE_A} -L${LIBKBLAS_DIR} -lkblas -fopenmp -lpthread -lm

After libklapack_full.so generated, you may need to add the directory of both libkblas.so and libklapack_full.so to the environmental variable LD_LIBRARY_PATH, to let the crate rstsr-kml-ffi know where to find lapack functions.

Changelog

  • v0.2.0

    • API Breaking: Now cargo feature dynamic_loading is not default.
Commit count: 57

cargo fmt