52.4_函数的相应修改
52.4 函数的相应修改
关于DeZero的“GPU化”,剩下的主要任务是修改DeZero的函数。这些具体的函数实际上是在forward方法中进行计算的,比如Sin类,其代码如下所示。
dezero/functions.py
class Sin(Function): def forward(self, x): y = np.sin(x) return y def backward(self, gy): x, = self.inputs gx = gy * cos(x) return gx代码中def forward(self, x):的参数x应为NumPy的ndarray实例。因此,我们可以对其使用np.sin(x)等NumPy的函数进行计算。如果想在
GPU上运行,参数x应为CuPy的ndarray实例。此时用cp.sin(x)来代替np.sin(x)。换言之,当x是NumPy时必须使用np.sin;当x是CuPy时必须使用cp.sin。基于以上内容,我们将Sin类修改如下。
dezero/functions.py
fromdezeroimport CUDA
class Sin(Functions): defforward(self,x): xp $=$ CUDA.get_array_module(x) $\mathbf{y} = \mathbf{x}\mathbf{p}.\sin (\mathbf{x})$ return y defbackward(self,gy): x, $=$ selfinputs gx $=$ gy\*cos(x) returngx上面的代码通过xp =uda.get_array_module(x)提取x对应的模块。代码中的xp可以是cp,也可以是np。之后使用xp进行计算。现在的Sin类在CPU/GPU(NumPy/CuPy)上都能正确运行。

这里只展示了 Sin 类的代码,但上面的修改需要应用于dezero/functions.py 中所有对应的地方。对应的地方指的是 np.xxX() 这种以 np. 开头的代码。我们要对这些地方执行与上面相同的修改。此外,还要对dezero/optimizers.py 和dezero/layers.py 执行同样的修改。
最后修改DeZero的四则运算的代码。具体来说,就是对dezero/core.py按如下内容进行修改。
dezero/core.py
def as_array(x, array_module=np):
if np.iscalar(x):
return array_module.array(x)
return xdef add(x0, x1):
x1 = as_array(x1,dezero.cuda.get_array_module(x0.data))
return Add()(x0, x1)
def mul(x0, x1):
x1 = as_array(x1,dezero.cuda.get_array_module(x0.data))
return Mul()(x0, x1)
# 对sub、rsub、div、rdiv进行同样的修改首先向as_array函数添加新的参数array_module。这个array_module的值为numpy或copy,函数将数据转换为array_module指定的模块的ndarray。然后使用这个新的as_array函数修改add和mul等四则运算函数。在add函数中使用as_array函数,是为了能够运行 这样的代码(x是Variable实例)。即使x.data是CuPy数据, 这样的代码也能正确运行。