Да, правильное параллельное сокращение необходимо для суммирования данных из нескольких потоков графического процессора в одну переменную.
Вот один тривиальный пример того, как это можно сделать из одного ядра:
$ cat t23.py
import math
def numba_example(number_of_maximum_loop,gs,ts,bs):
from numba import cuda
result = cuda.device_array([3,])
@cuda.jit(device=True)
def BesselJ0(x):
return math.sqrt(2/math.pi/x)
@cuda.jit
def cuda_kernel(number_of_maximum_loop,result,gs,ts,bs):
i = cuda.grid(1)
if i < number_of_maximum_loop:
cuda.atomic.add(result, 0, BesselJ0(i/100+gs))
cuda.atomic.add(result, 1, BesselJ0(i/100+ts))
cuda.atomic.add(result, 2, BesselJ0(i/100+bs))
# Configure the blocks
threadsperblock = 128
blockspergrid = (number_of_maximum_loop + (threadsperblock - 1)) // threadsperblock
# Start the kernel
init = [0.0,0.0,0.0]
result = cuda.to_device(init)
cuda_kernel[blockspergrid, threadsperblock](number_of_maximum_loop,result,gs,ts,bs)
return result.copy_to_host()
print(numba_example(1000,20,20,20))
$ python t23.py
[ 162.04299487 162.04299487 162.04299487]
$
Вы также можете сделать правильное уменьшение числа numba напрямую с помощью декоратора reduce
, как описано здесь , хотя я не уверен, что таким способом в одном ядре можно сделать 3 сокращения.
Наконец, вы можете написать обычное параллельное сокращение cuda, используя numba cuda, как указано здесь .Не должно быть трудным, я думаю, расширить это для выполнения 3 сокращений в одном ядре.
Эти 3 различных метода, вероятно, будут иметь различия в производительности, конечно.
В целом, если выВы задаетесь вопросом о расхождении результатов между моим кодом выше и вашим кодом на python в вопросе, я не могу это объяснить.Когда я запускаю ваш код на python, я получаю результаты, соответствующие коду numba cuda в моем ответе:
$ cat t24.py
import math
def numpy_example(number_of_maximum_loop,gs,ts,bs):
import numpy as np
result = np.zeros([3,])
def BesselJ0(x):
return math.sqrt(2/math.pi/x)
for i in range(number_of_maximum_loop):
result[0] += BesselJ0(i/100+gs)
result[1] += BesselJ0(i/100+ts)
result[2] += BesselJ0(i/100+bs)
return result
print(numpy_example(1000,20,20,20))
$ python t24.py
[ 162.04299487 162.04299487 162.04299487]
$