3 คะแนน โดย GN⁺ 2026-03-25 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เพิ่มประสิทธิภาพการจัดวางเทนเซอร์ระหว่าง GPU·RAM·NVMe เพื่อรัน ตัวจัดตารางอนุมานแบบรับรู้ลำดับชั้นการจัดเก็บข้อมูล สำหรับโมเดลภาษาขนาดใหญ่
  • บน Mac Mini 32GB สามารถรันโมเดล Mixtral 8x7B(31GB) ที่ความเร็ว 2.2 tok/s และโมเดล Llama 70B(40GB) ที่ความเร็ว 0.3 tok/s
  • วิเคราะห์รูปแบบการเข้าถึงและแบนด์วิดท์ของฮาร์ดแวร์เพื่อให้ โมเดลที่ใหญ่เกินหน่วยความจำจริงทำงานได้อย่างเสถียร รวมถึงโมเดลที่เดิม llama.cpp ล้มเหลวด้วย OOM ก็ยังประมวลผลได้
  • ลด I/O ได้สูงสุด 75% และทำแคชฮิตเรตได้ 99.5% ผ่าน การกำหนดเส้นทางผู้เชี่ยวชาญของ MoE, นิวรอนแคช, และ การพรีเฟตช์
  • เลือกโหมด Full-resident, Expert-streaming, Dense FFN-streaming โดยอัตโนมัติตามขนาดโมเดลและฮาร์ดแวร์ เพื่อคงประสิทธิภาพที่เหมาะสมที่สุด
  • มี HTTP API ที่เข้ากันได้กับ Ollama จึงเชื่อมต่อกับ OpenClaw เป็นต้นได้ และใช้ SSD แบบอ่านอย่างเดียวเพื่อรองรับ การอนุมานบน NVMe โดยไม่กระทบอายุการใช้งาน

ภาพรวม

  • Hypura เป็น ตัวจัดตารางอนุมาน LLM แบบรับรู้ลำดับชั้นการจัดเก็บข้อมูล สำหรับสภาพแวดล้อม Apple Silicon โดยเป็นเครื่องมือที่ทำ การเพิ่มประสิทธิภาพการจัดวางเทนเซอร์ ระหว่าง GPU·RAM·NVMe
  • กระจายการจัดวางเทนเซอร์ตามรูปแบบการเข้าถึง ต้นทุนแบนด์วิดท์ และประสิทธิภาพฮาร์ดแวร์ ทำให้ โมเดลขนาดใหญ่ที่เกินหน่วยความจำจริงสามารถทำงานได้อย่างเสถียร
  • บน Mac Mini 32GB สามารถรันโมเดล Mixtral 8x7B(31GB) ที่ความเร็ว 2.2 tok/s และโมเดล Llama 70B(40GB) ที่ความเร็ว 0.3 tok/s
  • ในสภาพแวดล้อมเดียวกัน llama.cpp ไม่สามารถรันได้เนื่องจาก OOM (Out of Memory)

ที่มาของปัญหา

  • Mac สำหรับผู้บริโภคมี หน่วยความจำรวมความเร็วสูงและอุปกรณ์จัดเก็บ NVMe แต่มีข้อจำกัดด้านความจุหน่วยความจำ
  • ตัวอย่างเช่น M1 Max 32GB ไม่สามารถโหลดโมเดลขนาด 40GB ได้โดยตรง จึงเกิด การสว็อปมากเกินไปและจบการทำงานด้วย OOM
  • Hypura แก้ปัญหานี้ด้วยการวิเคราะห์โครงสร้างของโมเดลและจัดวางให้เหมาะสมในแต่ละชั้น

