# 2025-fyh-hw1 **Repository Path**: gpuap/2025-fyh-hw1 ## Basic Information - **Project Name**: 2025-fyh-hw1 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-25 - **Last Updated**: 2026-01-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 2025年秋季国科大《GPU架构与编程》大作业一 这是一个基于原生 CUDA C++ 实现高性能脉冲神经网络(SNN)推理项目。该项目专为 FashionMNIST 数据集设计,通过手动优化的 CUDA Kernels 实现了全脉冲神经网络的前向传播,包含卷积层(Conv)和全连接层(FC)的脉冲动力学模拟。 ## 主要特性 * **时间维度并行化 (Time-step Parallelism)**:在全连接层中,将时间步($T=8$)的循环完全展开为一次并行计算。利用寄存器数组同时累加所有时间步的突触电流,极大提升了指令级并行度(ILP),并避免了重复读取权重。 * **混合精度计算**:输入层使用 `Float`,中间层脉冲使用 `Int8` 存储,显著降低显存带宽压力。 * **PTX 汇编优化**:使用内联 PTX 汇编实现无分支(Branchless)的 LIF 神经元更新,避免 Warp Divergence。 * **向量化访存**:在全连接层利用 `float4` 和 `uchar4` 指令进行向量化读取,最大化内存吞吐。 --- ## 核心算子函数详解 (Kernel Explanations) 代码的核心在于几个高度优化的 CUDA 核函数,分别对应神经网络的不同组件: ### 1. `lif_update_ptx` (Device Function) * **作用**:Leaky Integrate-and-Fire (LIF) 神经元的物理模型实现。 * **原理**: * 负责累加膜电位 `v`,判断是否超过阈值(`THRESHOLD = 1.0f`)。 * 如果超过阈值,发放脉冲(返回 1.0)并重置电压;否则保持电压。 * **优化**:使用了 **内联 PTX 汇编 (Inline PTX Assembly)**。通过 `setp` (谓词设置) 和 `selp` (条件选择) 指令,替代了传统的 `if-else` 语句。这消除了 GPU 线程束(Warp)的分歧(Branch Divergence),显著提升了并行计算效率。 ### 2. `conv1_static_int8` * **层级**:第一层卷积 (Conv1)。 * **输入**:`Float` (原始图像) -> **输出**:`Int8` (脉冲序列)。 * **逻辑**: * 由于输入是静态图像,电流在 $T$ 个时间步内是恒定的。 * **优化**:Kernel 先计算一次卷积电流,然后在寄存器内循环 $T$ 次进行 LIF 累加。这避免了在每个时间步重复读取输入图像。 * 使用 Shared Memory 缓存卷积核权重。 ### 3. `conv2_dynamic_int8` * **层级**:第二层卷积 (Conv2)。 * **输入**:`Int8` (上一层脉冲) -> **输出**:`Int8` (脉冲序列)。 * **逻辑**: * 输入是随时间变化的脉冲信号(0 或 1),因此必须在时间步循环 $T$ 内部逐次计算卷积。 * **优化**:使用了 Shared Memory 缓存权重(`s_weight`),并针对 6x5x5 的卷积核进行了循环展开(Unroll)。 ### 4. `fc1_fast_vectorized` * **层级**:第一层全连接 (FC1)。 * **输入**:`Int8` -> **输出**:`Int8`。 * **逻辑**: * 将三维的特征图拉平并进行全连接计算。 * **优化 (核心亮点)**:使用了 **向量化读取** 和 **时间展开**。 * 利用 `reinterpret_cast` 一次性读取 4 个权重。 * 利用 `uchar4` 一次性读取 4 个输入脉冲值。 * **并行 T 计算**:在内部循环中,使用 `float sums[8]` 数组同时累加所有时间步的电流,随后再串行更新电压。 ### 5. `fc_shared_weights` (Template Kernel) * **层级**:FC2 和 FC3 层。 * **输入**:`Int8` -> **输出**:`Int8` (中间层) 或 `Float` (输出层)。 * **逻辑**:这是一个模板函数,通过 `IS_OUTPUT` 参数控制行为。 * **Shared Memory**:线程块协作将权重矩阵加载到共享内存中,减少对 Global Memory 的重复访问。 * **FC2 (`IS_OUTPUT=false`)**:执行 LIF 逻辑,输出 0/1 脉冲。 * **FC3 (`IS_OUTPUT=true`)**:作为最后一层,**不发放脉冲**。直接输出膜电位累加值(Float),用于分类判断。 ### 6. `argmax_kernel` * **层级**:后处理/分类层。 * **逻辑**: * 接收 FC3 输出的连续值。 * 在时间维度 $T$ 上对电压进行积分(求和)。 * 使用 Block 内规约(Reduction)找出 10 个类别中积分值最大的类别索引,作为最终预测结果。 --- ## 编译与运行 (Usage) ### 依赖 * NVIDIA GPU (Compute Capability >= 3.5) * CUDA Toolkit (10.0+) * C++ Compiler (C++11 standard) ### 编译命令 ```bash nvcc -O3 -std=c++11 -arch=sm_75 inference.cu -o snn_inference