Автоматическое преобразование CudaMat в Python - PullRequest
3 голосов
/ 18 июля 2011

Я пытаюсь ускорить мой код на Python, который является математической матрицей, с использованием некоторой формы CUDA. В настоящее время мой код использует Python и Numpy, поэтому кажется, что его не должно быть слишком сложно переписать его, используя что-то вроде PyCUDA или CudaMat.

Однако, с моей первой попытки использования CudaMat, я понял, что мне пришлось переставить множество уравнений, чтобы все операции выполнялись на GPU. Это включало создание многих временных переменных, чтобы я мог хранить результаты операций.

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

Пакету Theano удается это сделать, сначала создав символическое представление операций, а затем скомпилировав их в CUDA. Однако после того, как я немного опробовал Theano, я был разочарован тем, насколько непрозрачным было все. Например, просто получить фактическое значение для myvar.shape [0] сложно, так как дерево оценивается не намного позже. Я также предпочел бы меньше инфраструктуры, в которой мой код в значительной степени соответствует библиотеке, которая действует незаметно вместо Numpy.

Таким образом, то, что я действительно хотел бы, является чем-то намного более простым. Я не хочу автоматического дифференцирования (есть другие пакеты, такие как OpenOpt, которые могут сделать это, если мне это нужно) или оптимизации дерева, а просто преобразования из стандартной записи Numpy в CudaMat / PyCUDA / кое-что CUDA. На самом деле, я хочу, чтобы его можно было оценить просто как Numpy без кода CUDA для тестирования.

В настоящее время я думаю о том, чтобы написать это сам, но прежде чем даже подумать о таком предприятии, я хотел узнать, знает ли кто-нибудь еще о подобных проектах или о хорошей стартовой точке. Единственный известный мне проект, который может быть близок к этому, - это SymPy, но я не знаю, насколько легко было бы приспособиться к этой цели.

Моя текущая идея состоит в том, чтобы создать класс массива, который выглядел бы как класс Numpy.array. Единственная функция - построить дерево. В любой момент этот класс символьного массива можно преобразовать в класс массива Numpy и оценить (также может быть четность один к одному). Кроме того, класс массива может быть пройден и иметь команды CudaMat. Если требуются оптимизации, их можно выполнить на этом этапе (например, переупорядочение операций, создание временных переменных и т. Д.), Не мешая проверять происходящее.

Любые мысли / комментарии / и т.д. на это будет принята с благодарностью!

Обновление

Вариант использования может выглядеть примерно так (где sym - теоретический модуль), где мы можем делать что-то, например, вычислять градиент:

W = sym.array(np.rand(size=(numVisible, numHidden)))
delta_o = -(x - z)
delta_h = sym.dot(delta_o, W)*h*(1.0-h)
grad_W = sym.dot(X.T, delta_h)

В этом случае grad_W на самом деле будет просто деревом, содержащим операции, которые необходимо выполнить. Если вы хотите оценить выражение нормально (то есть через Numpy), вы можете сделать:

npGrad_W = grad_W.asNumpy()

, который будет просто выполнять команды Numpy, которые представляет дерево. С другой стороны, если вы хотите использовать CUDA, вы должны сделать:

cudaGrad_W = grad_W.asCUDA()

, который преобразует дерево в выражения, которые могут выполняться через CUDA (это может происходить несколькими способами).

Таким образом, должно быть тривиально: (1) проверить grad_W.asNumpy() == grad_W.asCUDA() и (2) преобразовать ваш ранее существующий код в CUDA.

1 Ответ

2 голосов
/ 01 августа 2011

Вы смотрели на часть GPUArray в PyCUDA?

http://documen.tician.de/pycuda/array.html

Хотя я сам не использовал ее, кажется, это то, что вы ищете.В частности, ознакомьтесь с разделом «Оценка пользовательских выражений за один проход» в нижней части этой страницы.

...