LoginSignup
11
13

More than 3 years have passed since last update.

行列の積でベンチマーク : NumPy, Numba, Cython, Swig, OpenCL, intelMKL

Last updated at Posted at 2017-03-20

[2020-08-26追記]
広告になりますが記事が古くなってきたのでコレスキー分解をベンチの対象として更新しました。
Pythonと関数単位での高速化(cython, numba, swig) - 夜間飛行
[2020-08-26追記ここまで]

組み込みクラスの環境にディープラーニングを突っ込むことに興味があるのですが、その中で実装も簡単で実行速度もよい方法を模索しています。
そこで、ちょっとしたベンチマークのため、NumPy, Numba, Cython, Swig, OpenCL, intelMKLでの NxN 行列2つの積を計算させました。

Swigは中でfloatをdoubleに非明示的にキャストしてたり、実装確認中のメモが一部ゾンビ化してしまいましたが、ご査収ください。もっと比較水準増やしたり、環境違いの結果なPL待ってまーす。

NumPyCuPy_test/Test01.ipynb at master · Chachay/NumPyCuPy_test

今回掛け算される人

単精度のNxN行列 maと同じく単精度のNxN行列 mb

行列の定義
N = 1000 # 下の表のNと一致
# Generate NxN randomized matrix
ma = np.random.rand(N, N).astype(np.float32)
mb = np.random.rand(N, N).astype(np.float32)

結果まとめ

NumbaでNumpyのdotを使った結果が圧倒的。だけど、実行結果キャッシュされてたりしない?

N=3 N=100 N=1000
実行時間[us] 速度 実行時間[us] 速度 実行時間[ms] 速度
1 Numpy Native 1.34 1.00 94.2 1.00 87.9 1.00
2 Numba Simple Mult 1.24 1.08 1,040.0 0.09 6,870.0 0.01
3 Numba Numpy 2.03 0.66 74.6 1.26 23.5 3.74
4 Cython Simple Mult 19.20 0.07 660,000.0 0.00 NA -
5 Cython Numpy 1.52 0.88 94.1 1.00 87.8 1.00
6 Swig Simple Mult 1.97 0.68 837.0 0.11 7,450.0 0.01
7 Swig MKL cblas_dgemm 2.57 0.52 123.0 0.77 95.8 0.92
8 OpenCL Simple Mult(Parallel) 2,560.00 0.00 3,160.0 0.03 877.0 0.10

[メモ] 実行しながらメモったはずだけど大小関係おかしい。みなおしてみます。

Numpy

リファレンス見てください

np.dot(ma, mb)

Numba

np.dotにjitをかけたNum_NpDotと、数学の定義通り行列掛け算をするNum_Dotを準備

from numba import jit
@jit
def Num_NpDot(a, b):
    return np.dot(a, b)
@jit    
def Num_Dot(a, b):
    c = np.zeros((a.shape[0], b.shape[1]))
    for i in range(a.shape[0]):
        for j in range(b.shape[1]):
            for k in range(a.shape[1]):
                c[i][j] += a[i][k] * b[k][j]
    return c

Cython

型の定義もしてやるなど目をかけながら世話をして、Cに翻訳しているということからNumbaには勝てるだろうと思っていたら、今回のような結果になり、お前にはかなりがっかりしたぞ。

Numba水準と同じ. ビルドはVC2015でO2相当の最適化(のはず).

cimport numpy as np
cimport cython
import numpy as np

@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False)  # turn off negative index wrapping for entire function

cpdef np.ndarray Cy_NpDot(np.ndarray a, np.ndarray b):
    return np.dot(a, b)

cpdef np.ndarray Cy_Dot(np.ndarray a, np.ndarray b):
    cdef np.ndarray c
    c = np.zeros((a.shape[0], b.shape[0]))
    for i in range(a.shape[0]):
        for j in range(b.shape[1]):
            for k in range(a.shape[1]):
                c[i][j] += a[i][k] * b[k][j]
    return c

Cy_DotがCython通しているくせにとても使えない子になって困った。

Swig

最近すっかりお世話になるようになった。PythonやってるのにC++で大事なところを書く。
Pythonはデータハンドリングにしか使わないのですよ、方式。

Numbaと同じく、いわゆる掛け算のSwig_DotとNumpy相当水準としてIntelMKL登板。
ビルドはVC2015でO2相当の最適化(のはず).

単精度なのにdoubleで用意してしまった。しまった。
(特にMKLの中で変なことになっていそうだけど、とりあえず目をつぶる)

void Swig_Dot(int mm1, int mn1, double* mat1,
              int mm2, int mn2, double* mat2,
              double** outmat, int* mm, int* mn)
{
    double* arr = NULL;
    arr = (double*)calloc(mm1 * mn2, sizeof(double));

    // Multiplying matrix a and b and storing in array mult.
    for(int i = 0; i < mm1; ++i)
        for(int j = 0; j < mn2; ++j)
            for(int k = 0; k < mn1; ++k)
                arr[i*mn2+j] += mat1[i*mn1+k] * mat2[k*mn2+j];
    *mm = mm1;
    *mn = mn2;
    *outmat = arr;
}

void Swig_Dot_MKL(int mm1, int mn1, double* mat1,
              int mm2, int mn2, double* mat2,
              double** outmat, int* mm, int* mn)
{
    double alpha = 1.0;
    double beta = 0.0;

    double *C = (double *)mkl_malloc( mm1*mn2*sizeof( double ), 64 );
    if (C == NULL) {
        printf( "\n ERROR: Can't allocate memory for matrices. Aborting... \n\n");
        mkl_free(C);
        return;
    }

    for (int i = 0; i < (mm1*mn2); i++) {
        C[i] = 0.0;
    }
    cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 
                mm1, mn2, mn1, alpha, mat1, mn1, mat2, mn2, beta, C, mn2);

    double *res = (double *)malloc( mm1*mn2*sizeof( double ));
    memcpy(res, C, mm1*mn2*sizeof( double ));
    *mm = mm1;
    *mn = mn2;
    *outmat = res;
    mkl_free(C);
}

OpenCL

おまけ。GPUと比較するためのスタブだと思ってください。CuPyと比べようと思ったけど、ただのハードウェア マッチョクラブになりそう。

省略。

参考文献

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13