@maxxfuu: 推理工程第13/90天 我用C语言构建了一个MNIST分类器。并不为此骄傲,但够坦率说出来。它花了我5……
摘要
作者分享了用C语言构建MNIST分类器的经历,强调理解基础比编码更重要,并解释了一维向量矩阵乘法的直觉。
查看缓存全文
缓存时间: 2026/07/20 17:31
推理工程第13/90天
我用C语言写了一个MNIST分类器。
没什么好骄傲的,但我足够坦诚。我花了整整5天才完全理解并掌握1D向量矩阵乘法的直觉。
它只是三个嵌套的for循环,但不知为何,就是没开窍。完全反直觉。以下是我希望一开始就知道的一些事情。
实际上,我认为有时把东西画出来,创建不同的可视化,并与语言模型对话来建立理解,如果方法得当,会有很大帮助。
我花了大约6个小时追踪代码、绘制数据流、预测形状、理解数学原理。这些都不需要写任何代码。一旦我完全理解了MNIST的流程,写代码就快得惊人。用C实现MNIST大约用了1小时,而理解一切用了6小时。
从心态上讲,我认为学习深度学习确实是一个不同的游戏。从全栈工程的角度来看,构建稳健的后端和优雅的前端几乎有一本现成的“手册”。我发现直接投入实践、边做边学比阅读文档更能教会你东西。
然而,学习推理、CUDA以及构建像MNIST这样的简单项目,与全栈工程完全不同。理解某些东西为什么有效、并建立直觉是一个巨大的障碍。往前走,我肯定会把“token”花在理解基本原理上,而不是写代码上。
在技术方面,以下是让我对matmul_forward()的三重for循环实现豁然开朗的直觉!由于矩阵是以1D向量的形式存在,选择正确的单元格就是弄清楚三个索引变量中哪个对应步进(step)、步幅(stride)和固定点(pin)。
这不是正式的术语,但很有道理。
步进是你移动的轴。它可以是行方向或列方向。向哪个方向移动由固定点决定。步幅是你在1D数组上每一步跳过的距离。
看一下动画中的B[l*k + j]。固定点是j,它将你固定在一列上,因此唯一的自由变量是步进l。迭代沿着该列从上到下流动。由于B存放在一个1D数组中,“向下移动一行”并不是移动一个单元格,而是移动一个完整的步幅,即行的宽度k。
虽然哪个变量扮演步幅、固定点和步进完全取决于for循环的结构,但我已经能够使用这个框架来概括矩阵乘法的各种变体。
从明天开始,我就能用CUDA重写这段C代码了!
相似文章
@maxxfuu: 推理工程第6/90天 我写了一个用于一维卷积的CUDA内核,只是为了练习写未优化的……
一位开发者分享了他们在推理工程的第6天,编写了一个用于一维卷积的CUDA内核,解释了PagedAttention的内存效率,并概述了GPU内存层次结构(全局、寄存器、本地、常量、共享)。
@sumitdotml: 2026年第25周:C语言中CPU张量核心基础(加法/乘法、归约、步长、2D矩阵乘法等),阅读Arcee的一些内容
作者分享了用C语言构建纯CPU张量库的进展,涵盖了加法/乘法、归约、步长和2D矩阵乘法等基础知识,以及从阅读Arcee关于基础模型的技术博客中获得的见解。
@harshbhatt7585: https://x.com/harshbhatt7585/status/2063593933314113587
作者分享了从头训练一个160M参数大语言模型的经验,尝试了多种架构,如多Token预测和分层推理模型。他强调快速迭代、简化思路以及理解架构有效原因的重要性。
@DivyanshT91162: Andrej Karpathy 的整个声誉都建立在一个理念上:"只有当你从头开始构建它时,你才真正理解它…"
一条 Twitter 帖子讨论了 Andrej Karpathy 教学理念的讽刺之处——通过从头构建来学习——而现在他却在用 AI 编程,并分享了一段为期 3 周的学习历程,使用 Claude Opus 4.8 以老派方式掌握深度学习。
@0x0SojalSec:想要在AI/ML领域真正脱颖而出,不仅仅是使用工具,而是理解并改进它们?理解为什么梯度下降…
一条推文,推广了一份精心整理的数学与深度学习资源合集,旨在帮助理解像Claude这样的模型背后的基础,包括线性代数、实分析、优化和表示论。