Ниже приведен пример кода, использующего pycuda с включенным в него кодом «ядро» (с SourceModule
)
import pycuda
import pycuda.driver as cuda
from pycuda.compiler import SourceModule
import threading
import numpy
class GPUThread(threading.Thread):
def __init__(self, number, some_array):
threading.Thread.__init__(self)
self.number = number
self.some_array = some_array
def run(self):
self.dev = cuda.Device(self.number)
self.ctx = self.dev.make_context()
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
cuda.memcpy_htod(self.array_gpu, some_array)
test_kernel(self.array_gpu)
print "successful exit from thread %d" % self.number
self.ctx.pop()
del self.array_gpu
del self.ctx
def test_kernel(input_array_gpu):
mod = SourceModule("""
__global__ void f(float * out, float * in)
{
int idx = threadIdx.x;
out[idx] = in[idx] + 6;
}
""")
func = mod.get_function("f")
output_array = numpy.zeros((1,512))
output_array_gpu = cuda.mem_alloc(output_array.nbytes)
func(output_array_gpu,
input_array_gpu,
block=(512,1,1))
cuda.memcpy_dtoh(output_array, output_array_gpu)
return output_array
cuda.init()
some_array = numpy.ones((1,512), dtype=numpy.float32)
num = cuda.Device.count()
gpu_thread_list = []
for i in range(num):
gpu_thread = GPUThread(i, some_array)
gpu_thread.start()
gpu_thread_list.append(gpu_thread)
Я хотел бы использовать тот же метод, но вместо использования "код ядра ", я хотел бы сделать несколько вызовов функции, которая является внешней (не такой, как" код ядра "), то есть классическая функция, определенная в моей основной программе и которая принимает в качестве аргумента различные параметры, общие для всей основной программы,Возможно ли это?
Люди, которые практиковали Matlab
, могут знать функцию arrayfun
, где B = arrayfun(func,A)
- это вектор результатов, полученный путем применения функции func
для каждого элемента вектора A
.
На самом деле, это версия того, что обычно называют функцией map
: я хотел бы сделать то же самое, но с версией для графического процессора / Pycuda.
Если кто-то может дать какой-то совет или информациюДля выполнения этих нескольких вызовов версии GPU, я был бы признателен.
ОБНОВЛЕНИЕ 1 : Извините, я забыл в начале своего поста сказать, что я называю внешней и классической функцией.Ниже приведен пример функции, которая используется в главном разделе:
def integ(I1):
function_A = aux_fun_LU(way, ecs, I1[0], I1[1])
integrale_A = 0.25*delta_x*delta_y*np.sum(function_A[0:-1, 0:-1] + function_A[1:, 0:-1] + function_A[0:-1, 1:] + function_A[1:, 1:])
def g():
for j in range(6*i, 6*i+6):
for l in range(j, 6*i+6):
yield j, l
## applied integ function to g() generator.
## Here I a using simple map function (no parallelization)
if __name__ == '__main__':
map(integ, g())
ОБНОВЛЕНИЕ 2: Возможно, решением было бы вызвать функцию extern из кода ядра, что также принесет пользувысокой мощности графического процессора множественных вызовов кода ядра.Но как справиться с возвращенным значением этой внешней функции, чтобы вернуть его в основную программу?
ОБНОВЛЕНИЕ 3: Ниже приведено то, что я пробовал,
# Class GPUThread
class GPUThread(threading.Thread):
def __init__(self, number, some_array):
threading.Thread.__init__(self)
self.number = number
self.some_array = some_array
def run(self):
self.dev = cuda.Device(self.number)
self.ctx = self.dev.make_context()
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
cuda.memcpy_htod(self.array_gpu, some_array)
test_kernel(self.array_gpu)
print "successful exit from thread %d" % self.number
self.ctx.pop()
del self.array_gpu
del self.ctx
def test_kernel(input_array_gpu):
mod1 = SourceModule("""
__device__ void integ1(int *I1)
{
function_A = aux_fun_LU(way, ecs, I1[0], I1[1]);
integrale_A = 0.25*delta_x*delta_y*np.sum(function_A[0:-1, 0:-1] + function_A[1:, 0:-1] + function_A[0:-1, 1:] + function_A[1:, 1:]);
}""")
func1 = mod1.get_function("integ1")
# Calling function
func1(input_array_gpu)
# Define couples (i,j) to build Fisher matrix
def g1():
for j in range(6*i, 6*i+6):
for l in range(j, 6*i+6):
yield j, l
# Cuda init
if __name__ == '__main__':
cuda.init()
# Input gTotal lists
some_array1 = np.array(list(g1()))
print 'some_array1 = ', some_array1
# Parameters for cuda
num = cuda.Device.count()
gpu_thread_list = []
for i in range(num):
gpu_thread = GPUThread(i, some_array1)
#gpu_thread = GPUThread(i, eval("some_array"+str(j)))
gpu_thread.start()
gpu_thread_list.append(gpu_thread)
Я получаю следующую ошибку при выполнении:
`Traceback (most recent call last):
File "/Users/mike/anaconda2/envs/py2cuda/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "Example_GPU.py", line 1232, in run
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
NameError: global name 'some_array' is not defined`
Я не вижу, что не так с переменной 'some_array' и строкой self.array_gpu = cuda.mem_alloc(some_array.nbytes)
Любой может увидеть ошибку?спасибо