Я пытаюсь ускорить мой код на 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.