code window

2024年4月30日星期二

Llamafile: 專為大模型設計的推論框架(二)

隨著 ChatGPT、BERT 等大型語言模型在自然語言處理領域掀起巨大波瀾,AI 技術正以前所未有的速度走近大眾生活。然而,這些 LLM 的訓練和推論對計算資源提出了極高要求,動輒數十甚至數百 GB 的模型體積也給分發和部署帶來諸多不便。為了讓 LLM 真正為更多人所用,我們不僅需要更強大的硬體和演算法,還需要打造全新的工具鏈和基礎設施。

正是基於這一考慮,Mozilla 創新團隊於去年底發布了 llamafile 專案。透過巧妙結合 llama.cpp 和 Cosmopolitan Libc 兩大開源專案,llamafile 可將 LLM 權重檔案直接轉換為可執行檔,讓使用者無需編程即可在多種環境一鍵部署 AI 服務。自首發以來,在社群開發者的積極參與下,llamafile 迭代了多個重大版本,新增了一系列振奮人心的特性,有力推動了 LLM 技術的普及。本文將深入剖析 llamafile 的設計理念和關鍵實現,探討其在 LLM 工程化中的重要意義。

LLM 部署的技術挑戰

隨著 Transformer 等新架構的發明,LLM 的參數規模和計算開銷呈指數級增長。以 GPT-3 為例,其參數量高達 1750 億,訓練時使用了多達 10000 個 GPU,耗費了數百萬美元的算力成本。即便是在推論階段,為了獲得最佳的回應速度,仍然需要 TB 量級顯存的支援。這對絕大多數潛在使用者而言是難以企及的。

為了降低准入門檻,LLM 的開發者們開始探索各種優化技術,包括:

- 模型蒸餾:將大模型的知識提煉到小模型中,在保留核心能力的同時大幅減少參數量。 

- 量化感知訓練:透過低位元表示權重,在犧牲部分精度的前提下顯著降低儲存和頻寬佔用。

- 稀疏注意力:利用注意力矩陣的稀疏特性,避免計算無關 Token 之間的相關度,節省算力。

經過這些優化,LLM 的體積得以大幅壓縮,如今流行的開源模型如 LLaMA 和 GPT-J 的體積已降至百 GB 以下,資源佔用也在業餘愛好者可接受的範圍內。但與此同時,模型檔案格式也呈現出多樣化的趨勢。由於缺乏統一的標準,不同的模型在權重儲存方式上存在顯著差異。比如有的採用 NumPy 的 npz 格式,有的則使用 PyTorch 的 pt 格式,還有的會自訂一套序列化方案。這就導致了模型利用的碎片化問題,不利於推廣普及。

除了格式不一致,LLM的硬體適配也面臨諸多障礙。一方面,儘管上述優化在降低推論開銷上已經卓有成效,但對於複雜的任務而言,CPU 計算能力仍嫌不足,必須借助 GPU、TPU 等專用加速器。而這些異構設備在編程模型上存在顯著差異,且驅動配置繁瑣,應用程式很難做到一次編寫,隨處執行。另一方面,由於模型體積仍然較大,單機記憶體很難將其全部裝載,因此通常需要分散式推論,這進一步加劇了環境依賴。

由此可見,要真正普及 LLM 技術,我們需要在工具鏈和基礎設施層面做出改變。具體而言,期望有這樣一套方案,能夠:

1. 屏蔽 LLM 檔案格式的差異,提供統一的模型描述和轉換機制。

2. 封裝異構硬體差異,實現可移植、高效能的加速方案。  

3. 簡化分散式環境配置,做到開箱即用、按需擴縮。

llamafile 正是基於這些考量應運而生。透過在兩個成熟專案的基礎上提供薄薄一層"膠水",它巧妙地化解了上述矛盾,讓部署 LLM 變得無比簡單。

llama.cpp:為 LLM 注入 C 的效能

在介紹 llamafile 的核心設計之前,我們有必要先了解其重要組成部分:llama.cpp。

眾所周知,Python 以簡潔優雅著稱,是機器學習研究人員的首選語言。但在工程實踐中,Python 的執行效率一直飽受詬病。這在 LLM 推論場景下尤為突出,因為模型體積巨大,稍有不慎就會引入性能瓶頸。為了避免這一問題,llama.cpp 的作者選擇用 C/C++ 從頭實現 LLM 推論。