การจัดวางตามชั้นโดยอิงจากโครงสร้างโมเดล

  • Norms และ Embeddings: มีขนาดเล็กแต่ถูกเข้าถึงทุกโทเคน จึงตรึงไว้บน GPU
  • MoE Expert Routing: ใช้ประโยชน์จากความ sparse โดยจะเปิดใช้งานผู้เชี่ยวชาญเพียง 2 จาก 8 คนต่อโทเคน
    • ดักจับเราเตอร์เพื่อระบุผู้เชี่ยวชาญที่ถูกเปิดใช้งาน แล้วโหลดเฉพาะส่วนที่จำเป็นจาก NVMe
    • ทำได้ทั้ง ลด I/O ลง 75% และ นิวรอนแคชฮิตเรต 99.5%
    • ใช้ การติดตามการเปิดใช้งานร่วม (co-activation tracking) เพื่อคาดการณ์ผู้เชี่ยวชาญที่จะถูกเปิดใช้งานถัดไปและทำการพรีเฟตช์ล่วงหน้า
  • Dense FFN Weights: คิดเป็นประมาณ 60% ของขนาดโมเดล
    • สตรีมจาก NVMe ผ่าน dynamic pool buffer
    • prefetch lookahead depth จะปรับอัตโนมัติตามหน่วยความจำที่มีให้ใช้
  • ผลลัพธ์คือ แม้แต่โมเดลที่เดิมแครชเมื่อใช้วิธี mmap แบบเดิมก็ยังรันได้ และสำหรับโมเดลที่พอดีกับหน่วยความจำก็ทำงานที่ ความเร็วระดับ Metal GPU โดยไม่มีโอเวอร์เฮด

วิธีการทำงาน

  • Hypura จะ อ่านไฟล์ GGUF และโปรไฟล์แบนด์วิดท์ของ GPU·RAM·NVMe
  • จากนั้นจัดวางแต่ละเทนเซอร์ลงในหนึ่งในสามชั้นต่อไปนี้
    • GPU(Metal): ชั้น Attention, Norm, Embedding
    • RAM: ชั้น overflow ที่ไม่สามารถโหลดขึ้น GPU ได้
    • NVMe: ชั้นที่เหลือ โดยใช้ F_NOCACHE + pread เพื่อทำ I/O โดยตรง
  • เลือก โหมดอนุมาน โดยอัตโนมัติตามขนาดโมเดลและฮาร์ดแวร์
    • Full-resident: โหลดโมเดลทั้งหมดไว้ใน GPU+RAM ไม่มี NVMe I/O
    • Expert-streaming: สำหรับโมเดล MoE โดยให้เฉพาะเทนเซอร์ที่ไม่ใช่ผู้เชี่ยวชาญอยู่บน GPU และสตรีมเทนเซอร์ผู้เชี่ยวชาญจาก NVMe
    • Dense FFN-streaming: สำหรับโมเดลขนาดใหญ่ที่ไม่ใช่ MoE โดยให้ Attention+Norm อยู่บน GPU และสตรีม FFN จาก NVMe
  • ขนาดพูลบัฟเฟอร์, ความลึกการพรีเฟตช์, งบหน่วยความจำ จะคำนวณอัตโนมัติตามโปรไฟล์ฮาร์ดแวร์

ประสิทธิภาพ

  • สภาพแวดล้อมทดสอบ: M1 Max, หน่วยความจำรวม 32GB, NVMe 5.1GB/s
  • ผลการวัดประสิทธิภาพหลัก
    • Qwen 2.5 14B Q4_K_M (8.4GB): โหลดเต็มบน GPU, 21 tok/s
    • Mixtral 8x7B Q5_K_M (30.9GB): โหมด Expert-streaming, 2.2 tok/s, แคชฮิตเรต 99.5%
    • Llama 3.3 70B Q4_K_M (39.6GB): โหมด Dense FFN-streaming, 0.3 tok/s, พูล 24 สล็อต, พรีเฟตช์ 7 ชั้น
  • โมเดลที่พอดีกับหน่วยความจำมี โอเวอร์เฮด 0 และโมเดลที่เกินหน่วยความจำก็ยัง คงสถานะพร้อมใช้งานได้ด้วย Hypura

การติดตั้งและการรัน

  • ต้องใช้ Rust 1.75+ และ CMake
  • ขั้นตอนการติดตั้ง
    git clone --recurse-submodules https://github.com/hypura/hypura.git  
    cd hypura  
    cargo build --release  
    
  • ตัวอย่างการรัน
    hypura profile  
    hypura run ./model.gguf --prompt "Hello, world"  
    hypura run ./model.gguf --interactive  
    hypura bench ./model.gguf  
    hypura inspect ./model.gguf  
    
  • สำหรับโมเดลที่ยังไม่ผ่านการตรวจสอบ แนะนำให้ทดสอบด้วย --max-tokens 10

