2021/01/08

OpenBLASのビルド

はじめに


OpenBLASのビルド方法いろいろです。リビジョンは 78702753f を使用しています。

make時に利用できるオプションは Makefile.rule に記載されています。

Linuxでビルド


単にOpenBLASをLinux環境でビルドするだけなら簡単です。Debian 10だと以下のようになります。
$ git clone https://github.com/xianyi/OpenBLAS.git
$ cd OpenBLAS
$ make -j2
<中略>
 OpenBLAS build complete. (BLAS CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_haswellp-r0.3.13.dev.a (Multi-threading; Max num-threads is 8)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
-j2で2並列ビルドにしています。gfortranがインストールされていない環境なのでLAPACK関連はビルドされていません。

ビルドしたライブラリを呼び出せるか確認するため、インストールします。

$ make PREFIX=$(pwd)/build install
https://github.com/xianyi/OpenBLAS/wiki/User-Manual#call-cblas-interface に記載されている例をビルドして実行してみます。例に記載されてるコードをコピーしたファイルがa.cです。
$ LD_LIBRARY_PATH=../build/lib gcc -I ../build/include -lopenblas a.c
$ LD_LIBRARY_PATH=../build/lib ldd a.out
        linux-vdso.so.1 (0x00007ffd9019f000)
        libopenblas.so.0 => ../build/lib/libopenblas.so.0 (0x00007f17e22f7000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f17e2110000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f17e1f8d000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f17e1f6c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f17e26aa000)
$ LD_LIBRARY_PATH=../build/lib ./a.out
11.000000 -9.000000 5.000000 -9.000000 21.000000 -1.000000 5.000000 -1.000000 3.000000 
計算結果が出力されていることを確認できました。

VirtualBox内のLinuxでビルド


CPUの自動判定ができない環境では、動かしたいCPUの系統をTARGETで指定する必要があります。 少なくともVirtualBox内では自動判定できませんでした。 TARGETの一覧はTargetList.txt に記載されています。

ここでは、VirtualBox内のDebian 10でNEHALEMを指定してみます。CPUは2個です。gfortranはインストール済みの環境です。

$ make TARGET=NEHALEM -j2
<中略>
 OpenBLAS build complete. (BLAS CBLAS LAPACK LAPACKE)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Fortran compiler ... GFORTRAN  (cmd & version : GNU Fortran (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_nehalemp-r0.3.13.dev.a (Multi-threading; Max num-threads is 2)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
依存しているライブラリは以下のようになります。
$ ldd libopenblas_nehalemp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007f5cdda3e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5cdcba7000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5cdcb86000)
        libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007f5cdc918000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5cdc757000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5cdda40000)
        libquadmath.so.0 => /lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f5cdc715000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f5cdc4f7000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5cdc4db000)

CBLASのみビルド


FortranインターフェイスもLAPACKも不要であれば、
$ make TARGET=NEHALEM ONLY_CBLAS=1 -j2
<中略>
 OpenBLAS build complete. (CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_nehalemp-r0.3.13.dev.a (Multi-threading; Max num-threads is 2)

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblas_nehalemp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007fff91ebd000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff87e467000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff87e446000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff87e285000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff87e992000)
のようにすることで依存するライブラリの数を減らせます。なお、異なるオプションでmakeを実行済みの場合は、最初にmake cleanを実行しておく必要があります。

BLASとCBLASのみビルド


