回答編集履歴
2
説明の追記
test
CHANGED
@@ -20,9 +20,13 @@
|
|
20
20
|
|
21
21
|
|
22
22
|
|
23
|
+
number_of_maximum_loop = 10000
|
24
|
+
|
25
|
+
|
26
|
+
|
23
27
|
start = time.time()
|
24
28
|
|
25
|
-
count = np.sum(np.ones(
|
29
|
+
count = np.sum(np.ones(number_of_maximum_loop, dtype="int"))
|
26
30
|
|
27
31
|
elapsed_time = time.time() - start
|
28
32
|
|
@@ -43,6 +47,8 @@
|
|
43
47
|
は満たしてません
|
44
48
|
|
45
49
|
とりあえず、こう書けばエラーが出なくなります、というだけです
|
50
|
+
|
51
|
+
(注:【追記】に書いたように、データのサイズを大きくしたらCUDAとnumpyの速度が逆転しました)
|
46
52
|
|
47
53
|
|
48
54
|
|
@@ -80,6 +86,14 @@
|
|
80
86
|
|
81
87
|
|
82
88
|
|
89
|
+
result = cuda.to_device([0])
|
90
|
+
|
91
|
+
cuda_kernel[blockspergrid, threadsperblock](number_of_maximum_loop, result)
|
92
|
+
|
93
|
+
count = result.copy_to_host()[0]
|
94
|
+
|
95
|
+
# 1回目はコンパイルするため2回目を測定
|
96
|
+
|
83
97
|
start = time.time()
|
84
98
|
|
85
99
|
result = cuda.to_device([0])
|
@@ -108,6 +122,8 @@
|
|
108
122
|
|
109
123
|
```python
|
110
124
|
|
125
|
+
|
126
|
+
|
111
127
|
import numpy as np
|
112
128
|
|
113
129
|
from numba import cuda
|
@@ -124,9 +140,17 @@
|
|
124
140
|
|
125
141
|
|
126
142
|
|
143
|
+
number_of_maximum_loop = 10000
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
count = sum_reduce(np.ones(number_of_maximum_loop, dtype="int"))
|
148
|
+
|
149
|
+
# 1回目はコンパイルするため2回目を測定
|
150
|
+
|
127
151
|
start = time.time()
|
128
152
|
|
129
|
-
count = sum_reduce(np.ones(
|
153
|
+
count = sum_reduce(np.ones(number_of_maximum_loop, dtype="int"))
|
130
154
|
|
131
155
|
elapsed_time = time.time() - start
|
132
156
|
|
@@ -135,3 +159,37 @@
|
|
135
159
|
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
|
136
160
|
|
137
161
|
```
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
.
|
168
|
+
|
169
|
+
【追記】
|
170
|
+
|
171
|
+
Google ColabでGPUを有効にして確認したところ、
|
172
|
+
|
173
|
+
```python
|
174
|
+
|
175
|
+
number_of_maximum_loop = 10000
|
176
|
+
|
177
|
+
```
|
178
|
+
|
179
|
+
を
|
180
|
+
|
181
|
+
```python
|
182
|
+
|
183
|
+
number_of_maximum_loop = 1000000000
|
184
|
+
|
185
|
+
```
|
186
|
+
|
187
|
+
に変えたら、上記の一つ目のCUDAを用いたコードの速度はnumpyだけのコードの速度をやや上回りましたので、扱うデータのサイズが大きくなるとCUDAが有利になるようです
|
188
|
+
|
189
|
+
CUDAのコードを、回答の最初に提示したWebページに書かれてるような合算の高速化に対応させたものにすれば、さらにCUDAの方が有利になると思います (未確認)
|
190
|
+
|
191
|
+
ただし、「number_of_maximum_loop = 1000000000」の場合でも上記二つ目のCUDAを用いたコードはnumpyだけのコードよりもやや遅いです
|
192
|
+
|
193
|
+
もしかしたら、下記で指摘されてるバグが、まだ直ってないのかもしれません
|
194
|
+
|
195
|
+
[Numba CUDA vectorize and reduce decorators slower than expected #2266](https://github.com/numba/numba/issues/2266)
|
1
コード追加
test
CHANGED
@@ -2,13 +2,117 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
1万個の1を足すプログラム
|
5
|
+
を、「1万個の1を足すプログラム」と置き換えて、以下書きます
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
ただし、一つの変数に結果を合算するのは、
|
10
|
+
|
11
|
+
[CUDAで配列の総和を求めてみた](https://qiita.com/gyu-don/items/ef8a128fa24f6bddd342)
|
12
|
+
|
13
|
+
等に書かれてるように、CUDAで速度を出すために並列化するにはいろいろと工夫が要るケースで、この回答のCUDAを用いたコードはそこを頑張ってないので、
|
14
|
+
|
15
|
+
```python
|
16
|
+
|
17
|
+
import numpy as np
|
18
|
+
|
19
|
+
import time
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
start = time.time()
|
24
|
+
|
25
|
+
count = np.sum(np.ones(10000, dtype="int"))
|
26
|
+
|
27
|
+
elapsed_time = time.time() - start
|
28
|
+
|
29
|
+
print(count)
|
30
|
+
|
31
|
+
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
|
32
|
+
|
33
|
+
```
|
34
|
+
|
35
|
+
に速度で圧倒的に負けますので、
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
> numba for cudaを用いて高速化
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
は満たしてません
|
44
|
+
|
45
|
+
とりあえず、こう書けばエラーが出なくなります、というだけです
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
[numba cuda does not produce correct result with += (gpu reduction needed?)](https://stackoverflow.com/questions/53745701/numba-cuda-does-not-produce-correct-result-with-gpu-reduction-needed)
|
52
|
+
|
53
|
+
を参考にした、質問に掲載のエラーを回避したコード
|
54
|
+
|
55
|
+
```python
|
56
|
+
|
57
|
+
from numba import cuda
|
58
|
+
|
59
|
+
import time
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
@cuda.jit
|
64
|
+
|
65
|
+
def cuda_kernel(number_of_maximum_loop, result):
|
66
|
+
|
67
|
+
i = cuda.grid(1)
|
68
|
+
|
69
|
+
if i < number_of_maximum_loop:
|
70
|
+
|
71
|
+
cuda.atomic.add(result, 0, 1)
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
number_of_maximum_loop = 10000
|
76
|
+
|
77
|
+
threadsperblock = 1024
|
78
|
+
|
79
|
+
blockspergrid = (number_of_maximum_loop + (threadsperblock - 1)) // threadsperblock
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
start = time.time()
|
84
|
+
|
85
|
+
result = cuda.to_device([0])
|
86
|
+
|
87
|
+
cuda_kernel[blockspergrid, threadsperblock](number_of_maximum_loop, result)
|
88
|
+
|
89
|
+
count = result.copy_to_host()[0]
|
90
|
+
|
91
|
+
elapsed_time = time.time() - start
|
92
|
+
|
93
|
+
print(count)
|
94
|
+
|
95
|
+
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
|
96
|
+
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
.
|
104
|
+
|
105
|
+
[GPU Reduction](https://numba.pydata.org/numba-doc/dev/cuda/reduction.html)
|
106
|
+
|
107
|
+
を参考にしたコード
|
6
108
|
|
7
109
|
```python
|
8
110
|
|
9
111
|
import numpy as np
|
10
112
|
|
11
113
|
from numba import cuda
|
114
|
+
|
115
|
+
import time
|
12
116
|
|
13
117
|
|
14
118
|
|
@@ -20,22 +124,14 @@
|
|
20
124
|
|
21
125
|
|
22
126
|
|
127
|
+
start = time.time()
|
128
|
+
|
23
|
-
|
129
|
+
count = sum_reduce(np.ones(10000, dtype="int"))
|
130
|
+
|
131
|
+
elapsed_time = time.time() - start
|
132
|
+
|
133
|
+
print(count)
|
134
|
+
|
135
|
+
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
|
24
136
|
|
25
137
|
```
|
26
|
-
|
27
|
-
参考
|
28
|
-
|
29
|
-
[GPU Reduction](https://numba.pydata.org/numba-doc/dev/cuda/reduction.html)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
ただし、時間測ってないので、
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
> numba for cudaを用いて高速化
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
になってるかは不明
|