- TurboFieldfare รัน Gemma 4 26B-A4B ด้วยหน่วยความจำราว 2GB โดยไม่ต้องโหลดโมเดลทั้งก้อนขนาด 14.3GB เข้าเมมโมรี ทำให้เครื่อง Apple Silicon Mac ที่มี 8GB ก็ทำ local inference ได้
- มันเก็บเพียง shared core 1.35GB และ FP16 KV cache ไว้ในหน่วยความจำ แล้วสตรีมน้ำหนักของ MoE expert ที่จำเป็นสำหรับแต่ละโทเค็นจาก SSD โดยใช้ LFU cache 16 สล็อตและ
preadแบบขนานเพื่อจำกัดงาน I/O - Gemma 4 26B-A4B เปิดใช้พารามิเตอร์ราว 3.88B ต่อโทเค็น และความเร็วในการถอดรหัสที่วัดได้คือ 5.1~6.3 tok/s บน M2 MacBook Air 8GB และ 31~35 tok/s บน M5 Pro 24GB
- เป็นรันไทม์เฉพาะทางที่พัฒนาด้วย Swift 6.2 และ Metal 4 พร้อมทั้งมีแอป Mac แบบเนทีฟ, CLI, เครื่องมือติดตั้ง และ เซิร์ฟเวอร์ที่เข้ากันได้กับ OpenAI แบบทดลอง บนไดเรกทอรีโมเดล
.gturboเดียวกัน - ขอบเขตปัจจุบันจำกัดอยู่ที่ การทำ inference แบบข้อความเท่านั้น บน Apple Silicon Mac ที่มี macOS 26 ขึ้นไปและ RAM อย่างน้อย 8GB โดยไม่รองรับภาพ เสียง วิดีโอ รวมถึง remote server authentication และ TLS
โครงสร้างการรันที่ลดการใช้หน่วยความจำ
- TurboFieldfare ไม่โหลด Gemma 4 26B-A4B เวอร์ชัน instruction-tuned เข้าเมมโมรีทั้งหมด
- เก็บ shared core 1.35GB และ FP16 KV cache ไว้ในหน่วยความจำ
- อ่านเฉพาะ routed expert ที่ต้องใช้สำหรับแต่ละโทเค็นจาก SSD ไปยังบัฟเฟอร์ที่ Metal มองเห็นได้
- แม้โมเดลแบบข้อความที่ติดตั้งแล้วจะมีขนาดราว 14.3GB แต่หน่วยความจำที่ใช้สำหรับน้ำหนักและ 4K KV cache อยู่ที่ราว 2GB
- โมเดลนี้เปิดใช้พารามิเตอร์รวมราว 3.88B พารามิเตอร์ ต่อโทเค็น จากทั้งหมด 26B พารามิเตอร์
- น้ำหนักใช้ MLX affine 4 บิตแบบ group 64 โดย router เป็น 8 บิต และ shared กับ routed expert เป็น 4 บิต
- ไม่ใช่โครงสร้างที่ห่อหุ้ม MLX หรือ llama.cpp แต่เป็น รันไทม์ Swift·Metal เฉพาะทาง ที่สร้างมาสำหรับ Gemma 4 26B-A4B
กระบวนการสร้างโทเค็น
- ในแต่ละ Transformer layer, Metal จะคำนวณ attention และ router ด้วยน้ำหนักที่อยู่ประจำในหน่วยความจำ
- CPU จะนำ expert ID 8 อันดับแรก ที่ router เลือกมาเทียบกับ LFU cache 16 สล็อตในแต่ละเลเยอร์
- cache miss จะถูกเติมด้วยการเรียก
preadแบบขนานจำนวนจำกัด - ระหว่างที่ SSD กำลังอ่านข้อมูล Metal จะคำนวณแขนง shared-expert ที่อยู่ประจำไปก่อน
- เมื่ออ่านเสร็จแล้วจึงรวม shared output และ routed output เข้าด้วยกัน
- cache miss จะถูกเติมด้วยการเรียก
- การทำ prompt prefill ใช้ chunk สูงสุด 128 โทเค็น เพื่อให้ expert ที่ดึงมาครั้งหนึ่งประมวลผลได้หลายแถว
- ในขั้นตอนการสร้าง จะวนลูป routed layer แบบโทเค็นต่อโทเค็น
- KV cache ใช้ที่เก็บแบบวนรอบสำหรับ 25 sliding-window layer และใช้ที่เก็บแบบเชิงเส้นสำหรับ 5 full-attention layer
- attention ในขั้นตอนถอดรหัสใช้วิธี exact split-K/V ที่แยกเส้นทาง K และ V ที่ถูกทำ normalization แล้ว
การติดตั้งและรูปแบบโมเดล
- เมื่อรันครั้งแรก หากเลือก Download ระบบจะดาวน์โหลดข้อมูลราว 15GB จาก revision ที่ตรึงไว้บน Hugging Face ผ่าน range request
- ตัวติดตั้งจะไม่สร้าง checkpoint ต้นฉบับทั้งก้อนเป็นไฟล์ชั่วคราวหรือในหน่วยความจำ
- จะรับเฉพาะช่วงไบต์ที่จำเป็นแล้วแพ็กใหม่เป็นเลย์เอาต์
.gturboทันที - ไม่ต้องเตรียม shard หรือ tensor ทั้งก้อนแยกต่างหาก จึงจำกัดการใช้หน่วยความจำชั่วคราวได้
- ไฟล์ติดตั้งที่เสร็จสมบูรณ์จะใช้งานได้ก็ต่อเมื่อผ่านการตรวจสอบ manifest และ file hash
- จะรับเฉพาะช่วงไบต์ที่จำเป็นแล้วแพ็กใหม่เป็นเลย์เอาต์
- หลังติดตั้งเสร็จ โมเดลจะใช้พื้นที่จัดเก็บราว 14.3GB และกระบวนการติดตั้งเองก็ไม่โหลดโมเดลเข้าเมมโมรี
- รันไทม์ยอมรับเฉพาะไดเรกทอรี
.gturboที่เสร็จสมบูรณ์และมีmanifest.jsonสุดท้ายเท่านั้น - รองรับการดาวน์โหลดต่อจากที่ค้างไว้, การลบสถานะดาวน์โหลดบางส่วน และการตรวจสอบการติดตั้งโดยไม่ต้องโหลดโมเดล
สภาพแวดล้อมการรันและประสิทธิภาพ
- สภาพแวดล้อมที่ต้องการคือ Apple Silicon Mac, macOS 26, Metal 4, Xcode 26 และ Swift 6.2 ขึ้นไป
- แพ็กเกจนี้เป็น arm64 เท่านั้น และไม่รองรับ macOS กับ Metal เวอร์ชันเก่า
- เครื่องที่ใช้ตรวจสอบคือ M2 MacBook Air 8GB โดยต้องมีพื้นที่ว่างสำหรับติดตั้งโมเดลและการเชื่อมต่ออินเทอร์เน็ตสำหรับดาวน์โหลดครั้งแรก
- ประสิทธิภาพการถอดรหัสที่วัดได้มีดังนี้
- M2 MacBook Air 8GB: 5.1~6.3 tok/s
- M5 Pro 24GB: 31~35 tok/s
- throughput จะแตกต่างกันไปตามความยาวพรอมป์ต์ ความยาวที่สร้าง สถานะ page cache และฮาร์ดแวร์ ดังนั้นค่าที่วัดได้จึงเป็นเพียงจุดอ้างอิง ไม่ใช่ขีดสูงสุดของประสิทธิภาพ
- ก่อนรันโมเดล ควรปิดแอปที่ใช้หน่วยความจำมาก และตรวจสอบหน่วยความจำว่างด้วย
memory_pressure -Q - แอป, decode service, CLI, เซิร์ฟเวอร์, การทดสอบ หรือโปรเซสโมเดลภายในเครื่องอื่น ๆ ควรรันทีละอย่างเท่านั้น
ผลิตภัณฑ์ที่มีให้และวิธีใช้งาน
- Swift package นี้มีผลิตภัณฑ์ 6 รายการ
TurboFieldfare: ไลบรารี Swift ที่มีรันไทม์และ Metal kernelTurboFieldfareMac: แอป Mac แบบเนทีฟสำหรับติดตั้งและสร้างผลลัพธ์TurboFieldfareDecodeService: โปรเซส local model·Metal แบบใช้ครั้งเดียวที่แอป Mac ใช้งานTurboFieldfareCLI: instruction chat และ raw completion ผ่านบรรทัดคำสั่งTurboFieldfareServer: เซิร์ฟเวอร์ Chat Completions แบบ loopback ที่เข้ากันได้กับ OpenAITurboFieldfareRepack: เครื่องมือสำหรับการติดตั้งแบบสตรีมมิงและตรวจสอบการติดตั้ง
- ในแอป Mac สามารถดาวน์โหลดโมเดล แล้วเลือก Load Model และป้อนพรอมป์ต์เพื่อเริ่มสร้างผลลัพธ์
- สามารถดูความคืบหน้า ความเร็วในการถอดรหัส และการใช้หน่วยความจำได้จากแถบสถานะ
- ปรับ sampling, context length, expert-cache slot และตัวเลือกรันไทม์ได้
- instruction chat ของ CLI รับอาร์เรย์ข้อความแบบ JSON แล้วแปลงเป็นรูปแบบเดียวกับแอป Mac
- ค่าเริ่มต้นของ
--max-newซึ่งเป็นขีดจำกัดการตอบกลับคือ 1,024 โทเค็น - แอป Mac สามารถสร้างต่อได้จนกว่า context window ที่เลือกจะเต็ม
- ค่าเริ่มต้นของ
--promptใช้สำหรับ raw completion ที่ไม่ใช้รูปแบบแชต และสำหรับการเปรียบเทียบที่ทำซ้ำได้- ข้อความที่สร้างจะส่งไปยัง standard output ส่วนสถิติเวลาจะส่งไปยัง standard error และสามารถปิดการแสดงสถิติได้ด้วย
--quiet
พรอมป์ต์และขอบเขตที่รองรับ
- แอป Mac จะประมวลผลอินพุตเป็น instruction และใช้รูปแบบแชตของ Gemma โดยอัตโนมัติ
- ค่าตั้งต้นของ sampling คือ temperature
0.2, Top-K64, Top-P0.95- หากตั้ง temperature เป็น
0จะใช้ greedy output แบบกำหนดแน่นอน - โมเดลอาจตอบซ้ำหรือผิดได้ ดังนั้นผลลัพธ์สำคัญควรได้รับการตรวจสอบ
- หากตั้ง temperature เป็น
- แอปและ CLI รองรับข้อความผู้ใช้ ข้อความโมเดล และ system guidance แบบเลือกได้ แต่ ไม่เปิดเผยหรือเรียกใช้เครื่องมือ
- ปัจจุบันอินพุตและเอาต์พุตของโมเดลรองรับเฉพาะข้อความ ไม่รองรับภาพ เสียง หรือวิดีโอ
- CLI มีตัวเลือก
--max-context,--temperature,--top-k,--top-p,--repetition-penalty,--seedและสตริง--stopแบบระบุซ้ำได้
เซิร์ฟเวอร์ภายในเครื่องที่เข้ากันได้กับ OpenAI
- เซิร์ฟเวอร์แบบทดลองทำงานที่
127.0.0.1:8080/v1และรองรับ Chat Completions, การสตรีม, การประกาศ function tool และการใช้พรอมป์ต์ prefix เดียวซ้ำ - เซิร์ฟเวอร์จะส่งคืน tool call ที่โมเดลสร้างขึ้น แต่การอนุมัติและรันการเรียกใช้เครื่องมือทั้งหมดเป็นหน้าที่ของไคลเอนต์
- เนื่องจากไม่มี remote authentication และ TLS จึงควร จำกัดเซิร์ฟเวอร์ไว้ที่ loopback เท่านั้น
- แอป Mac, CLI และเซิร์ฟเวอร์ใช้ไดเรกทอรี
.gturboเดียวกัน แต่ผลิตภัณฑ์ที่ครอบครองโมเดลควรรันพร้อมกันได้เพียงตัวเดียว
ขอบเขตการพัฒนาและบันทึกการทดลอง
- Metal kernel แบบกำหนดเองรองรับ quantized GEMV, attention, MoE, normalization, RoPE, sampling และ production fusion
- รันไทม์นี้มีการสตรีม routed-expert จาก SSD, expert cache แบบจำกัด, prompt prefill แบบพรอมป์ต์เดียวระดับ chunk และการสร้างแบบโทเค็นต่อโทเค็น
- มีการเก็บ ผลการวัด 103 รายการ เป็นบันทึกการทดลอง ครอบคลุม kernel, caching, I/O, prefill และ decode
- เอกสารการทดลองรวมถึงการปรับแต่งที่ได้ผลมาก ไอเดียที่ล้มเหลว และผลลัพธ์เบื้องต้นที่ภายหลังถูกหักล้างหลังการตรวจสอบที่เข้มงวดขึ้น
- งานในอนาคตคือการพัฒนาแอป iPhone·iPad การวัดความเร็วและหน่วยความจำของ mobile inference รวมถึง benchmark บน Mac mini M4 16GB และ Apple Silicon Mac 8GB รุ่นอื่น
ไลเซนส์และเงื่อนไขของโมเดล
- ซอร์สโค้ดและเอกสารถูกเผยแพร่ภายใต้ Apache License 2.0
- น้ำหนักของโมเดลไม่ได้รวมอยู่ในรีโพซิทอรี และตัวติดตั้งจะดาวน์โหลดแยกต่างหากจาก checkpoint บน Hugging Face ที่ตรึงไว้
- เงื่อนไขการเผยแพร่เดิมยังคงมีผลกับน้ำหนักเหล่านั้น
- TurboFieldfare เป็น โครงการวิจัยอิสระ ที่ไม่ได้มีความร่วมมือ การสนับสนุน หรือการรับรองจาก Google
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ผมสงสัยมาตลอดว่าทำไมทุกครั้งถึงต้องยัด โมเดลทั้งก้อนลงหน่วยความจำ ราวกับจำเป็นต้องรู้ไปถึงว่ากษัตริย์ชาร์ลส์คือใคร เทคนิคการแบ่งไฟล์ใหญ่เป็นชิ้นเล็ก ๆ แล้วอ่านอย่างมีประสิทธิภาพด้วยหน่วยความจำน้อยนั้นถือว่าเป็นเรื่องที่ทำกันได้ดีอยู่แล้ว
ในวงการ AI ระดับแนวหน้า ดูเหมือนจะมีแนวโน้มว่าเก่งเรื่องสร้างโมเดล แต่โยนเรื่องการขยายสเกลและการใช้งานจริงไปให้ฝ่ายอินฟรา ถ้าความรู้ที่ใช้งานจริงมีไม่ถึง 10% การปรับละเอียดและการปรับให้เหมาะสมก็น่าจะลดต้นทุนได้มาก
LLM แบบ dense มักให้ประสิทธิภาพดีกว่า แต่ถ้าย้ายชั้นต่าง ๆ ออกไปไว้ในสตอเรจภายนอก จะช้ากว่า MoE มาก
ทุกวันนี้เวลาโหลดโปรเจกต์ที่ไม่รู้ที่มา เราควรรัน การตรวจสอบความปลอดภัย แบบนี้เอง ให้มันมองข้ามคำสั่งสำหรับเอเจนต์และไฟล์ Markdown ในรีโพ แล้วตรวจ Swift/Metal source, build script, CI config และ dependency ผลคือไม่พบโค้ดอันตราย แบ็กดอร์ การขโมย credential หรือ network endpoint ที่ซ่อนอยู่ แต่ความเสี่ยงด้านการคอมไพล์ ซัพพลายเชน และรันไทม์ยังคงมีอยู่
ถ้ามีพรอมป์ที่ดีกว่านี้ก็แชร์กันได้ ค่าใช้จ่ายที่รันด้วย Composer 2.5 ของ Cursor อยู่ที่ ต่ำกว่า 0.20 ดอลลาร์
ถ้าใช้ macOS 15 บน M1 MacBook Air ให้ลบสองบรรทัดต่อไปนี้ หรือครอบด้วย
if #available(macOS 26.0, *)ก็จะคอมไพล์ได้:opts.languageVersion = .version4_0ตามคอมเมนต์ในโค้ด จะพลาดผลที่ attention เร็วขึ้น 11.24 เท่า ทำให้ prefill เร็วขึ้น 2.4 เท่า แต่บน M1 Air GPU 8 คอร์ก็ยังได้ 5–6 โทเคนต่อวินาที
การปรับปรุง prefill 2.4 เท่า ใช้ได้เฉพาะกับตระกูล GPU apple10 ส่วน M1 ถ้าจำไม่ผิดเป็น apple7
อยากรู้ว่าโปรเจกต์นี้เทียบกับ
mmapธรรมดาอย่างไร llama.cpp ถ้าเปิดmmapแล้วปิด repacking ก็สามารถรันโมเดล 26B บน RAM 2GB ได้หากต้องการความต่างหลักดูเหมือนอยู่ที่การซิงก์การอ่านจาก SSD กับงาน inference เพื่อลด latency ซึ่งระบบปฏิบัติการไม่ได้คำนึงถึงบริบทการรันแบบนี้
mmapบน M2 8GB ตอน cold start การอ่าน expert ขนาด 3.36MB ใช้เวลา 10ms ด้วยmmapส่วนpreadใช้ 2.8ms และทั้ง simulation ได้ตามลำดับคือ 0.50 โทเคน/วินาที กับ 4 โทเคน/วินาทีเมื่อใช้
mmapระบบปฏิบัติการจะอ่านแบบตอบสนองหลังจากโมเดลแตะ page แล้ว จึงไม่รู้ว่า expert ไหนถูกเลือก หรือเมื่อไรจะซ้อนงาน GPU กับการอ่านได้ น้ำหนักส่วนที่ใช้ร่วมกันยังใช้mmapเพื่อความเรียบง่าย และคิดว่า llama.cpp ก็น่าจะรันต่ำกว่า 2GB ได้ แต่คงช้ากว่าประโยคที่ว่า “ผลการวัดเป็นจุดอ้างอิง ไม่ใช่เพดานประสิทธิภาพ” ดูเหมือน สำนวนเฉพาะของ Claude
ถ้าผู้เขียนใช้ LLM แค่ขัดเกลาประโยคและไม่ได้เติมเนื้อหาไร้สาระ ก็ไม่เป็นไร ถ้าตัวบทความเองเป็นงาน generated ที่ไม่มีประโยชน์ ก็แค่ให้คะแนนต่ำไป
น่าประทับใจที่บน M1 Max Mac Studio ซึ่งมี SSD เร็วกว่า ได้ 12 โทเคนต่อวินาที และตอบสนองแทบจะทันที แสดงให้เห็นความเป็นไปได้ในการรันโมเดลขนาดใหญ่โดยตรงจาก SSD แทนที่จะอยู่ในหน่วยความจำ
ช่วงนี้มีเอนจินสตรีมจาก SSD เยอะ แต่ไม่ค่อยมีใครลองฟีเจอร์ยาก ๆ เนื่องจากโมเดลหลักมี MTP head สำหรับ speculative decoding อยู่แล้ว จึงสามารถใช้มันเพื่ออ่านค่าน้ำหนัก expert จาก SSD ล่วงหน้าได้
ถ้าเตรียมน้ำหนักไว้ก่อนที่ GPU จะต้องใช้ ก็ลดต้นทุนจาก VRAM cache miss ได้มาก และถ้าพิสูจน์แล้วว่าได้ผล โมเดลในอนาคตอาจมี head เฉพาะสำหรับ preload expert และคำนึงถึงสิ่งนี้ตั้งแต่ขั้นฝึก
token draft ที่ MTP สร้างอาจทำนาย expert ของชั้นแรกได้ แต่ถ้าจะรู้ชั้นที่ 10 ต้องรันชั้นที่ 1–9 และอ่าน expert เหล่านั้นก่อน ดังนั้นแทนที่จะใช้ตัวสร้าง token ถัดไป ต้องมีอุปกรณ์ที่ถูกฝึกให้ทำนาย การ activate expert ของทุกชั้น พร้อมกัน
โปรเจกต์สำหรับรัน DiffusionGemma ก็ใกล้พร้อมแล้ว และถ้ารวมสองโปรเจกต์นี้น่าจะเข้ากันได้ดี บน M3 36GB ได้ ประมาณ 20 โทเคนต่อวินาที และมีโอกาสสูงที่จะหยิบ kernel ที่เร็วกว่าของกันและกันมาใช้
โค้ดปัจจุบันอยู่ที่ https://github.com/mmastrac/diffgemma แต่ยังไม่พร้อมสำหรับเผยแพร่
อยากรู้ความเห็นต่อเรื่องนี้
สงสัยว่าทำไมถึงต่างกันมากขนาดนี้ระหว่าง 5–6 โทเคนต่อวินาทีบน M2 MacBook Air แรม 8GB กับ 31–35 โทเคนต่อวินาทีบน M5 MacBook Pro ประสิทธิภาพ SSD ไม่น่าจะต่างกันถึงขนาดนั้น แต่คาดว่าวิธีนี้ SSD น่าจะเป็นคอขวดหลัก
https://www.tomshardware.com/laptops/macbooks/m5-macbook-pro...
หากรวมแคชของระบบปฏิบัติการแล้วใช้ได้ทั้งหมดแค่ 2GB ความเร็วในการอนุมานอาจลดลงอีก
preadค่อนข้างมาก แม้โปรเซสจะต่ำกว่า 2GB แต่ Mac รุ่น M5 ก็ยังแคชบางส่วนได้ และฮาร์ดแวร์เองก็เร็วกว่าอย่างมากการอ่านต่อโทเคนอยู่ที่ 83ms บน M2 และ 12ms บน M5 Pro ส่วนเวลารวมอยู่ที่ 163ms และ 30ms ตามลำดับ เป็นผลจากทั้งการอ่านและการประมวลผลด้วย GPU ที่เร็วขึ้น
คาดหวังว่าในอนาคต ระบบที่มี หน่วยความจำ 30–60GB และ SSD ที่เร็วมาก จะสามารถใช้เทคนิคแบบนี้รันโมเดลขนาดใหญ่มากได้
https://github.com/danveloper/flash-moe
https://github.com/JustVugg/colibri
สามารถใช้ https://github.com/antirez/ds4 หรือ https://github.com/steadfastgaze/MoEspresso ที่ทำเองได้ เนื่องจากต้องอ่าน expert สำหรับโทเคนถัดไปที่ไม่ได้อยู่ในหน่วยความจำจาก SSD ความเร็วจึงถูก จำกัดด้วยการอ่านจาก SSD และยิ่งมีหน่วยความจำมาก การอนุมานก็ยิ่งเร็วขึ้น