PyCUDA + Threading = Неверные дескрипторы при вызовах ядра - PullRequest
0 голосов
/ 07 мая 2011

Я постараюсь объяснить это;

У меня есть два класса;GPU(Object), для общего доступа к функциям графического процессора, и multifunc(threading.Thread) для конкретной функции, которую я пытаюсь использовать на нескольких устройствах.GPU содержит большую часть обработки "в первый раз", необходимую для всех последующих сценариев использования, поэтому multifunc вызывается из GPU с его экземпляром self, переданным в качестве аргумента __init__ (наряду с обычными очередями и тому подобным).

К сожалению, multifunc сжимается с:

File "/home/bolster/workspace/project/gpu.py", line 438, in run
    prepare(d_A,d_B,d_XTG,offset,grid=N_grid,block=N_block)
  File "/usr/local/lib/python2.7/dist-packages/pycuda-0.94.2-py2.7-linux-x86_64.egg/pycuda/driver.py", line 158, in function_call
    func.set_block_shape(*block)
LogicError: cuFuncSetBlockShape failed: invalid handle

Первым портом захода были, конечно, размеры блока, но они находятся в пределах диапазона (такое же поведение, даже если я принудительно block=(1,1,1), аналогично grid.

По сути, в multifunc все обычные функции CUDA memalloc и т. Д. Работают нормально (подразумевается, что это не является проблемой контекста). Так что проблема должна быть в SourceModule ingсама функция ядра.

У меня есть шаблон ядра, содержащий весь мой код CUDA, который имеет файловую область, и шаблонирование выполняется с jinja2 при инициализации GPU. Независимо от того, преобразован ли этот шаблонный объект вSourceModule объект в GPU и переданный в multifunc, или, если его преобразовать в multifunc, происходит то же самое.

Google был в значительной степени бесполезен для этой частиЭто специфическая проблема, но после стека я предполагаю, что упоминаемый Invalid Handle является дескриптором функции ядра, а не чем-то странным, что происходит с размерами блока.

Я знаю, что это очень важный момент.ситуация, но я уверен, что кто-то может увидеть проблему, которую я пропустил.

Ответы [ 2 ]

3 голосов
/ 07 мая 2011

Причина заключается в контекстной близости.Каждый экземпляр функции CUDA привязан к контексту и не является переносимым (то же самое относится к выделению памяти и ссылкам на текстуры).Таким образом, каждый контекст должен загружать экземпляр функции отдельно, а затем использовать дескриптор функции, возвращаемый этой операцией загрузки.

Если вы вообще не используете метапрограммирование, вам может оказаться проще скомпилировать код CUDA в кубинфайл, а затем загрузите нужные функции из кубина в каждый контекст с помощью driver.module_from_file.Вырезание и вставка непосредственно из моего производственного кода:

# Context establishment
try:
    if (autoinit):
        import pycuda.autoinit
        self.context = None
        self.device = pycuda.autoinit.device
        self.computecc = self.device.compute_capability()
    else:
        driver.init()
        self.context = tools.make_default_context()
        self.device = self.context.get_device()
        self.computecc = self.device.compute_capability()

    # GPU code initialization
    # load pre compiled CUDA code from cubin file
    # Select the cubin based on the supplied dtype
    # cubin names contain C++ mangling because of
    # templating. Ugly but no easy way around it
    if self.computecc == (1,3):
        self.fimcubin = "fim_sm13.cubin"
    elif self.computecc[0] == 2:
        self.fimcubin = "fim_sm20.cubin"
    else:
        raise NotImplementedError("GPU architecture not supported")

    fimmod = driver.module_from_file(self.fimcubin)

    IterateName32 = "_Z10fimIterateIfLj8EEvPKT_PKiPS0_PiS0_S0_S0_jjji"
    IterateName64 = "_Z10fimIterateIdLj8EEvPKT_PKiPS0_PiS0_S0_S0_jjji"

    if (self.dtype == np.float32):
        IterateName = IterateName32
    elif (self.dtype == np.float64):
        IterateName = IterateName64
    else:
        raise TypeError

    self.fimIterate = fimmod.get_function(IterateName)

except ImportError:
    warn("Could not initialise CUDA context")
0 голосов
/ 07 мая 2011

Типовое; как только я напишу вопрос, я решу его.

Проблема в том, что SourceModule работал вне активного контекста. Чтобы исправить это, я переместил вызов SourceModule в функцию run в потоке под настройкой контекста cuda. ​​

Оставим это на некоторое время, потому что я уверен, что у кого-то есть лучшее объяснение!

...