Agent使用第三方的大模型隨著使用頻率增加,成本也會上升,是否有更省錢的方法呢?有的,就是將這些大模型跑在CPU上。

一般來說,月租GPU伺服器至少也要花費9000左右,使用第三方服務的API可能很划算,但使用第三方服務始終存在資料外洩的風險。而且隨著用戶增加,按token計價的方式也一樣會讓花費快速增加。一些技術專家找到了一個省錢的方法,那就是讓大型模型在AMD的GPU,甚至在CPU上運行。如果在CPU上運行,我們只需要租一台核心夠用且內存較大的伺服器即可,每個月的價格瞬間就能降低千元甚至千元以下,有時候選擇折扣方案只要花費四千多塊台幣就能租一年。

想要在CPU上跑LLM,關鍵在於兩個要點:

1. 有效的CPU運算架構。

2. 充分利用大型模型的性能。

只要做到以上兩點再配合一台硬體配置還不錯的CPU伺服器,就可以得到一個性價比極高的本地大型模型服務。

有關第一點,Georgi Gerganov提出了用C/C++重新實現模型框架的想法。就是我們上次提到的llama.cpp。

使用C/C++的優點在於:

不需要額外的依賴,相比Python代碼需要的PyTorch等庫,C/C++直接編譯出可執行文件,避免了不同硬體的繁瑣準備工作:

1. 支持Apple Silicon芯片的ARM NEON加速,x86平台則以AVX2替代。

2. 具有F16和F32的混合精度。

3. 支持4-bit量化。

4. 不需要GPU,只需CPU即可運行。

由於這是純C/C++實現,不需要其他依賴,運行效率很高。除了MacBook Pro外,甚至還可以在Android上運行。

第二點,如何對100B大小的大型模型進行壓縮,以便於CPU機器運行呢?答案是通過「量化」。量化是指將連續取值的浮點型模型權重進行裁剪和取捨的技術,簡單來說就是壓縮,丟失部分精度,換取空間和性能。Georgi Gerganov提出了自己的量化方案ggml,ggml成為一種量化模型的文件格式。不過,由於大模型發展太快,ggml很快就跟不上,於是在去年年8月,推出了改進方案gguf,成為最新的量化模型文件格式。目前,HuggingFace也大力支持這個格式。當然,除了gguf方案外,還有其他量化方案,例如GPTQ等。總之,經過量化後的模型,可以提升性能,降低對硬體資源的要求。

有了llama.cpp和gguf,我們就可以在CPU上跑大模型了。

雖然llama.cpp可以直接運行,但運作起來總是不太方便。畢竟現在很少有人用C++來寫系統,所以最好能夠直接與我們的應用結合起來。

這裡有兩種方案:

1. 建立獨立服務,通過RPC或HTTP進行調用。

2. 將其編譯為業務系統開發語言所支持的模組,直接在代碼中調用。

第一種方案可以使用llama.cpp專案提供的輕量級HTTP服務,或者使用第三方的Docker容器來啟動服務。啟動後,就可以通過HTTP API來調用大型模型。

第二種方案,技術社群裡會有很多神人提供不同語言的模組,可以在llama.cpp專案的首頁找到這些專案。只需要找到適合你業務系統編程語言的模組,安裝到你的系統中,就可以像調用一個第三方庫一樣調用大型模型。另外,如果想要快速體驗,還可以通過ollama一鍵安裝和啟動大模型的功能。

量化後的模型對硬體的要求降低,但並不是說隨便一台舊電腦就能跑得動。比如我們有一個需要8G內存的大模型,我們可以試試6B的量化模型。如果有必要,可以升級到32G,這樣就可以增加量化的精度,獲得更好的結果。如果只有2G內存,建議用第三方接口調用。

模型經過量化後失去了一部分精度,會不會影響模型的準確性?

對於這個問題,應該根據自己的需求來選擇。會有不同參數量級的模型,是因為對於不同的應用場景所需要的資料精度是不同的。對於應用開發來說,要學會根據需要選擇適合的模型,適度降低成本。如果將所有LLM的處理都交給一個大模型去處理,代表模型要承受巨大的服務壓力,成本也會相應增加。因此,合理將不同的處理分配給不同的模型,在學習和調試的過程中,可以自己搭建一個本地的大模型服務,等調試完Agent之後,再將部分調用切換到付費的大模型上。如此一來,就可以降低成本。

