打開(kāi)網(wǎng)易新聞 查看精彩圖片

整理 | 華衛(wèi)、核子可樂(lè)

眾所周知,大語(yǔ)言模型(LLM)往往對(duì)硬件要求很高。近日,軟件工程師 Andrew Rossignol 成功在一臺(tái)“古董”老筆記本 PowerBook G4 上運(yùn)行了生成式 AI。

據(jù)了解,這臺(tái)筆記本已有 20 年歷史,僅配備 1.5 GHz PowerPC G4 處理器和 1 GB 內(nèi)存,但仍然順利跑起了 Meta 的 Llama 2 大模型推理任務(wù)。此番實(shí)驗(yàn)移植了開(kāi)源 llama2.c 項(xiàng)目,而后使用名為 AltiVec 的 PowerPC 矢量擴(kuò)展提升性能表現(xiàn)。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

在 PowerBook G4 上運(yùn)行 TinyStories 110M Llama 2 大模型推理任務(wù)。

Rossignol 在一篇博客里,完整介紹了關(guān)于此項(xiàng)目的所有過(guò)程和更多技術(shù)細(xì)節(jié)。以下是經(jīng)不改變?cè)獾姆g和整理后的博客原文:

1 另辟蹊徑,慢慢思考:在 PowerPC Mac 上運(yùn)行大模型

為舊硬件注入新生命永遠(yuǎn)是件令人心曠神怡的好事,也是我本人的愛(ài)好之一。讓現(xiàn)代軟件在幾十年前設(shè)計(jì)的系統(tǒng)上運(yùn)行起來(lái),對(duì)我總有種難以抗拒的吸引力。而在近年深入研究大語(yǔ)言模型(LLM)的過(guò)程中,這種沖動(dòng)也一直縈繞在我的腦海:能不能把 AI 的前沿技術(shù)引入自己那臺(tái)代表舊日榮光的 2005 款 PowerBook G4 中?借助一塊 1.5 GHz 處理器、整整 1 GB 的內(nèi)存和 32 位尋址空間,我開(kāi)始了實(shí)驗(yàn)并最終取得了成功。而通過(guò)在蘋(píng)果經(jīng)典筆記本電腦上跑起大模型推理,我們證明即使是陳舊的硬件也完全可以牽手代表未來(lái)的 AI 新成果。

我首先選擇了 Andrej Karpathy 的 llama2.c 項(xiàng)目——這個(gè)出色的項(xiàng)目?jī)H使用一個(gè) C 文件就實(shí)現(xiàn)了 Llama 2 大模型推理。其中沒(méi)有使用到任何加速器,性能完全靠項(xiàng)目的簡(jiǎn)單性實(shí)現(xiàn),也讓我找到了實(shí)現(xiàn)推理的基本思路。

我將其核心實(shí)現(xiàn)分叉成了名叫 ullm 的新項(xiàng)目。核心算法保持不變,但我花了一些時(shí)間對(duì)代碼做出改進(jìn),增強(qiáng)了其穩(wěn)健性。

2 代碼改進(jìn)

我從最基礎(chǔ)的改進(jìn)著手,陸續(xù)添加了系統(tǒng)函數(shù)的打包器,例如文件 I/O 和內(nèi)存分配機(jī)制,借此降低程序檢測(cè)難度。

  • 引入狀態(tài)返回,刪除所有 exit 調(diào)用。

  • 抽象文件訪問(wèn)以簡(jiǎn)化狀態(tài)處理。

  • 抽象 malloc/free 以進(jìn)行簡(jiǎn)單的調(diào)試 / 分析。

  • 將 512 字節(jié)靜態(tài) LUT 替換為單字符串。

  • 修復(fù)了使用 -Wall 編譯時(shí)的一些警告提示。

3 從庫(kù)入手

我把代碼組織成庫(kù)以便于大規(guī)模修復(fù),這套庫(kù)具有由標(biāo)頭公開(kāi)的公共 API,因此可以進(jìn)行單元測(cè)試、確保進(jìn)一步重構(gòu)不致破壞其推理功能。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

