Python中的CudaMat自动转换

3 投票
1 回答
931 浏览
提问于 2025-04-16 21:46

我正在考虑如何加速我的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

你有没有看过PyCUDA里的GPUArray部分?

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

虽然我自己没有用过,但看起来这正是你需要的。特别是,看看页面底部的“单次自定义表达式评估”那一节。

撰写回答