1を1万回足すプログラム
を、「1万個の1を足すプログラム」と置き換えて、以下書きます
ただし、一つの変数に結果を合算するのは、
CUDAで配列の総和を求めてみた
等に書かれてるように、CUDAで速度を出すために並列化するにはいろいろと工夫が要るケースで、この回答のCUDAを用いたコードはそこを頑張ってないので、
python
1import numpy as np
2import time
3
4number_of_maximum_loop = 10000
5
6start = time.time()
7count = np.sum(np.ones(number_of_maximum_loop, dtype="int"))
8elapsed_time = time.time() - start
9print(count)
10print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
に速度で圧倒的に負けますので、
numba for cudaを用いて高速化
は満たしてません
とりあえず、こう書けばエラーが出なくなります、というだけです
(注:【追記】に書いたように、データのサイズを大きくしたらCUDAとnumpyの速度が逆転しました)
numba cuda does not produce correct result with += (gpu reduction needed?)
を参考にした、質問に掲載のエラーを回避したコード
python
1from numba import cuda
2import time
3
4@cuda.jit
5def cuda_kernel(number_of_maximum_loop, result):
6 i = cuda.grid(1)
7 if i < number_of_maximum_loop:
8 cuda.atomic.add(result, 0, 1)
9
10number_of_maximum_loop = 10000
11threadsperblock = 1024
12blockspergrid = (number_of_maximum_loop + (threadsperblock - 1)) // threadsperblock
13
14result = cuda.to_device([0])
15cuda_kernel[blockspergrid, threadsperblock](number_of_maximum_loop, result)
16count = result.copy_to_host()[0]
17# 1回目はコンパイルするため2回目を測定
18start = time.time()
19result = cuda.to_device([0])
20cuda_kernel[blockspergrid, threadsperblock](number_of_maximum_loop, result)
21count = result.copy_to_host()[0]
22elapsed_time = time.time() - start
23print(count)
24print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
.
GPU Reduction
を参考にしたコード
python
1
2import numpy as np
3from numba import cuda
4import time
5
6@cuda.reduce
7def sum_reduce(a, b):
8 return a + b
9
10number_of_maximum_loop = 10000
11
12count = sum_reduce(np.ones(number_of_maximum_loop, dtype="int"))
13# 1回目はコンパイルするため2回目を測定
14start = time.time()
15count = sum_reduce(np.ones(number_of_maximum_loop, dtype="int"))
16elapsed_time = time.time() - start
17print(count)
18print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
.
【追記】
Google ColabでGPUを有効にして確認したところ、
python
1number_of_maximum_loop = 10000
を
python
1number_of_maximum_loop = 1000000000
に変えたら、上記の一つ目のCUDAを用いたコードの速度はnumpyだけのコードの速度をやや上回りましたので、扱うデータのサイズが大きくなるとCUDAが有利になるようです
CUDAのコードを、回答の最初に提示したWebページに書かれてるような合算の高速化に対応させたものにすれば、さらにCUDAの方が有利になると思います (未確認)
ただし、「number_of_maximum_loop = 1000000000」の場合でも上記二つ目のCUDAを用いたコードはnumpyだけのコードよりもやや遅いです
もしかしたら、下記で指摘されてるバグが、まだ直ってないのかもしれません
Numba CUDA vectorize and reduce decorators slower than expected #2266