該庫(kù)需要兩條輸入:其一為 const config,負(fù)責(zé)提供模型路徑、rng seed 與 token 輸出回調(diào)等細(xì)節(jié)信息;其二則是 state,負(fù)責(zé)跟蹤加載權(quán)重、臨時(shí)緩沖區(qū)和 tokenizer 狀態(tài)等。

生成的 API 測(cè)試起來(lái)非常簡(jiǎn)單,并可輕松為其構(gòu)建命令行界面工具。

4 基于回調(diào)的輸出與測(cè)試

由于遷移至公共 API,因此我們可以輕松使用回調(diào)替換掉基于 printf 的輸出,這樣就能讓推理引擎持續(xù)生成 token。這也是后續(xù)實(shí)現(xiàn)端到端推理管道集成測(cè)試所必需的最后一條變更。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

5 內(nèi)部結(jié)構(gòu)

除了公共 API 之外,我還重新組織了其內(nèi)部結(jié)構(gòu)。在改進(jìn)之后,代碼變得相對(duì)優(yōu)雅,同時(shí)刪除了所有 exit 調(diào)用,以便在初始化或推理過(guò)程中失敗時(shí)進(jìn)行狀態(tài)傳播。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

6 移植到 PPC

為了適應(yīng)運(yùn)行 gcc 4.x(大家沒(méi)看錯(cuò))工具鏈的 PowerPC Mac,我還做了額外的調(diào)整。最核心的問(wèn)題就是 PowerPC 7447B CPU 為大端處理器,而如今發(fā)布的模型檢查點(diǎn)和標(biāo)記器則默認(rèn)使用小端處理器。在首次測(cè)試時(shí) malloc 達(dá)到 2 GB,明顯是出了問(wèn)題。從種種跡象來(lái)看,模型明顯是在從文件中讀取小端值。

  • 大小端:將模型檢查點(diǎn) / 標(biāo)記器從小端轉(zhuǎn)換為大端。

  • 對(duì)齊,16 字節(jié):將權(quán)重復(fù)制到內(nèi)存中,而非進(jìn)行內(nèi)存映射。

  • 性能:AltiVec。

在解決了錯(cuò)誤并完成上述結(jié)構(gòu)變更后,我使用 x86 Dell PowerEdge T440 主力機(jī)實(shí)現(xiàn)了輸出奇偶校驗(yàn)。

以下是我編寫(xiě)的,用于切換模型檢查點(diǎn)的粗略代碼:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

7 模型

Llama2.c 項(xiàng)目推薦使用 TinyStories 模型,而且理由非常充分。這些小模型無(wú)需任何專(zhuān)門(mén)的硬件加速,即可生成特定形式的輸出。

在實(shí)驗(yàn)中,我使用 15M 模型變體進(jìn)行了大部分測(cè)試,之后又切換到保真度最高的 110M 模型。這已經(jīng)是上限了,更大的模型要么 32 位尋址空間裝不下,要么在現(xiàn)有硬件的 CPU 和可用內(nèi)存帶寬上運(yùn)行速度太慢。

好消息是,這些模型確實(shí)能創(chuàng)作出不少異想天開(kāi)的兒童故事,讀起來(lái)那是相當(dāng)有趣。而由于體量相對(duì)較小,它們也讓我在調(diào)試架構(gòu)難題時(shí)感受相對(duì)輕松。

8 性能

為了在蘋(píng)果與戴爾硬件間直觀比較性能,我選擇啟用編譯器優(yōu)化(-O2)的單線程推理選項(xiàng)。

在單一英特爾至強(qiáng) Silver 4216 3.2 GHz 核心上運(yùn)行推理時(shí),其基準(zhǔn)性能結(jié)果如下:

I ullm.llama2: Complete: 6.91 token/s

real 0m26.511s

user 0m26.019s

sys 0m0.472s

可以看到,戴爾的成績(jī)是總用時(shí) 26.5 秒,每秒平均生成 6.91 個(gè) token(劇透:蘋(píng)果遠(yuǎn)遠(yuǎn)達(dá)不到這個(gè)水平)。其中 Inference seed 并非隨機(jī),所以生成的輸出結(jié)果在每輪運(yùn)行中均恒定不變,這就保證了多次運(yùn)行下的性能間可以直接比較。