เซิร์ฟเวอร์ที่เข้ากันได้กับ Ollama

  • Hypura มี HTTP API ที่เข้ากันได้กับ Ollama จึง เข้ากันได้เต็มรูปแบบกับเครื่องมือที่อิง Ollama เช่น OpenClaw
    hypura serve ./model.gguf  
    
    Endpoint: http://127.0.0.1:8080  
    
    API: /api/generate, /api/chat, /api/tags  
    
  • เอนด์พอยต์หลัก
    Endpoint ฟังก์ชัน
    GET / ตรวจสอบสถานะ
    GET /api/tags รายการโมเดลที่โหลดอยู่
    GET /api/version เวอร์ชันเซิร์ฟเวอร์
    POST /api/show เมทาดาทาของโมเดล
    POST /api/generate สร้างข้อความ
    POST /api/chat สร้างบทสนทนาแบบโต้ตอบ
  • การเชื่อมต่อ OpenClaw ให้กำหนด Ollama base URL เป็น Hypura ใน ~/.openclaw/openclaw.json
  • ตัวเลือกของเซิร์ฟเวอร์
    hypura serve  [OPTIONS]  
    --host    ค่าเริ่มต้น 127.0.0.1  
    --port    ค่าเริ่มต้น 8080  
    --context    ค่าเริ่มต้น 4096  
    

สถาปัตยกรรม

  • ใช้โครงสร้างแบบ Cargo workspace และประกอบด้วยสอง crate
    • hypura: ไบนารีหลักและไลบรารี
    • hypura-sys: FFI binding ของ llama.cpp (บิลด์ด้วย CMake)
  • โมดูลหลัก
    โมดูล บทบาท
    scheduler/placement.rs เพิ่มประสิทธิภาพการจัดวางเทนเซอร์ระหว่าง GPU/RAM/NVMe
    compute/inference.rs เอนจินอนุมานและฟังก์ชันโหลด/สร้างสำหรับเซิร์ฟเวอร์
    compute/nvme_backend.rs NVMe streaming, นิวรอนแคช, evaluation callback
    server/routes.rs HTTP handler ที่เข้ากันได้กับ Ollama
    profiler/ การโปรไฟล์ฮาร์ดแวร์
    cli/bench.rs เครื่องมือเบนช์มาร์ก
    model/tensor_role.rs การจัดประเภทบทบาทของเทนเซอร์

FAQ

  • ไม่มีปัญหาเรื่องอายุการใช้งาน SSD

    • Hypura อ่านจาก SSD เท่านั้น ไม่มีการเขียน
    • NVMe I/O ทำแบบอ่านอย่างเดียวด้วย pread() + F_NOCACHE
    • SSD ทำหน้าที่เพียง cold storage ส่วนการคำนวณทำบน RAM/GPU
    • การเขียนที่เกิดขึ้นมีเพียงระดับเล็กน้อยแค่ หน่วย KB เช่น JSON ผลเบนช์มาร์ก ไฟล์สถิติ เป็นต้น

แนวทางความปลอดภัย

  • หากโมเดลเกินขีดจำกัด RAM (เผื่อไว้ –4GB) จะบล็อก bench --baseline
  • สำหรับโมเดลที่ยังไม่ผ่านการตรวจสอบ ให้ทดสอบด้วย --max-tokens 10
  • โมเดลทดสอบถูกเก็บไว้ในไดเรกทอรี ./test-models/

ไลเซนส์

  • MIT License

ประกาศด้านจริยธรรม

  • โค้ดในรีโพซิทอรีไม่ได้เขียนขึ้นโดยผู้สร้างเองทั้งหมด
  • สร้างขึ้นจาก การทดลองสร้างโค้ดตามคำสั่งโดยใช้ LLM
  • เป็นโปรเจกต์เพื่อสำรวจความเป็นไปได้ของการอนุมานบน NVMe

