2013年2月16日土曜日

EPDのMKLをマルチスレッドで実行する方法

概要

EPDでNumpyの行列-行列積をレッツノートJ10(i3 2350m)とデスクトップ(i5 2500k)で実行したが,性能が周波数分程度しか変わっていない.
どうやら,デフォルトではマルチスレッドでプログラムが走らないらしい.それでも,下手にC言語で行列演算をするよりもMKL連携のNumpyの方が高速なのだが,まさかMKLがマルチスレッドに対応していないわけがないと思うので,方法を探した.
方法発見までそこそこ苦労したのでまとめる.

方法

import mkl
mkl.set_num_threads(MyNum)

MyNumにスレッド数を入れる.これだけ.
あとは全部NumpyとMKLが上手くやってくれる.

ベンチ

デスクトップ環境(定格i5 2500k)で超簡単な行列-行列積ベンチマークを行ったので,ソースと実行結果を示す.なお,EPDは64bit版でOSはWindows7 64bit,メモリは16GB.

ソース:

import time import mkl import numpy as np mkl.set_num_threads(4) num2 = 10000 #行列サイズ #計算用の行列作成 starttime = time.clock() A = np.ones((num2,num2),'d') B = np.ones((num2,num2),'d') #行列作成の時間出力 print time.clock() - starttime #行列-行列積の実行 starttime = time.clock() C = np.dot(A, B) # 実行時間と演算性能の出力 print time.clock() - starttime print str(2*num2**3/(time.clock() - starttime)*1e-6) + u" [MFROPS]"

結果:

スレッド数1: 0.465379485104 77.7279291321 25730.7639873 [MFROPS] 
スレッド数2:
0.45703352782 39.7218425794 50350.0858396 [MFROPS]
スレッド数4: 0.358474042039 22.0854201077 90557.3095905 [MFROPS]
スレッド数8: 0.459133079081 22.1900988011 90130.1277687 [MFROPS]
インテルによるとi5 2500kの理論性のはターボ無しで105.6 [GFLOPS] = 105600 [MFLOPS]らしいので,4スレッドで実行すると85.8 %の実行効率が得られたことになる. これほどの性能が得られるとちょっと信じがたい値だ. ループのない簡単な演算を行うコードならCythonは必要無さそう.理論性能をい引き出したとしても,性能向上の余地は17 %しかないということなのだから. そして,Visual Studio C++で行列演算プログラムを作成してもせいぜい10 %しか実行効率を得られない自分は行列演算では大人しく計算ライブラリやPythonのNumpyを使うべきなのだろう.

0 件のコメント:

コメントを投稿