好了,使用相同的代碼在 1.5 GHz PowerPC 7447B 處理器上運(yùn)行,PowerBook G4 到底取得了怎樣的成績(jī)?

I ullm.llama2: Complete: 0.77 token/s

real 4m0.099s

user 3m51.387s

sys 0m5.533s

雖然速度慢得多,但它仍然成功了!在與擁有更高內(nèi)存帶寬的現(xiàn)代 CPU 相比,PowerPC 的速度大約是其九分之一。老實(shí)講,居然能跟 15 年后的年輕計(jì)算機(jī)保持在同一性能數(shù)量級(jí)內(nèi),這真的令人印象深刻。

下面我們來(lái)看看耗費(fèi)時(shí)間最長(zhǎng)的函數(shù):matmul。控制結(jié)構(gòu)的核心在于嵌套循環(huán)與乘法 / 求和。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

那還能不能做得更好?我記得 PowerPC 處理器支持所謂 AltiVec 矢量擴(kuò)展,雖然早期版本的處理器擴(kuò)展比較有限,但確實(shí)包含一項(xiàng)可以加快速度的關(guān)鍵運(yùn)算:融合乘加。使用融合乘加運(yùn)算,處理器能夠執(zhí)行 4 倍的并行浮點(diǎn)乘法與加法,依靠 SIMD(單指令多數(shù)據(jù))語(yǔ)義實(shí)現(xiàn)加速。

以下是使用 AltiVec SIMD 擴(kuò)展重寫(xiě)的同一函數(shù)。請(qǐng)注意,這是我第一次編寫(xiě) AltiVec 代碼。在修復(fù)了 16 字節(jié)對(duì)齊問(wèn)題之后,此代碼能夠與原始 C 語(yǔ)言版本生成同樣的輸出。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

可以看到,這里實(shí)際上有 4 個(gè)并行求和,之后我在核心乘法求和循環(huán)結(jié)束時(shí)進(jìn)行了手動(dòng)求和。

如今網(wǎng)絡(luò)上幾乎找不到多少關(guān)于這個(gè)古老擴(kuò)展集的資料,好在 Gemini 給了我不少幫助。另外,官方提供的 PowerPC 文檔也還不錯(cuò),只是與舊版本的 ISA 并不完全匹配。

I ullm.llama2: Complete: 0.88 token/s

real 3m32.098s

user 3m23.535s

sys 0m5.368s

好極了!AltiVec 將推理過(guò)程縮短了約 30 秒,讓實(shí)現(xiàn)速度從戴爾的九分之一變成了八分之一,每秒生成的 token 數(shù)量則增加了 10%。爽!

9 后續(xù)探索

Llama2.c 項(xiàng)目還討論了如何使用相同代碼運(yùn)行具備數(shù)十億參數(shù)的模型。雖然頗具吸引力,但遺憾的是 G4 PowerPC 系統(tǒng)是 32 位的,因此最大可尋址內(nèi)存只有區(qū)區(qū) 4 GB,運(yùn)行模型體量的上限也就是這個(gè) 110M TinyStories 了。量化技術(shù)雖然有肥皂劇幫助,但模型檢查點(diǎn)仍然高達(dá) 7 GB(不量化則約為 26 GB),還是塞不進(jìn)可用地址空間。

所以我認(rèn)為這個(gè)項(xiàng)目可以到此結(jié)束了。在此過(guò)程中,我熟悉了大模型的性質(zhì)及其操作方式,也深切意識(shí)到矩陣乘法正是制約每秒輸出 token 數(shù)量的最大瓶頸。

所以還是讓我的老爺機(jī)做它該做的吧:一邊聽(tīng)歌一邊碼字,今天確實(shí)辛苦它了。

https://www.macrumors.com/2025/03/24/powerbook-g4-generative-ai/

http://www.theresistornetwork.com/2025/03/thinking-different-thinking-slowly-llms.html