1 ความคิดเห็น

 
GN⁺ 2026-03-25
ความคิดเห็นจาก Hacker News
  • อยากเสนอให้ผู้ดูแลพิจารณา ปัจจุบันตารางเปรียบเทียบยังมี โมเดลเก่า อย่าง Qwen 2.5 14B, Mixtral 8x7B และ Llama 3.3 70B อยู่
    ช่วงหลังมีรายงานมากมายว่าโมเดล Qwen 3.5 MoE ทำผลงานได้อย่างน่าทึ่งบนฮาร์ดแวร์ Apple
    ลองดู บทความของ Simon Willison ประกอบได้
    ถ้าเป็นไปได้ อยากให้เพิ่มโมเดล Kimi K2.5 (1T พารามิเตอร์) ลงในตารางด้วย
    ทวีตที่เกี่ยวข้อง: seikixtc, danpacary

    • ขอบคุณที่แชร์มา ถ้าคุณยินดีรันเบนช์มาร์กด้วย Hypura โดยตรง ฉันจะรวมผลเข้ากับสถิติให้ ไม่งั้นฉันจะเพิ่มไว้ใน todo list ของฉัน
    • Simon นอกเรื่องนิดหน่อย แต่เว็บของคุณ ล่ม ไปพักหนึ่ง
      มีข้อความผิดพลาดเกี่ยวกับ Heroku ขึ้นมา แต่ตอนนี้กลับมาใช้งานได้ตามปกติแล้ว
      ฉันเข้าไปดู โพสต์นี้ แล้วก็เห็นว่าคุณเขียนเรื่อง litellm ไว้แล้วด้วย อ่านได้ดีมาก
    • น่าเสียดายที่ในตัวอย่าง Kimi ไม่มี ตัวชี้วัดความเร็วโทเค็น
  • สำหรับงานในเครื่อง ความเร็วต่ำกว่า 1 โทเค็นต่อวินาทีก็ยัง ใช้งานได้ ถ้าเป็น งานเบื้องหลัง
    ความต่างระหว่าง “จบทันที” กับ “เสร็จข้ามคืน” ก็ยังเป็น การก้าวกระโดดด้านประสิทธิภาพ ที่มีความหมาย

  • ในความเป็นจริง สิ่งสำคัญคือรูปแบบการอ่านมีความ ต่อเนื่อง (sequential) แค่ไหน
    NVMe อ่านแบบต่อเนื่องได้ 5–7GB/s แต่ถ้าเป็นการอ่านแบบสุ่มจะลดลงเหลือราว 500MB/s
    สำหรับโมเดล 1T หากคิดแบบ fp16 จะต้องสตรีมข้อมูล 2TB ต่อหนึ่ง forward pass ดังนั้นตามทฤษฎีแล้วจะใช้เวลามากกว่า 300 วินาทีต่อโทเค็น
    ไม่เหมาะกับงานโต้ตอบ แต่ยังพอมีความเป็นไปได้สำหรับ batch inference

    • บน M1 Max การอ่านแบบสุ่ม 4K (QD=1) อยู่ที่ประมาณ 65MB/s
    • เห็นด้วย อันนี้ใกล้เคียง POC (Proof of Concept) มากกว่าจะใช้งานจริง
      แต่กับโมเดล MoE ขนาดเล็ก สามารถสร้างได้หลายโทเค็นต่อวินาที จึงพอใช้งานได้จริง
    • แก่นของโมเดล MoE คือ sparse activation
      ไม่ได้อ่านครบทั้ง 2TB แต่เข้าถึงเฉพาะ expert layer บางส่วน
      แต่ละเลเยอร์มีขนาดระดับไม่กี่ MiB ทำให้ประสิทธิภาพการเข้าถึง NVMe ก็ไม่ได้แย่นัก
  • ฉันสงสัยว่า “โมเดล 1T พารามิเตอร์” มาจากไหน เพราะในรีโปเห็นมีแต่โมเดล 70B หรือต่ำกว่า

    • พูดถึงในเชิงความเป็นไปได้เท่านั้น แต่ช้าเกินไปจนแทบไม่เหมาะใช้งานจริง นอกจาก งานระยะยาวเฉพาะทาง
      โมเดลที่สมจริงกว่าคือกลุ่ม MoE ที่เล็กกว่าแต่ยังสร้างได้หลายโทเค็นต่อวินาที
    • ชื่อเรื่องดูค่อนข้างเวอร์ไปหน่อย สุดท้ายสิ่งสำคัญคือ ความเร็ว แต่กลับไม่มีข้อมูลในส่วนนั้น
  • ประเด็นของ MoE คือด้วย sparse activation จึงไม่ต้องอ่านครบทั้ง 2TB
    แต่รูปแบบการเข้าถึงจะ กระจัดกระจายแบบสุ่ม ซึ่งเป็นเงื่อนไขที่แย่ที่สุดสำหรับ NVMe
    สำหรับงานอย่าง agent inference ที่ latency สำคัญ ประเด็นนี้ถือเป็นหัวใจหลัก

  • เหมือน Intel Optane จะพลิกตัวอยู่ในหลุมศพ

    • เมื่อ 10 ปีก่อน Memristor ก็ดูเหมือนใกล้ออกสู่ตลาดแล้ว แต่ตอนนี้หายไปหมดแล้ว
    • ฉันยังเก็บ Optane ใหม่อยู่ 4 ตัว ไม่ได้ล้อเล่นนะ มีจริง
      แต่ในทางปฏิบัติมันไม่ได้เร็วกว่า NVMe เท่าไร ซอฟต์แวร์ที่รองรับ การอ่าน/เขียนแบบขนาน แทบไม่เห็นความต่าง
    • เดี๋ยวนี้ชินแล้วที่ Intel ทำของดีแล้วก็ เลิกกลางคัน
      ถึงอย่างนั้นถ้าเอา 4 ตัวมามัด RAID 0 ก็น่าจะอัดแบนด์วิดท์ PCIe 16x ได้เต็ม
    • มีการพูดถึง pmem
  • ฮาร์ดแวร์ Mac สำหรับผู้บริโภคมีทั้ง unified memory และ NVMe ที่เร็ว แต่ความจุมีจำกัด
    ถ้าโหลดโมเดล 40GB บน M1 Max 32GB จะเกิด swap หนักมากและสุดท้ายเข้าสู่สถานะ panic
    macOS ไม่มี OOM killer แบบ Linux และจะลงเอยแค่พื้นที่ swap ไม่พอ

  • การมี “หน่วยความจำให้มากที่สุด” สำคัญก็จริง แต่ แบนด์วิดท์ (bandwidth) เป็นตัวแปรที่สำคัญกว่า
    M4 Pro อยู่ที่ 273GB/s, M4 Max ที่ 546GB/s และ M4 Ultra ที่ 819GB/s
    หลังจากโมเดลเข้าไปอยู่ในหน่วยความจำแล้ว แบนด์วิดท์จะเป็นตัวกำหนด ความเร็วโทเค็น
    สำหรับ Hypura นั้น M4 Max คือ sweet spot เพราะ 64GB ก็รันโมเดล 70B (Q4) ได้สบาย และสร้างได้เร็วกว่า Pro ราว 2 เท่า

  • โปรเจกต์นี้ทำงานคล้าย swap memory อัจฉริยะ
    จุดที่น่าสนใจคือมันคอยควบคุมไม่ให้ใช้ NVMe มากเกินไป
    แต่ถ้าใช้งาน NVMe หนักจริง ๆ ก็ยังน่ากังวลเรื่อง อายุการใช้งานที่สั้นลง

    • คำว่า “ทำให้ NVMe รับภาระหนัก” ฟังแปลก ๆ
      SSD มีอายุเซลล์ลดลงตามจำนวนครั้งที่เขียนก็จริง แต่แทบไม่มีกรณีที่ ภาระการอ่าน จะทำให้คอนโทรลเลอร์เสียหาย
      ถ้าเกิดแบบนั้นจริง แปลว่าระบบน่าจะมีปัญหาอย่างอื่น
  • น่าจะดีถ้าเอาโปรเจกต์นี้ไปเทียบกับการทดลองก่อนหน้า, ความพยายามอีกอัน
    อันนี้ใช้ mmap-based และมีรายงานว่า overhead สูง

    • โค้ดนั้น เขียนโดย LLM เลยเชื่อถือได้น้อย
    • อีกอย่าง implementation นี้ไม่ได้ใช้ quantization แบบแรงมาก จึงทำให้คุณภาพลดลงน้อยกว่า