具體而言,llama.cpp 提供了一個通用的推論引擎,可以載入 LLaMA、GPT-J、GPT-NeoX 等主流模型,並執行高效的文字生成。它採用自訂的權重格式,將模型劃分為若干個分片,每個分片包含其全部參數。這種組織方式可以充分利用局部性原理,在載入和訪問權重時盡可能減少快取缺失和頁面調度。

在演算法實現上,llama.cpp 對矩陣乘等關鍵路徑進行了極致優化,充分利用了 SIMD、Loop Unrolling 等現代 CPU 特性,再加上精心調教的多執行緒並行,使其在工業級伺服器上的推論效能可比肩商用解決方案。

為了方便地與現有應用整合,llama.cpp 還提供了一個相容 OpenAI API 的 HTTP 伺服器。使用者只需將請求發送至指定埠,即可獲得類似於 GPT-3 的對話體驗。這極大降低了二次開發的門檻。

然而,llama.cpp 仍存在一些不足之處:

1. 儘管提供了 Python binding,但在實際使用中仍不可避免地需要一些 C++ 知識,對非專業開發者不太友善。

2. 雖然權重格式經過優化,但轉換過程需要花費較長時間,且佔用大量磁碟空間。  

3. 雖然已經適配了 CUDA 後端,但配置過程較為繁瑣,且未考慮 AMD 平台。

llamafile 透過引入 Cosmopolitan Libc,巧妙地解決了這些問題。

Cosmopolitan Libc:賦予 C 跨平台的靈魂

談到跨平台,很多人首先想到 Java 的"一次編寫,到處執行"。然而,對於偏好 C/C++ 的系統級開發者而言,這一理念似乎遙不可及。一個主要原因是,不同作業系統在底層 API 的語義和呼叫規範上存在顯著差異。為了適配多種環境,開發者不得不編寫大量膠水程式碼,人工處理各種邊界情況,既繁瑣又容易出錯。這嚴重阻礙了 C/C++ 程式的可移植性。

Cosmopolitan Libc 試圖從根本上解決這一困境。它的核心理念是:透過提供一層統一的系統呼叫抽象,讓開發者只需面向 Cosmopolitan API 編程,生成的目標碼就可以不經修改地在 Linux、Windows、macOS 等各種環境直接執行。

實現這一點的關鍵是 Cosmopolitan 的連結器。傳統的連結器如 ld 只負責解析符號、分配位址,對目標平台並不作過多假設。而 Cosmopolitan 的連結器則內置了一個微型作業系統,可在裸機環境直接啟動。在入口函數執行之前,它會初始化 GDT、頁表等關鍵資料結構,並提供執行緒調度、虛擬記憶體、動態連結等現代作業系統的核心功能。這使得 Cosmopolitan 程式可以不依賴宿主機核心,直接控制硬體資源。

在 API 層面,Cosmopolitan 參考了 POSIX 規範,提供了檔案、網路、多執行緒等常用系統服務。為了適配不同 ISA,它還實現了通用的原子操作、鎖機制等並發原語。對於跨平台必須的元件如 libc、libm,Cosmopolitan 也提供了自己的實現。這些努力最終使得開發者只需遵循 Cosmopolitan 的編程規範,就能編寫可移植的系統級應用。

但光有可移植性還不夠,Cosmopolitan 還需為高效能計算提供支援,這主要體現在兩個方面:

1. 動態連結。LLM 推論通常需要呼叫 CUDA、BLAS 等第三方程式庫。為此,Cosmopolitan 實現了自己的動態連結器,可以載入宿主機的共享物件,並自動完成重定位。

2. GPU 加速。考慮到異構計算的廣泛應用,Cosmopolitan 透過封裝 CUDA driver API,使得 GPU 核心可以直接內聯到 Cosmopolitan 程式中,避免了 JIT 編譯帶來的額外開銷。

這兩個特性是 Cosmopolitan 區別於傳統 Libc 的關鍵所在,也是 llamafile 實現其設計目標的重要基石。

https://github.com/Mozilla-Ocho/llamafile

融合創新:llamafile 的架構設計

有了前面的鋪墊,我們就可以詳細解讀 llamafile 的核心設計思路了。

簡單來說,llamafile 直接利用 llama.cpp 作為 LLM 推論後端,透過 Cosmopolitan Libc 將其打包為可執行檔。這裡的關鍵是,llamafile 將模型權重硬編碼到可執行檔中,使得最終產物可脫離原始碼獨立執行,且不受環境約束。

具體實現上,llamafile 主要經過如下步驟:

