de[v|b]log

ShellScript, Coffee, iOS/OSX Dev
Origin: Himajinworks.
About.

Intel Math Kernel Library (MKL)をGNU Octave経由で利用するということでちょっとしたメモを残します。

そのまえに

実は @mopp に、「なんか去年の8月くらいからMKLが無料で使えるようになったみたいっすよ」と言われて気づいて使ってみようという流れ。
Ubuntu環境にOctaveをapt経由で入れるとreference BLASがデフォルトで入ってくるらしく、遅いので切り替え先を考えようという感じです。

想定環境

  • この記事は環境としてUbuntu Server 14.04 (64 bit)を想定しています。
    • 今回導入した対象のマシンのCPUに関する情報は以下。
      • Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz
  • 環境を構築するにあたってはaptを用い、GNU Octaveもapt経由でインストールするものとします。
  • 比較対象としてOpenBLASを用いています。インストールに関してはubuntu 14.04でBLASを使う - kashiの日記を参考にして行いました。(すごいわかりやすいと思います。)

注意

  • 今回すでにOctaveやOpenBLAS等のインストールされた作業環境に追加でMKLを導入したため、依存関係を明確に示すことはできません。

MKLのダウンロード

環境構築

※ すでにMKLのインストーラ(l_mkl_*.*.*.*.tgz)がダウンロードされているものとします。

  1. ダウンロードしたインストーラを含むファイルを展開し、展開先のディレクトリに入る。
  2. CUI環境を対象としているためinstall.shを実行し、会話形式のインストーラでインストールをすすめる。
    • ここでインストール対象のパスが指定できるが、今回はデフォルトで提示された/opt/intelを利用した。
  3. インストールが完了したら再起動する。

実行について

  • 今回はOctaveをMKLにリンクしてビルドするのとは別の手段をとったため、Octave - GHER内の"Using MKL"を参考にし、起動時に共有ライブラリをプリロードすることで利用した。
    • 以下に今回利用した実行スクリプト(zshスクリプト)を示します。
    • 以下のスクリプトに関してはMITライセンス下で提示するものとします
    • ユーザーはMKL_INSTALL_VERSION/opt/intel/compilers_and_libraries_**のディレクトリ名を参考にして埋めて、またNB_THREADSを適切に与える必要があります。(NB_THREADSは物理コア数で良いかと思います。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#! /usr/bin/env zsh

#
# This script is distributed under MIT license.
#
# ---
#
# The MIT License (MIT)
#
# Copyright (c) 2016 K. Murakami
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# ---
#

#
# Usage :
#    ./this_script.sh task.m
#

#
# Configure base paths
#
MKL_INSTALL_VERSION= # User will specify this value.

if [[ -z "${MKL_INSTALL_VERSION}" ]]; then
    echo "Install version was not specified." 1>&2
    return 1
fi

MKL_PATH=/opt/intel/compilers_and_libraries_${MKL_INSTALL_VERSION}/linux
MKL_LIB=${MKL_PATH}/mkl/lib/intel64_lin
MKL_COMPILER_LIB=${MKL_PATH}/compiler/lib/intel64_lin

#
# Configure the number of threads
#
NB_THREADS= # User will specify this value.

#
# Validate lib paths
#
if [[ -z "${MKL_LIB}" ]]; then
    echo "MKL_LIB is not specified." 1>&2
    return 1
fi

if [[ ! -e ${MKL_LIB} ]]; then
    echo "MKL_LIB is not exist in specified path. (${MKL_LIB})" 1>&2
    return 1
fi

if [[ -z "${MKL_COMPILER_LIB}" ]]; then
    echo "MKL_COMPILER_LIB is not specified." 1>&2
    return 1
fi

if [[ ! -e ${MKL_COMPILER_LIB} ]]; then
    echo "MKL_COMPILER_LIB is not exist in specified path. (${MKL_COMPILER_LIB})" 1>&2
    return 1
fi

#
# Configure library paths
#
MKL_LIB_PATHS=()

## libmkl_gf_lp64
MKL_LIB_PATHS+=${MKL_LIB}/libmkl_gf_lp64.so

## libmkl_intel_thread
MKL_LIB_PATHS+=${MKL_LIB}/libmkl_intel_thread.so

## libmkl_core
MKL_LIB_PATHS+=${MKL_LIB}/libmkl_core.so

## libiomp5
MKL_LIB_PATHS+=${MKL_COMPILER_LIB}/libiomp5.so

#
# Validate paths
#
for lib_path in ${MKL_LIB_PATHS}; do
    if [[ ! -e ${lib_path} ]]; then
        echo "Required library not found in ${lib_path} ." 1>&2
        return 1
    fi
; done

#
# If task is not specified, this script will launch octave CLI.
#
TASK=(${*})

#
# Run task
#
MKL_NUM_THREADS=${NB_THREADS} LD_PRELOAD="${MKL_LIB_PATHS}" octave -q ${TASK}

return ${?}

ベンチマーク

  • 以下のベンチマークの結果は10回実行した平均実行時間。
    行列積、和、一般化逆行列の結果についてはInv, Add, Mult with OpenBLAS and Intel MKLで見ることができます。

SGEMM

  • Drop-in Acceleration of GNU Octave | Parallel Forall | Parallel Forallを参考に、SGEMMのベンチマークのコードを作成した。
    • 入力は8192×8192の正方行列。
    • 入力の行列の要素は乱数生成器で生成される値で、単精度浮動小数点数。
    • 結果で示す性能指標(Flops)は、10回実行した平均実行時間をもとにして計算。
  • 結果
    • MKL :
      • 6.7958961487 sec (STDDEV : 1.0908508286)
      • 161.790528 GFlops
    • OpenBLAS :
      • 6.0104995728 sec (STDDEV : 0.0616038211)
      • 182.931820 GFlops

DGEMM

  • Drop-in Acceleration of GNU Octave | Parallel Forall | Parallel Forallを参考に、DGEMMのベンチマークのコードを作成した。
    • 入力は8192×8192の正方行列。
    • 入力の行列の要素は乱数生成器で生成される値で、倍精度浮動小数点数。
    • 結果で示す性能指標(Flops)は、10回実行した平均実行時間をもとにして計算。
  • 結果
    • MKL :
      • 18.2146522522 sec (STDDEV : 0.5390612789)
      • 60.364130 GFlops
    • OpenBLAS :
      • 19.9562644958 sec (STDDEV : 0.2537641703)
      • 55.096064 GFlops

行列和

(DGEMMでよかったが、その前に回してしまったので提示)

  • 乱数生成器で生成された倍精度の値を要素とする任意のサイズの正方行列を与える。

matrix_add

行列積

(DGEMMでよかったが、その前に回してしまったので提示)

  • 乱数生成器で生成された倍精度の値を要素とする任意のサイズの正方行列を与える。

matrix_mult

一般化逆行列

  • Octaveのpinvに対して乱数生成器で生成された任意のサイズの正方行列を与える。

matrix_geninv

感想とか

参考