CUDA / pycuda - Реализовать графическую функцию GPU для классической функции с вектором параметров - PullRequest
0 голосов
/ 06 февраля 2019

Ниже приведен пример кода, использующего 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)

Любой может увидеть ошибку?спасибо

...