正如读者所料,EXO 轻而易举地从 eBay 上买到了一台旧的 Windows 98 PC 作为该项目的基础,硬件有了,但仍有许多障碍需要克服。EXO 解释说,将数据导入旧硬盘就是一项巨大的挑战,因此他们只能使用老式 FTP(good old FTP)通过这台古老机器的以太网端口进行文件传输。
然而,更大的挑战是让 Windows 98 编译现代代码。好在 EXO 找到了 Andrej Karpathy 的 llama2.c 项目。借助此资源和旧的 Borland C++ 5.02 IDE 和编译器(加上一些小调整),可以将代码制作成与 Windows 98 兼容的可执行文件并运行。
代码已经开源。
项目地址:https://github.com/exo-explore/llama98.c
在 Windows 98 下编译现代代码非常棘手。我们首先尝试了 mingw,据说它可以为 Windows 98/Pentium II 编译现代 C++。结果却走入了死胡同 — 可能是由于 CMOV 指令不支持奔腾 Pro 之前的版本。
于是,我们采用了老式的方法:Borland C++ 5.02 是一款有 26 年历史的集成开发环境和编译器,可直接在 Windows 98 上运行。唯一的问题是它支持的是非常老的 C/C++ 版本。现代 C++ 是不可能的,但几十年来 C 语言的变化却少得惊人。C 语言最大的变化是在 1999 年(C99),所以很遗憾我们错过了。旧版 C 的主要限制是不能「随处声明」变量,所有变量都必须在函数的开始部分声明。
Borland C++ 5.02,一款有 26 年历史的集成开发环境,仍然能够完成任务。
Karpathy 救场
这让我们想到了 Andrej Karpathy 的 llama2.c:700 行纯 C 语言,可以在具有 Llama 2 架构的模型上运行推理。非常完美,但为了在奔腾 II 上运行 Win98,它仍然需要一些调整:
用「DLONGWORD」代替「long long」(使用类型定义);
将所有变量声明移至函数起始处;
简化了从磁盘到内存的加载(内存映射会导致 SEGFAULTS);
通过用 GetTickCount () 代替 clock_gettime 修复了时间戳问题。
本项目的代码可在 GitHub 上的 llama98.c 获取。
成功!在 Windows 98 上运行的 260K 参数 Llama 模型生成了一个关于 Sleepy Joe 的故事。
结果
终于让它工作了!以下是我们实现的结果,完全在 Pentium II CPU 上运行,无需 GPU:
Llama 3.2 1B 的结果是基于运行适合内存的模型碎片的基准测试和磁盘读取基准测试得出的。Llama98.c 正在通过卸载功能进行扩展,以运行更大的模型来进行实际测试。
虽然没有达到 ChatGPT 的速度,但让任何现代人工智能模型在二十多年前的 CPU 硬件上运行,都是朝着我们的使命迈出的重要一步。在此特别感谢 Chris Wellons 关于如何在 Windows 98 上运行 C++ 的精彩博文。