GenAI Engineer Thailand #0 - Self-hosted LLM on GCP

GenAI Engineer Thailand #0 - Self-hosted LLM on GCP

ผ่านไปแล้วสำหรับอีเวนต์แรกของ GenAI Engineer Thailand (Discord group) กลุ่มนี้เกิดขึ้นเพราะพวกเราอยากให้มันเป็นที่รวมตัวของ practitioner ทั้งหลาย ได้มาแชร์ประสบการณ์กัน ที่สำคัญคือได้แลกเปลี่ยนความรู้กัน เอาเทคนิคไอเดียเด็ด ๆ มาแชร์แบ่งปันให้กันฟัง จะได้เอาไปต่อยอดใช้ในงานจริงได้ด้วย 😉

ในอีเวนต์นี้ เรามี speaker สุดพิเศษ คือคุณ Coco - Senior AI/ML Engineer จาก ArcFusion.ai มาแชร์เรื่องการ Deploy LLM บน GCP ให้ฟังกัน🌟

ในบทความนี้ ผมสรุปมาให้สำหรับใครที่พลาดไปนะฮะ

LLM is memory-bound

คุณ Coco บอกว่า การทำ Inference ของ LLM นั้นเป็นแบบ Memory-bound ไม่ใช่ Compute-bound นั่นหมายความว่า การโหลดข้อมูลเข้าไปใน GPU Memory ใช้เวลานานกว่าการประมวลผลข้อมูลซะอีก 😱 ดังนั้น Bottleneck หลักๆ คือขนาดโมเดล/prompt ที่ยัดเข้าไปใน GPU Memory ได้นั่นเอง

เราจะได้รู้ได้ยังไงว่า เป็น Compute-Bound หรือ Memory-Bound

เราต้องคำนวนหา Operation per byte (ops:byte) ออกมาก่อนฮะ

  • ถ้างานที่เราทำน้อยกว่า ops:byte ของ hardware แปลว่า เป็น memory-bound
  • แต่ถ้ามากกว่าก็เป็น compute-bound

คำนวน ops:byte ยังไง?

  • ops/byte = compute_bandwidth / memory_bandwidth
    เช่น Nvidia A10 มี compute_bandwidth (FP16 tensor core) = 125 TFLOPS และ GPU memory bandwidth อยู่ที่ 600 GB/s

นั่นแปลว่า

  • 125 TF / 600 GB/s
  • = 208.3 ops / bytes

Reference: https://www.baseten.co/blog/llm-transformer-inference-guide/

แล้วเราจะรู้ได้ยังไงว่า LLM ต้องใช้ กี่ ops:byte?

เราต้องหาจุดที่มีคำนวนเยอะที่สุดใน model ซึ่ง โดนส่วนใหญ่คือ ช่วง Attention Layers

https://www.baseten.co/blog/llm-transformer-inference-guide/

จากตัวอย่างในลิ้งข้างบน Llama2 7B จะมี 62 ops/byte

ถ้าเทียบกับการเอามารันบน A10 ก็จะเห็นว่า 62 ops/byte น้อยกว่า 208.3 ops/byte นั่นแปลว่า Llama2 7B จะติด memory bound

Quantization and Memory Optimization

ดังนั้นยิ่งเราจัดการ memory ได้ดีเท่าไหร่ก็จะสามารถเพิ่มความเร็วในการทำ Inference ได้ดีเช่นกัน เทคนิคที่คุณ Coco พูดถึงนั้น เช่น

  1. Quantization อย่าง AutoGPTQ, AWQ ที่ช่วยบีบอัดขนาดการเก็บข้อมูลให้เล็กลง 📉
  2. FlashAttention ที่ปรับแต่ง Attention Mechanism ใหม่ให้ไวขึ้น ⚡️
  3. Continuous Batching - Batching คือการรวบ (Batch) request ที่ขอเข้ามาเป็นก้อนเดียว แล้วรันพร้อมกัน ทำให้ไม่ต้องต่อคิว พร้อมกับคำว่า Continuous ทำให้ ไม่ต้องรอให้ batch ครบ ก็ประมวลได้เลย ลองจินตนาการแบบนี้ฮะ
    1. เวลาเราขึ้นรถตู้ ถ้าเป็น static batching คือ เรารอขึ้นรถตู้ทีละคน รถตู้ก็จะออกตามเวลา หรือเมื่อเต็ม
    2. ส่วน continuous batching คือ สมมติเรามีรถตู้ 3 คัน คิวรถตู้ก็จะดูว่าคันไหนว่างแล้วบอกเราว่า “ไอหนูไปขึ้นคันนั้นลูก” แล้วออกเลย
    3. ข้อดีคือ ”ไอหนู“ ก็ไม่ต้องรอ คันไหนว่างก็ขึ้นแล้ว let's go!

Ray Serve and vLLM

อีกอย่างที่ห้ามพลาดเลยก็คือ Framework อย่าง Ray Serve และ vLLM ครับ

  • Ray Serve เป็นตัวช่วยในการจัดการทรัพยากรสำหรับ ML ของเรา จะ scale เพิ่มลด cpu/gpu อะไรก็แก้ config ใช้ได้เลย
  • ส่วน vLLM ก็เป็น Inference Engine ที่ออกแบบมาสำหรับ LLM โดยเฉพาะ ตัว vLLM นี่คือจะ optimize memory ขั้นสุด ด้วยเทคนิคต่าง ๆ เช่น PagedAttention ทำให้โมเดลใหญ่ๆ ที่ต้องใช้ RAM เยอะ ก็รันได้อย่างไหลลื่น
    • ที่น่าสนใจไปอีกคือ vLLM มี Ray integrate มาให้แล้ว ดังนั้นกดรันได้เลยจ้า สบายตัว

Demonstration step-by-step

คุณ Coco ก็มา demo ให้เราดูครับว่า ถ้าเราจะรัน inference server ด้วย Ray และ vLLM เนี่ย step-by-step เลยมันทำยังไงบ้าง ตามไปดูกันฮะ

เพิ่มเติ่มเรื่อง Ray จากคุณเสือ (Tora) ครับ


Conclusion

สุดท้ายนี้ ขอขอบคุณทุกคนมากนะครับ ทั้งที่อ่าน และที่ฟังใน Live Session หวังว่าความรู้ดีๆ จากคุณ Coco จะเป็นประโยชน์กับเพื่อนๆ LLM practitioner ทุกคนนะครับ ขอบคุณที่อ่านกันมาถึงตรงนี้เลย Happy Deploying! 😉👍

Additional resources

บทความที่น่าสนใจฮะจากคุณ Natthanan Bhukan (MLE at CJ Express) เขียนอธิบายว่า vLLM ทำยังไงถึงรัน LLM ได้เร็ว

How does vLLM optimize the LLM serving system?
Let’s explore how vLLM optimizes the vLLM serving system without losing the accuracy of the model by using PageAttention.