NumPyからCuPyへ:高速化の一例
はじめに
Pythonで数値計算を行う際によく使われるライブラリがNumPyです。しかし、GPUを活用することで計算速度を向上させたい場面も多いでしょう。そこでCuPyが登場します。この記事では、NumPyのコードをCuPyに置き換える一例とその性能比較について解説します。一方でCuPyの苦手な処理についても触れますので、使いどころを間違えないようにしましょう。
環境
$ pip install numpy cupy
Installing collected packages: fastrlock, numpy, cupy
Successfully installed cupy-12.2.0 fastrlock-0.8.2 numpy-1.24.4
(cupy)
$ pip list
Package Version
------------- -------
cupy 12.2.0
fastrlock 0.8.2
numpy 1.24.4
pip 23.2.1
pkg_resources 0.0.0
setuptools 44.0.0
$ python -V
Python 3.8.10
$ uname -a
Linux user 5.15.0-83-generic #92~20.04.1-Ubuntu SMP Mon Aug 21 14:00:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
- Ubuntu 20.04
インストール
バイナリパッケージ(ホイール形式)は、PyPI上でLinuxおよびWindows向けに利用可能。
Platform | Architecture | Command |
---|---|---|
CUDA 10.2 | x86_64 / aarch64 | pip install cupy-cuda102 |
CUDA 11.0 | x86_64 | pip install cupy-cuda110 |
CUDA 11.1 | x86_64 | pip install cupy-cuda111 |
CUDA 11.2 ~ 11.8 | x86_64 / aarch64 | pip install cupy-cuda11x |
CUDA 12.x | x86_64 / aarch64 | pip install cupy-cuda12x |
ROCm 4.3 (experimental) | x86_64 | pip install cupy-rocm-4-3 |
ROCm 5.0 (experimental) | x86_64 | pip install cupy-rocm-5-0 |
上記を参考に、pipでインストールします。
CuPyについて
CuPyはPythonプログラミング言語でGPUによる高速計算をサポートするオープンソースライブラリです。多次元配列、疎行列、およびそれらの上で実装された多様な数値アルゴリズムをサポートしています。CuPyはNumPy同じAPIセットを共有しており、NumPy/SciPyのコードをGPUで実行するためのドロップイン置換として機能します。CuPyはNVIDIAのCUDA GPUプラットフォームと、v9.0からはAMDのROCm GPUプラットフォームもサポートしています。
NumPyのサンプルコード
まずは、行列の積を計算するシンプルなNumPyのコードを見てみましょう。
CuPyによる高速化
次に、上記のコードをCuPyに置き換えてみます。
性能比較
両者のコードを実行した結果、CuPyの方が計算速度が大幅に向上したことが確認できました。
- NumPy Time: 3.5 seconds
- CuPy Time: 1.0 seconds
初回オーバーヘッド: CuPy(または他のGPUライブラリ)をはじめて使用する際には、GPUの初期化などに時間がかかる場合があります。このオーバーヘッドは一度だけ発生することが多いです。
CuPyの苦手な処理
CuPyを使用する際には、CPUからGPUへのデータ転送が必要なケースがあります。このデータ転送は、大量のデータを扱う場合には、パフォーマンスに悪影響となります。以下に、この「苦手な処理」を模倣する簡単なPythonコードを示します。
NumPyのサンプルコード
CuPyのサンプルコード
性能比較
NumPy Calculation time: 0.02361893653869629 seconds
CuPy Data transfer time: 0.2935044765472412 seconds
CuPy Calculation time: 0.34106016159057617 seconds
約17倍の差があります。このように、データ転送が必要なケースでは、CuPyのパフォーマンスが悪化することがあります。
使いどころを間違えないようにしましょう。
まとめ
CuPyはGPUを活用して高速な数値計算を可能にする強力なライブラリですが、その性能を最大限に引き出すためにはいくつかの注意点があります。とくに、CPUからGPUへのデータ転送が必要な場合、この転送時間が全体のパフォーマンスに影響を与える可能性があります。
一方で、大量のデータに対する複雑な計算を高速に行う必要がある場合、CuPyは非常に有用です。また、初回のオーバーヘッドを除けば、一般的にはNumPyよりも高速に動作することが多いです。
以上がCuPyとNumPyの比較、そしてCuPyの使いどころについての簡単なガイドでした。どちらのライブラリもそれぞれの用途で非常に優れていますので、自分のプロジェクトに最適な選択をしてください。
以上です。ありがとうございました。
Discussion
すみません、実行時間に関して質問したいです。
数秒代だと誤差がどのくらいあるかが知りたいです
コメントありがとうございます。
結論から先に申し上げると、ケースバイケースとなります。
以下に根拠をリストアップするので、それらが参考になれば幸いです。
CuPy
はGPUへのデータ転送に時間がかかるCuPy
の性能を活かすには小さな前処理を挟む必要があるかも知れません。CuPy
のメリットが活きてきます。そうでなければNumPy
をCPUで処理させたほうが良いかも知れません。PCIe
の帯域幅が処理速度に影響します。(つまり各パーツの性能全てが変数となる。)なので、結果的に処理させる端末で簡単な処理系を作って試してみないと、具体的なパフォーマンスをはかることはできません。
ということで、サンプルコードを書きました。
上記コードに必要なライブラリ
コードは仮想環境をアクティベートして実行します。
その結果、以下の出力を得ました。
初期変数
x
の値を変化させたときの処理速度を示しています。初期変数
x
が十分に大きくなった時、CuPy
が活きているのがわかります。参考までにわたしの実行環境を出力します。
以上です。ご参考になれば幸いです。