gfortranがインストールされている環境であれば、NO_LAPACK=1を指定することでBLASとCBLASのみをビルドできます。
$ make TARGET=NEHALEM NO_LAPACK=1 -j2
<中略>
 OpenBLAS build complete. (BLAS CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Fortran compiler ... GFORTRAN  (cmd & version : GNU Fortran (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_nehalemp-r0.3.13.dev.a (Multi-threading; Max num-threads is 2)

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblas_nehalemp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007fff1b6ed000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8826dc6000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8826da5000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8826be4000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8827317000)

マルチスレッドなしでビルド


LAPACKが不要かつマルチスレッドも不要であれば
$ make TARGET=NEHALEM ONLY_CBLAS=1 USE_THREAD=0 -j2
<中略>
 OpenBLAS build complete. (CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_nehalem-r0.3.13.dev.a (Single-threading)  

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblas_nehalem-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007ffcdf5d1000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb537e1d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb537c5c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb538218000)
のようにすることで、依存するライブラリの数をさらに減らせます。

マルチCPU対応でビルド


Linux環境でマルチCPU対応のビルドしてみます。
$ make DYNAMIC_ARCH=1 -j2
<中略>
 OpenBLAS build complete. (BLAS CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblasp-r0.3.13.dev.a (Multi-threading; Max num-threads is 8)
  Supporting multiple x86_64 cpu models with minimum requirement for the common code being HASWELL

To install the library, you can run "make PREFIX=/path/to/your/installation install".
$ ldd libopenblasp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007ffec9b63000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6da587d000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f6da585c000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6da569b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f6da6d60000)
$ du -b libopenblasp-r0.3.13.dev.so
20676824        libopenblasp-r0.3.13.dev.so
makeのログを見る限り、
PRESCOTT
CORE2
NEHALEM
SANDYBRIDGE
HASWELL
SKYLAKEX
COOPERLAKE

BARCELONA
BULLDOZER
PILEDRIVER
STEAMROLLER
EXCAVATOR
ZEN
がビルドされてるようです。

比較のため、haswellの場合のサイズもみてみます。

$ ldd libopenblas_haswellp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007ffd066e2000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f37a4b71000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f37a4b50000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f37a498f000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f37a50dc000)
$ du -b libopenblas_haswellp-r0.3.13.dev.so
4077872 libopenblas_haswellp-r0.3.13.dev.so
複数のCPUに対応したことで .so のサイズが増えていることが分かります。

続いて、VirtualBox内のLinux環境でマルチCPU対応のビルドしてみます。

$ make TARGET=NEHALEM DYNAMIC_ARCH=1 NO_LAPACK=1 -j2
<中略>
 OpenBLAS build complete. (BLAS CBLAS)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Fortran compiler ... GFORTRAN  (cmd & version : GNU Fortran (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblasp-r0.3.13.dev.a (Multi-threading; Max num-threads is 2)
  Supporting multiple x86_64 cpu models with minimum requirement for the common code being NEHALEM

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblasp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007ffdc5bfd000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa9101af000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa91018e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa90ffcd000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa91168c000)
$ du -b libopenblasp-r0.3.13.dev.so
20676824        libopenblasp-r0.3.13.dev.so
同じようにビルドされました。

Windows10 WSL1


Windows10のWSL1環境でビルドしてみます。gfortranがインストールされている環境です。こちらもDebian 10です。

この環境でもCPU自動検出は動作しないのでTARGETを指定する必要があります。

$ make TARGET=NEHALEM ONLY_CBLAS=1 -j2
<中略>
 OpenBLAS build complete. (CBLAS)

  OS               ... Linux
  Architecture     ... x86_64
  BINARY           ... 64bit
  C compiler       ... GCC  (cmd & version : cc (Debian 8.3.0-6) 8.3.0)
  Library Name     ... libopenblas_nehalemp-r0.3.13.dev.a (Multi-threading; Max num-threads is 8)

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblas_nehalemp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007ffff07e4000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f74fdea0000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f74fde7f000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f74fdcb0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f74fe3ba000)
$ du -b libopenblas_nehalemp-r0.3.13.dev.so
3817776 libopenblas_nehalemp-r0.3.13.dev.so

Windows10 WSL1 + clang


WSL1環境でgccではなくclangでビルドしてみます。
$ make TARGET=NEHALEM ONLY_CBLAS=1 CC=clang -j2
<中略>
 OpenBLAS build complete. (CBLAS)

  OS               ... Linux
  Architecture     ... x86_64
  BINARY           ... 64bit
  C compiler       ... CLANG  (cmd & version : clang version 7.0.1-8+deb10u2 (tags/RELEASE_701/final))
  Library Name     ... libopenblas_nehalemp-r0.3.13.dev.a (Multi-threading; Max num-threads is 8)

To install the library, you can run "make PREFIX=/path/to/your/installation install".

$ ldd libopenblas_nehalemp-r0.3.13.dev.so
        linux-vdso.so.1 (0x00007fffd93c6000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc764ab0000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc764a8f000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc7648c0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc764fb5000)
$ du -b libopenblas_nehalemp-r0.3.13.dev.so
3692824 libopenblas_nehalemp-r0.3.13.dev.so
gccでビルドした場合に比べて、若干ですが .so のサイズが小さくなっています。

Windows10 WSL1 + Android NDK


Android NDKをWSL1に準備して、Android用にクロスコンパイルしてみます。 ここで利用するAndroid NDKのバージョンはr21d (21.3.6528147)です。

リリースノートによると、

  • platforms
  • sources/cxx-stl
  • sysroot
  • toolchains(toolchains/llvm を除く)
がNDKのパスから削除されるとのことですので、toolchains/llvmのみを用いてOpenBLASをビルドしてみます。

x86 32-bit


x86の32-bit向けのビルドするためのシェルスクリプトの例は以下のとおりです。
#!/bin/bash
API_VERSION=24
NDK=/path/to/ndk/android-ndk-r21d-linux-x86_64/android-ndk-r21d
NDK_BINPATH=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
NDK_SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
NDK_LIBPATH=$NDK_SYSROOT/usr/lib/i686-linux-android/$API_VERSION
NDK_CC="i686-linux-android$API_VERSION-clang --sysroot $NDK_SYSROOT -B$NDK_LIBPATH"
PATH=$NDK_BINPATH:$PATH make TARGET=NEHALEM ONLY_CBLAS=1 AR=ar CC="$NDK_CC" LDFLAGS="-L$NDK_LIBPATH" HOSTCC=gcc USE_THREAD=0 -j2
これを実行してビルドが成功すると、
 OpenBLAS build complete. (CBLAS)

  OS               ... Android
  Architecture     ... x86
  BINARY           ... 32bit
  C compiler       ... CLANG  (cmd & version : Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project
 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn))
  Library Name     ... libopenblas_nehalem-r0.3.13.dev.a (Single-threading)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
