実行環境
OS: Windows 11
Python: 3.10.2 (インストール済みであることを前提します)
実験条件
スクリプト、使用法等はこれ以外の環境でも同様のはずです。ただしCUDAはGeForceのGPUでないと使えません。
CPU: intel corei7 11700F (ハイエンド(?))
GPU: GeForce GTX1650(4GB) (ローエンド(?))
注意
筆者は一介の学部生です。GPU等について認識が誤っている部分があるかもしれません。
誤り、誤植等ありましたら、ご指摘よろしくお願いいたします。
GPUの利用方法
1.CUDA(GeForce Experience)のインストール
公式サイトからCUDA11.6のインストーラをダウンロード。Installer TypeはLocalで大丈夫です。インストーラをダウンロード後、exeファイルを実行して指示に従ってインストールを進めます。基本的には推奨設定のまま進めて大丈夫だと思います。
2.GPUに適したドライバをインストール
このページからお使いのGPUに適したドライバをインストールしましょう。
ダウンロードタイプについてですが、大雑把にGameReadyはゲーム用(速度優先)、studioはグラフィック処理の精度優先だそうです。筆者もあまり詳しくありませんので、詳細は他の方の記事にお任せします。筆者はとりあえずGameReadyの方をインストールしました。
インストーラをダウンロード後、exeファイルを実行して同様に指示に従って進めます。GeForce Experienceはインストール済みのはずですので、ドライバーのみインストールの方で大丈夫です。
3.numpyとcupyのpipインストール(ローカル環境に入れたくない場合はvenv等の仮想環境を利用できます)
pip install cupy-cuda116
pip install numpy
pip install cupyと書いてある記事が複数ありますが、筆者の環境では失敗しました。
CUDAのバージョンによって適宜116の部分を書き換える(例えば10.1の場合cupy-cuda101)必要があるようです。(すべてのバージョンについて確認したわけではありません。)
cupyはnumpyのほとんどの関数に対応しているようですので、以下のように変更することで簡単にGPUを用いた実行が可能です。
import numpy as np
arr = np.random.random_sample((10, 10))
import cupy as cp
arr = cp.random.random_sample((10, 10))
では最後に、GPUとCPUに速度勝負をさせてみましょう。お題は逆行列計算です。
import numpy as np
import cupy as cp
import time
def test(size,num=1):
start=time.time()#時間計測開始
print(f"size:{size},num:{num}")
for i in range(num):
arr = np.random.random_sample((size, size)) #size次の乱数行列生成
rev = np.linalg.inv(arr) #逆行列計算
end=time.time()#時間計測終了
print(f"cpu:{round(end-start,8)}sec")
start=time.time()#時間計測開始
for i in range(num):
arr = cp.random.random_sample((size, size)) #size次の乱数行列生成
rev = cp.linalg.inv(arr)#逆行列計算
end=time.time()#時間計測終了
print(f"gpu:{round(end-start,8)}sec")
Size=[10,10,100,1000,2000,5000,10000]
Num=[5000,5000,500,50,25,10,5]
for s,n in zip(Size,Num):
test(s,n)
上のプログラムを用いて、行列のサイズと計算回数を適宜変化させて実験しました。
以下の動画は、プログラムをコマンドプロンプトから実行した際のタスクマネージャの様子です。
CPUとGPUが交代で動いている様子がわかっていただけると思います。
以下の表に実験結果を示します。各値は、各サイズの乱数行列についての逆行列の平均計算時間です。
比の値が1以上であれば、GPUの方が高速に計算を実行できたことを示します。
行列サイズ | CPU:Corei7 11700 (sec) | GPU:GTX1650 (sec) | 比(CPU/GPU) |
---|---|---|---|
10 | 0.00018624 | 0.00029849 | 0.624 |
10 | 0.00018572 | 0.00016565 | 1.121 |
100 | 0.00522239 | 0.00090294 | 5.784 |
1000 | 0.08481761 | 0.05751644 | 1.475 |
2000 | 0.26992218 | 0.30537095 | 0.884 |
5000 | 1.76327453 | 3.504635 | 0.503 |
10000 | 10.22772169 | 7.51856899 | 1.360 |
最初に行列サイズを10として実行したときのGPUの実行時間がやや長くなっていますが、これはGPUの起動にかかる時間の影響を含んでいると考えられます。全体としてややGPUの方が速いという印象を受けましたが、行列サイズによっては必ずしもそうではないようです。
何度か実験を行いましたが、サイズが100の時にはGPUが圧倒的に優位であり、サイズが2000の時には拮抗、5000のときにはCPUの方が優位となり、サイズ10000で再びGPUの方が速くなる、という傾向は変化しませんでした。なお、サイズ20000の行列をそのまま計算させようとすると、筆者の環境のGPUではメモリ不足でエラーとなってしまいました。
今回はPython、中でもNumpyで書かれたプログラムをGPUで実行する方法と、CPUとGPUの逆行列計算の実行時間の比較を行いました。Python環境とGPUを積んだPCがあれば簡単に実行できますので、ぜひ試してみてください。