1. 模型轉換。首先使用 llama.cpp 提供的工具,將各種常見格式的權重檔案轉換為 llama.cpp 定制格式。這個過程是一次性的,轉換結果可供重複使用。

2. 構建 blob。利用 Cosmopolitan 的連結器 objcopy,將轉換後的權重檔案以 blob 的形式內嵌到目標檔案中。

3. 連結可執行檔。將 llama.cpp 的核心程式碼、Cosmopolitan Libc、權重 blob 等目標檔案一起連結,生成最終的可執行檔。在這個過程中,連結器會進行符號解析和重定位,並生成元資料供啟動期使用。

4. 執行期載入。當可執行檔啟動時,首先由 Cosmopolitan 執行期完成初始化,並解析命令列參數。隨後,llamafile 利用 mmap 將嵌入的權重 blob 映射到記憶體,模擬 llama.cpp 的模型載入過程,繼而可以開始推論。

整個過程無需依賴 Python 直譯器,權重載入也省去了從檔案系統讀取的 I/O 開銷,再加上 Cosmopolitan 對資源的細粒度控制,使得 llamafile 的端到端效能接近原生應用。

為了進一步提高效能,llamafile 還在 Cosmopolitan 的基礎上實現了以下增強:

- 利用 GPU 加速矩陣運算,針對 NVIDIA 平台封裝了 cuBLAS API,AMD 平台則使用 ROCm。

- 針對 NUMA 架構進行 NUMA-aware 記憶體分配和執行緒調度優化。

- 引入 Cosmopolitan 對 JIT 編譯的支援,可在執行期產生高度優化的計算核心。

- 在模型並行方面,llamafile 支援多 GPU 橫向擴展,並利用 NCCL 實現高效通訊。

同時,llamafile 還致力於提供開箱即用的使用者體驗:

- 提供 llamafile-convert 工具簡化模型轉換,並與 Hugging Face 等社群生態深度整合。

- 持續完善 API server,提供易用的 RESTful 介面,同時相容各種應用框架。  

- 針對 CPU 後端實施 Lazy Tensor 優化,減少不必要的顯存佔用。

這些設計使得 llamafile 不僅在性能上拔得頭籌,也讓 LLM 開發和使用前所未有地便捷。


推動大語言模型民主化進程

自面世以來,llamafile 迅速俘獲了開源社群的芳心。憑藉卓越的性能和體驗,它已躍升為 Mozilla 最受歡迎的專案之一。在眾多貢獻者的推動下,llamafile 正以驚人的速度迭代演進,展現了開源力量的非凡魅力。

開源程式碼,技術創新,社群協作,這是 llamafile 專案的三大法寶,也是它不斷突破自我、續寫傳奇的力量源泉。  

自 v0.1 發布以來,llamafile 幾乎以每月一版的速度迭代。在 v0.8 中,它不僅支援了 Meta 最新發布的 LLaMA 3 等 SOTA 模型,還帶來了一系列性能優化:透過手寫組合語言實現的 BLAS 核心將 CPU 運算效率提高了一個數量級;針對 NVIDIA 和 AMD GPU 的異構調度策略也更加完善;為樹莓派等 ARM 平台提供了專門的低位元量化方案,即便在這些小型設備上也能實現即時對話。如此迅猛的進化速度,展現了開源力量的驚人魅力。

與此同時,llamafile 還在架構層面做出了前瞻性的嘗試。比如在 v0.7 中,它引入了混合執行引擎,可以根據模型規模和硬體條件動態調整執行策略。對於超大規模模型,它會自動採用流水線並行、張量融合等圖優化技術,最小化資料移動;對於中小規模模型,則會利用 Lazy Tensor 避免無謂的顯存分配,提高快取利用率。這為 LLM 推論提供了一套全局優化的範式。  

llamafile 也在積極擁抱社群生態。透過提供相容 OpenAI 的 API,它可以直接取代商業方案,為各種創新應用提供基礎支撐。在 LangChain、AutoGPT 等熱門專案中,我們已經可以看到 llamafile 的身影。Mozilla 還專門成立了 MIECO專案,為 llamafile 等開源技術搭建產學研用協同創新的平台,推動 AI 生態良性發展。

展望未來,隨著演算法優化的不斷突破,以及晶圓代工工藝的持續進步,LLM 推論已展現出阿米巴原生的趨勢特徵。從雲端到邊緣、從資料中心到終端,llamafile 這樣的"蘋果核"有望成為 AI 民主化的助推器,讓智慧應用遍地開花。  

