Alink教程(Java版)
Alink教程(Python版)
该文档涉及的组件

Failed to load BLAS警告——Mac OS上解决方法

问题描述:


运行Alink自带的example时,会出现两条不影响程序执行的警告:

六月 05, 2021 3:40:36 下午 com.github.fommil.netlib.BLAS <clinit>

警告: Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS

六月 05, 2021 3:40:36 下午 com.github.fommil.netlib.BLAS <clinit>

警告: Failed to load implementation from: com.github.fommil.netlib.NativeRefBLAS

ALink的线性代数模块依赖于netlib-java进行优化处理(用到com.github.fommil.netlib和breeze,查看maven依赖树,依赖顺序是alink_core_flink -> breeze -> netlib)。这条警告消息说明将使用纯JVM实现,如果程序需要进行大规模线性计算用纯JVM速度会很慢。

可能原因分析:


  1. 没有安装BLAS库,需要根据系统安装合适的BLAS库
  2. 安装了BLAS,但是BLAS是C/Fortran写的,JVM无法直接运行,需要通过netlib-java调用


BLAS与netlib-java介绍:


BLAS

(Basic Linear Algebra Subprograms)是进行向量和矩阵等基本线性代数操作的数值库。这些程序是LAPACK(Linear Algebra PACKage)的一部分,便于建立功能更强的数值程序包。BLAS库有大量优化版本,如Intel的MKL,ATLAS,以及利用GPU计算技术实现的CUBLAS等。

netlib-java

是对BLAS等库的调用接口的封装,方便在JVM上运行,也是Spark默认的依赖之一。netlib-java官网介绍如下:

netlib-java is a wrapper for low-level BLAS, LAPACK and ARPACK that performs as fast as the C / Fortran interfaces with a pure JVM fallback. netlib-java is included with recent versions of Spark

所以说,netlib-java不是数值计算库,它用JNILoader调用系统里安装好的、更底层的BLAS库,加载时按照

  • delegating builds that use machine optimised system libraries
  • self-contained native builds using the reference Fortran from netlib.org
  • F2J to ensure full portability on the JVM

的顺序检查是否已经安装了有优化的动态库,没有安装的话就用JVM实现的线性计算方法。

解决过程:


Install BLAS

假如本地没有BLAS库,可以使用apt-get或者homebrew安装一个,具体参考官网的Library安装介绍。因为我的系统是自带vecLib(位于/System/Library/Frameworks/vecLib.framework/,一个针对macOS做过向量运算优化的BLAS库)的macOS Big Sur,假如你也有,那就不用再安装其他BLAS了。

Install netlib-java

官网不推荐用源码安装,最好用maven添加依赖的jar包。注意,ALink原本的依赖关系中已有netlib,如图

用的“core”版本。所以我先在alink_core_flink的pom.xml中排除了breeze对netlib.core的依赖,如下

<!-- breeze dependency -->
<dependency>
    <groupId>org.scalanlp</groupId>
    <artifactId>breeze_${alink.scala.major.version}</artifactId>
    <version>${breeze.version}</version>
    <exclusions>
        <!-- This is included as a compile-scoped dependency by jtransforms, which is
             a dependency of breeze. -->
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.github.fommil.netlib</groupId>
            <artifactId>core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

然后另外添加对“all”的依赖,参考官网写法,如下:

<dependency>
    <groupId>com.github.fommil.netlib</groupId>
    <artifactId>all</artifactId>
    <version>1.1.2</version>
    <type>pom</type>
</dependency>


配置JVM参数

针对想要进一步定制使用的BLAS库的用户,官网还介绍了相应的JVM参数设置方法。

在IDEA中配置JVM参数的方法是,"Help" --> "Edit Custom VM Options",然后修改"idea.vmoptions"文件(没有的话会自动创建一个)。需要添加的参数见https://github.com/fommil/netlib-java#customisation

但是实际上,我并没有进行这个配置,因为更新maven后,发现自动下载了以下动态库:

官网的性能测试显示,nativeref和nativesystem库与CBLAS等库在macOS上性能差异不大,所以我略去了配置JVM这一步。

效果测试

用以下代码进行了一百次矩阵乘,测试10次,修改netlib版本前平均花费9.807s,修改后花费2.759s。

for(int i=0;i<100;i++) {
    DenseMatrix matA = DenseMatrix.rand(400, 300);
    DenseMatrix matB = DenseMatrix.rand(300, 500);
    DenseMatrix matC = matA.multiplies(matB);
    DenseMatrix matD = new DenseMatrix(500, 400);
    BLAS.gemm(1., matB, true, matA, true, 0., matD);
    Assert.assertArrayEquals(matD.transpose().getData(), matC.data, TOL);
}

修改后不再有warning,运行时出现正确调用了c编写的动态库的提示,如下:

六月 06, 2021 10:48:46 上午 com.github.fommil.jni.JniLoader liberalLoad

信息: successfully loaded /var/folders/t6/wzswp0mj7wncdrt0qb4f19m80000gn/T/jniloader2915855141334031512netlib-native_system-osx-x86_64.jnilib