Python
LINPACK
CuPy

pythonでlinpackしてみる


linpackをpythonで書いてみる


概要

過去何度かスーパーコンピュータの性能を示すbenchmarkの一つlinpackを手元で試してみようという記事を書いた。

なんどもlinpackと書いているが、実際のところ、linpackが何をしているかよく理解していない。

そのため、pythonでlinpackを書いてみて、何をしているか把握しようと考えた。


linpackとは

linpackは要は、n×n の線型方程式系 Ax = b を解く(xを求める)プログラムらしい。

アルゴリズム的な話をこちらの資料を参考にした。

pythonで実装がないかと調べた見たところ、

資料が見つかった。


pythonで解いてみる。

numpyで解く場合要は、

import numpy as np

n = 100
A = np.random.rand(n, n)
b = np.random.rand(n, 1)
x = np.linalg.solve(A, b)

と解いているということらしい。

上で紹介したこの資料を参考にプログラムを書いてみた。

プログラムは、こちらの githubにあげている。

ちゃんと意味はわかっておらず、ベンチマーク本体は、np.linalg.solve(A, b) で下の、r0 = cn.linalg.norm(r, cn.inf) は検算なのだろう。

手元のマシンで、nの数値を、10000にして、大体20Gflops/Secくらい出たので、それっぽいかなと感じた。


cuda(cupy) を使う

GPUを使うと早いらしいので、NVIDAのGPUを使って演算出来ないか試してみた。pythonには、CUDAをnumpyライクに扱う CuPy がありそちらを使って演算してみる。手元にcudaの動くマシンは無かったので、GCPのGCEインスタンスのGPU(P100)をアタッチして試した。

cupynumpy と互換性があるようで、以下のように書き換えれば動いた

import cupy as cu

n = 100
A = cu.random.rand(n, n)
b = cu.random.rand(n, 1)
x = cu.linalg.solve(A, b)

nvida-smi を見るときちんと動いているようだった。

15000次元で、テストしたところ。

Linpack benchmark 532.0809 GFlops/Sec とあり、 532Gflops 出たようだ(数値は怪しいのであまり鵜呑みにしないでください)。数値は怪しいが、少なくとも、numpyで動かしたときよりは早かった。

また、numpyでも試した。わかったことは、numpyもcpuがあれば並列で動くようだ。


cuda(cupy) を単精度で使う

上の、cupyを使った際に、a = cn.random.rand(n, n).astype(cn.float) を指定した。numpyは、floatを指定すると、倍精度(float64)が指定されるそうだ。cudaなどのgpuはfloat32の方が性能が出るので、a = cn.random.rand(n, n).astype(cn.float32);float32を明示して単精度で演算してみた。

そうすると、25000次元で解くことが出来て、計算速度も、 1110.7489 GFlops/Sec と1Tflopsを超えた(数値的に怪しいので鵜呑みにしないでください。ただ、上記プログラムより早かったです)。

ちなみに、numpy(CPU)()でやる場合、8CPUで Linpack benchmark 81.1896 GFlops/Sec81.1896GFlops であった。大体、13倍くらい早い。


まとめ


  • スパコンで使われるlinpackが一体何をしているか分からなかったので、pythonで書いてどういうものか見てみた。

  • numpyだと Ax=b を解くのは、 x = np.linalg.solve(A, b) とすれば良いようだ。これで、スパコンがやっている演算と 基本的 には同じ事ができる。

  • ついでにcupyも試してみた。GPUを使うと早くなるようだ。