作為這一變革的先行者,Mozilla 正在 llamafile 的基礎上謀劃更宏大的藍圖。相信在可見的未來,它必將釋放出比肩作業系統和瀏覽器的顛覆性力量,成為 AI 新紀元的基石。讓我們拭目以待,見證 llamafile "出圈"的那一天。

小結

llamafile 是 Mozilla 為推動 LLM 大眾化做出的重要努力。它巧妙結合了 llama.cpp 和 Cosmopolitan Libc 兩大開源專案,透過將模型權重內嵌到可執行檔,徹底解決了 LLM 分發和部署的難題。  

性能方面,得益於 Cosmopolitan 細粒度的系統呼叫抽象和 llamafile 在 GPU 加速、BLAS 優化等方面的卓越工作,其端到端回應速度可比肩商業方案,且可輕鬆橫向擴展。

體驗方面,llamafile 提供了豐富的工具鏈支援,簡化了模型轉換和自訂流程。其 API server 更是開箱即用,無需過多配置即可實現靈活呼叫。

llamafile 的成功離不開開源社群的積極參與。Mozilla 不僅以 MIECO 的形式搭建產學研用協同創新的平台,更以 llamafile 為起點規劃 AI 普惠的宏偉藍圖。  

站在 IT 發展的新起點,Mozilla 正以 llamafile 為引擎,驅動 AI 技術向更廣闊的應用場景滲透。我們有理由相信,這場由開源力量領跑的 AI 革命,必將像當年的個人電腦和網際網路一樣,以摧枯拉朽之勢重塑數位世界的格局。讓我們攜手共進,做 AI 新時代的見證者和開創者!

個人觀點

作為一個開源愛好者和AI研究者,我對 llamafile 這樣的創新專案感到由衷的敬佩和興奮。在我看來,它不僅是一個技術突破,更代表了開源精神和創新動力的完美結合。

llamafile最令人印象深刻的,是它在複雜的異構環境中實現了"一次編寫,隨處執行"的理想。這在以往的 AI 部署中幾乎是不可想像的。無論是格式轉換、運行時優化還是分散擴展,llamafile 提供的全流程自動化方案堪稱教科書般的典範。更難能可貴的是,這一切都建立在開源專案的基礎之上,展現了開源社群協作的驚人力量。

同時,llamafile 對 LLM 生態的推動作用也不容小覷。一方面,它大大降低了 LLM 的准入門檻,讓更多人可以參與到這場 AI 變革中來。透過與主流開源社群的緊密整合,llamafile 將釋放出更多創新活力。另一方面,llamafile 的成功也為商業公司敲響了警鐘。在开源力量面前,封閉平台和專有格式已經岌岌可危。唯有擁抱開放,合作共贏,才能在 AI 新時代佔得一席之地。

當然,llamafile 還有進一步完善的空間。比如在安全和隱私方面,目前的方案可能還不夠成熟;在支援更多的模型和硬體時,也需要投入大量的適配工作。但我相信,在開源社群的共同努力下,這些問題終將迎刃而解。Mozilla 樹立的"開源+創新"範式,也必將在更多領域綻放異彩。

展望未來,我對 AI 技術的民主化充滿期待。隨著 llamafile 這樣的基石工程不斷夯實,LLM 推論從雲端向終端滲透的趨勢已勢不可擋。在可見的未來,也許我們每個人都將擁有自己的"AI助手"。它們不再是大公司的專利,而是真正服務於每個人的智慧夥伴。這場變革不僅將提升生產力,改善生活品質,更將從根本上重塑人與科技的關係。而這一切,都將由開源力量來推動和實現。作為這個偉大時代的一分子,我們每一個人都應該努力探索開源的無限可能,用創新和協作為 AI 新紀元續寫傳奇。讓我們攜手並進,共創美好未來!

沒有留言:

發佈留言

SambaNova SN40L: 利用Dataflow和專家組合(COE)來克服AI記憶牆的大模型

摘要 GPT-4等整體式大型語言模型(LLM)為現代生成AI應用鋪路。然而,大規模訓練、服務及維護整體式LLM仍然極其昂貴和充滿挑戰。現代AI加速器計算能力與記憶體比例的不成比例增長已經造成了記憶體壁障,需要新的方法來部署AI。最近的研究顯示,許多小型專家模型的組合,每個模型參數...