支持:
计算图由表示各种操作的节点构建,如矩阵乘法、元素级操作和激活函数。所有操作都使用CUDA核函数实现,以便在NVIDIA GPU上并行执行。
enum OpType: 定义操作类型枚举,包括输入、加法、减法、乘法、除法、矩阵乘法和各种激活函数。
xxxxxxxxxxstruct ComputeNode
: 计算图节点结构体,包含操作类型、前向传播值、梯度值和输入节点列表。
ComputeNode(int rows, int cols, int batch = 1): 构造函数,初始化节点的维度和批处理大小。~ComputeNode(): 析构函数,防止内存泄漏。zeroGrad(): 重置节点的梯度为零。reluForwardKernel: 实现ReLU前向传播,对输入大于0的部分保持不变,小于0的部分置为0。reluBackwardKernel: 实现ReLU反向传播,对输入大于0的部分传递梯度,小于0的部分梯度置为0。sigmoidForwardKernel: 实现Sigmoid前向传播,计算1/(1+e^(-x))。sigmoidBackwardKernel: 实现Sigmoid反向传播,计算梯度:output * (1 - output) * 输出梯度。matmulForwardKernel: 实现矩阵乘法前向传播,计算C = A * B。matmulBackwardAKernel: 实现矩阵乘法对输入A的反向传播,计算A的梯度。matmulBackwardBKernel: 实现矩阵乘法对输入B的反向传播,计算B的梯度。negGradKernel: 辅助核函数,用于计算负梯度(减法操作中使用)。mulBackwardKernel: 实现元素级乘法的反向传播,计算两个输入的梯度。divBackwardKernel: 实现元素级除法的反向传播,计算两个输入的梯度。addBackwardCUDA: 实现加法操作的反向传播,直接将输出梯度复制到两个输入的梯度中。subBackwardCUDA: 实现减法操作的反向传播,对第一个输入直接传递梯度,对第二个输入传递负梯度。mulBackwardCUDA: 实现元素级乘法操作的反向传播,调用相应的CUDA核函数。divBackwardCUDA: 实现元素级除法操作的反向传播,调用相应的CUDA核函数。matrixMatMulCPU: CPU版本的矩阵乘法(用于验证CUDA实现的正确性)。class ComputeGraph: 计算图管理类,提供以下方法:
~ComputeGraph(): 析构函数,释放所有节点的内存。addInput(int rows, int cols, int batchSize = 1): 添加输入节点。addAdd(ComputeNode* a, ComputeNode* b): 添加加法节点。addSub(ComputeNode* a, ComputeNode* b): 添加减法节点。addMul(ComputeNode* a, ComputeNode* b): 添加元素级乘法节点。addDiv(ComputeNode* a, ComputeNode* b): 添加元素级除法节点。addMatMul(ComputeNode* a, ComputeNode* b): 添加矩阵乘法节点。addReLU(ComputeNode* input): 添加ReLU激活函数节点。addSigmoid(ComputeNode* input): 添加Sigmoid激活函数节点。forward(): 执行前向传播,按照拓扑排序依次计算每个节点的值。backward(ComputeNode* outputNode): 执行反向传播,计算每个节点的梯度,从输出节点开始向输入节点传播。main(): 示例程序入口点,演示如何使用计算图框架:
reluForwardKernel: 对输入数据应用ReLU激活函数(max(0,x)),每个线程处理一个元素。reluBackwardKernel: 计算ReLU的梯度,当输入大于0时梯度为上游梯度,否则为0。sigmoidForwardKernel: 计算Sigmoid激活函数(1/(1+e^(-x))),每个线程处理一个元素。sigmoidBackwardKernel: 计算Sigmoid的梯度,公式为out_grad * sigmoid(x) * (1-sigmoid(x))。matmulForwardKernel: 实现矩阵乘法,每个线程负责计算结果矩阵中的一个元素。matmulBackwardAKernel: 计算矩阵乘法关于第一个输入矩阵的梯度,实现了dL/dA的计算。matmulBackwardBKernel: 计算矩阵乘法关于第二个输入矩阵的梯度,实现了dL/dB的计算。negGradKernel: 计算负梯度,用于减法操作的反向传播。mulBackwardKernel: 计算元素级乘法的梯度,对A的梯度为Bout_grad,对B的梯度为Aout_grad。divBackwardKernel: 计算元素级除法的梯度,对A的梯度为out_grad/B,对B的梯度为-A*out_grad/(B²)。addBackwardCUDA: 实现加法操作的梯度计算,由于加法的性质,输出梯度会直接传递给两个输入。subBackwardCUDA: 实现减法操作的梯度计算,第一个输入接收正梯度,第二个输入接收负梯度。mulBackwardCUDA: 封装元素级乘法的CUDA核函数调用,管理内存分配和传输。divBackwardCUDA: 封装元素级除法的CUDA核函数调用,管理内存分配和传输。matrixMatMulCPU: 在CPU上实现矩阵乘法,用于验证CUDA实现的正确性。~ComputeGraph(): 析构函数,负责释放所有节点占用的内存,防止内存泄漏。addInput, addAdd, addSub, addMul, addDiv, addMatMul, addReLU, addSigmoid: 这些方法用于创建不同类型的计算节点并添加到计算图中。每个方法创建一个特定类型的节点,设置其操作类型和输入节点,并将节点添加到图中。forward(): 按照拓扑排序顺序执行前向传播。对于每个节点,根据其操作类型调用相应的CUDA函数计算其值。backward(ComputeNode* outputNode): 执行反向传播。首先重置所有节点的梯度,然后从输出节点开始,按照拓扑排序的逆序计算每个节点的输入梯度。每种操作类型都有特定的反向传播逻辑。main(): 演示如何使用计算图框架构建和训练简单的神经网络模型:
完整代码:
https://github.com/AllenZYJ/Edge-Computing-Engine/blob/master/cuda_mat/mat_grad.cu