2016-10-13 8 views
1

実際のコードに関連するコードスニペットを高速化するためにPython Numbaモジュールの@vectorizeデコレータを使用することの有効性をテストしようとしています。 CUDAcastでのデモでNumebを使用した負の速度の増加Vectorize target = 'cuda'

import numpy as np 
from timeit import default_timer as timer 
from numba import vectorize 


@vectorize(["float32(float32, float32)"], target='cpu') 
def VectorAdd(a,b): 
     return a + b 

def main(): 
     N = 32000000 

     A = np.ones(N, dtype=np.float32) 
     B = np.ones(N, dtype=np.float32) 
     C = np.zeros(N, dtype=np.float32) 


     start = timer() 
     C = VectorAdd(A, B) 
     vectoradd_time = timer() - start 

     print("C[:5] = " + str(C[:5])) 
     print("C[-5:] = " + str(C[-5:])) 

     print("VectorAdd took %f seconds" % vectoradd_time) 

if __name__ == '__main__': 
     main() 

、デモンストレーターは、経由してGPUに大きな配列の方程式を送信することにより、100倍のスピードアップを取得します@:私はhere利用できると、以下に示すCUDAcast#10に設けられたコードスニペットを利用していますベクトル化デコレータ。しかし、私がgpuに@vectorizeターゲットを設定すると:

@vectorize(["float32(float32, float32)"], target='cuda') 

...結果は3〜4倍遅くなります。 target = 'cpu'を指定すると、実行時間は0.048秒になります。 target = 'cuda'で実行時間は0.22秒です。私はIntel Core i7-4710MQプロセッサとNVIDIA Quadro K2100M GPUを搭載したDELL Precisionラップトップを使用しています。実行中のnvprof(NVIDIAプロファイラツール)の出力は、メモリ処理(予想)に多くの時間が費やされていることを示していますが、GPUではCPUの処理全体よりも機能評価に時間がかかります。明らかに、これは私が望んでいた結果ではありませんが、私のハードウェアとコードに基づいて、私の一部で何らかのエラーが発生したか、それとも合理的ですか?

答えて

0

この質問は私にとっても興味深いものです。 私はあなたのコードを試してみて、同様の結果を得ました。この「ベンチマーク」で

import numpy as np 
from timeit import default_timer as timer 
from numba import vectorize, cuda 

N = 16*50000 #32000000 
blockdim = 16, 1 
griddim = int(N/blockdim[0]), 1 

@cuda.jit("void(float32[:], float32[:])") 
def VectorAdd_GPU(a, b): 
    i = cuda.grid(1) 
    if i < N: 
     a[i] += b[i] 

@vectorize("float32(float32, float32)", target='cpu') 
def VectorAdd(a,b): 
    return a + b 


A = np.ones(N, dtype=np.float32) 
B = np.ones(N, dtype=np.float32) 
C = np.zeros(N, dtype=np.float32) 

start = timer() 
C = VectorAdd(A, B) 
vectoradd_time = timer() - start 
print("VectorAdd took %f seconds" % vectoradd_time) 

start = timer() 
d_A = cuda.to_device(A) 
d_B = cuda.to_device(B) 
VectorAdd_GPU[griddim,blockdim](d_A, d_B) 
C = d_A.copy_to_host() 
vectoradd_time = timer() - start 
print("VectorAdd_GPU took %f seconds" % vectoradd_time) 

print("C[:5] = " + str(C[:5])) 
print("C[-5:] = " + str(C[-5:])) 

私もホストからのアカウントに配列のコピーに時間がかかる:どういうわけか私はcuda.jitを使ってCUDAカーネルを書いて、あなたのコードでそれを追加しました。この問題を調査するために デバイスからホストへと移動します。この場合、GPUの機能はCPUの機能よりも遅いです。

CPU - 0.0033; 
GPU - 0.0096; 
Vectorize (target='cuda') - 0.15 (for my PC). 

コピー時間が計上されていない場合:

GPU - 0.000245 

だから、私が学んだことを、(1)コピー、ホストからデバイスへとデバイスから上記のケースでは

ホストすることは時間がかかる。それは明らかでよく知られています。 (2)理由はわかりませんが、@vectorizeはGPUの計算を大幅に遅くする可能性があります。 (3)自己書込みカーネルを使用する方が良い(もちろんメモリコピーを最小限に抑える)。

私は@ cuda.jitを明示的有限差分スキームで解くことによって@ cuda.jitをテストしました。この場合、Pythonプログラムの実行時間はCプログラムに匹敵し、約100倍のスピードアップを提供することが分かりました。これは、幸いにもこの場合、ホストとデバイスの間でデータ交換を行わずに多くの繰り返しを実行できるためです。

UPD。使用ソフトウェア&ハードウェア:Win7 64bit、CPU:Intel Core2 Quad 3GHz、GPU:NVIDIA GeForce GTX 580.

+0

ローマ、「サニティチェック」のおかげで、また@ cuda.jitコードに感謝します。私はNumbaとCUDAには新しいので、私が探検する次の大きな道になるでしょう!使用しているハードウェア(プロセッサ、GPUなど)を投稿に追加できますか? – blrmkrAE

関連する問題