が表示されます。なお、AR=ar を AR=i686-linux-android-ar としてもビルドできます。

x86 64-bit


x86の64-bit向けのビルドするためのシェルスクリプトの例は以下のとおりです。
#!/bin/bash
API_VERSION=24
NDK=/path/to/ndk/android-ndk-r21d-linux-x86_64/android-ndk-r21d
NDK_BINPATH=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
NDK_SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
NDK_LIBPATH=$NDK_SYSROOT/usr/lib/x86_64-linux-android/$API_VERSION
NDK_CC="x86_64-linux-android$API_VERSION-clang --sysroot $NDK_SYSROOT -B$NDK_LIBPATH"
PATH=$NDK_BINPATH:$PATH make TARGET=NEHALEM ONLY_CBLAS=1 AR=ar CC="$NDK_CC" LDFLAGS="-L$NDK_LIBPATH" HOSTCC=gcc USE_THREAD=0 -j2
これを実行してビルドが成功すると、
 OpenBLAS build complete. (CBLAS)

  OS               ... Android
  Architecture     ... x86_64
  BINARY           ... 64bit
  C compiler       ... CLANG  (cmd & version : Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project
 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn))
  Library Name     ... libopenblas_nehalem-r0.3.13.dev.a (Single-threading)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
が表示されます。なお、AR=ar を AR=x86_64-linux-android-ar としてもビルドできます。

arm 32-bit


armの32-bit向けのビルドするためのシェルスクリプトの例は以下のとおりです。
#!/bin/bash
API_VERSION=24
NDK=/path/to/ndk/android-ndk-r21d-linux-x86_64/android-ndk-r21d
NDK_BINPATH=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
NDK_SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
NDK_LIBPATH=$NDK_SYSROOT/usr/lib/arm-linux-androideabi/$API_VERSION
NDK_CC="armv7a-linux-androideabi24-clang --sysroot $NDK_SYSROOT -B$NDK_LIBPATH"
PATH=$NDK_BINPATH:$PATH make TARGET=ARMV7 ONLY_CBLAS=1 ARM_SOFTFP_ABI=1 AR=ar CC="$NDK_CC" LDFLAGS="-L$NDK_LIBPATH" HOSTCC=gcc USE_THREAD=0 -j2
これを実行してビルドが成功すると、
 OpenBLAS build complete. (CBLAS)

  OS               ... Android
  Architecture     ... arm
  BINARY           ... 32bit
  C compiler       ... CLANG  (cmd & version : Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project
 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn))
  Library Name     ... libopenblas_armv7-r0.3.13.dev.a (Single-threading)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
が表示されます。なお、AR=ar を AR=arm-linux-androideabi-ar としてもビルドできます。

arm 64-bit


armの64-bit向けのビルドするためのシェルスクリプトの例は以下のとおりです。
#!/bin/bash
API_VERSION=24
NDK=/path/to/ndk/android-ndk-r21d-linux-x86_64/android-ndk-r21d
NDK_BINPATH=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
NDK_SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
NDK_LIBPATH=$NDK_SYSROOT/usr/lib/aarch64-linux-android/$API_VERSION
NDK_CC="aarch64-linux-android24-clang --sysroot $NDK_SYSROOT -B$NDK_LIBPATH"
PATH=$NDK_BINPATH:$PATH make TARGET=ARMV8 ONLY_CBLAS=1 AR=ar CC="$NDK_CC" LDFLAGS="-L$NDK_LIBPATH" HOSTCC=gcc USE_THREAD=0 -j4
mkdir -p build-aarch64
INSTALL_DIR=$(readlink -f build-aarch64)
PATH=$NDK_BINPATH:$PATH make TARGET=ARMV8 ONLY_CBLAS=1 PREFIX=$INSTALL_DIR install
これを実行してビルドが成功すると、
 OpenBLAS build complete. (CBLAS)

  OS               ... Android
  Architecture     ... arm64
  BINARY           ... 64bit
  C compiler       ... CLANG  (cmd & version : Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project
 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn))
  Library Name     ... libopenblas_armv8-r0.3.13.dev.a (Single-threading)

To install the library, you can run "make PREFIX=/path/to/your/installation install".
が表示されます。なお、AR=ar を AR=aarch64-linux-android-ar としてもビルドできます。