วิธีตั้งค่า OLLAMA_NUM_PARALLEL และ OLLAMA_MAX_QUEUE
อธิบายการทำงานของ Ollama เมื่อมีคำขอพร้อมกันหลายรายการ พร้อมวิธีปรับค่า OLLAMA_NUM_PARALLEL และ OLLAMA_MAX_QUEUE เพื่อจัดการคิวและป้องกันข้อผิดพลาด HTTP 503 รวมถึงผลกระทบต่อ VRAM
จะเกิดอะไรขึ้นกับคำขอที่สองของ Ollama ในขณะที่คำขอแรกกำลังประมวลผล
การทำงานพร้อมกันของ Ollama ถูกกำหนดโดยตัวแปรสภาพแวดล้อม (environment variables) 3 ตัว โดยค่าเริ่มต้นโมเดลที่โหลดไว้หนึ่งตัวจะให้บริการได้ทีละหนึ่งคำขอเท่านั้น คำขอที่สองจะไม่ถูกปฏิเสธและจะไม่ได้รับคำตอบที่ไม่สมบูรณ์ แต่จะรออยู่ในคิวจนกว่าจะมีช่องว่างว่างลง จากนั้นจึงจะเริ่มประมวลผลด้วยความเร็วปกติ
คำขอที่เข้ามาจะมีผลลัพธ์ที่เป็นไปได้ 3 รูปแบบ คือ เริ่มประมวลผลทันทีในช่องว่างที่ว่างอยู่, รออยู่ในคิว หรือคิวเต็มแล้วเซิร์ฟเวอร์ปฏิเสธด้วย HTTP 503 ซึ่งผลลัพธ์ที่คุณได้รับจะถูกกำหนดโดย OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE และ OLLAMA_MAX_LOADED_MODELS
ค่าเริ่มต้นมีความปลอดภัย ซึ่งเป็นเหตุผลว่าทำไมผู้ใช้คนที่สองจึงรายงานว่าเซิร์ฟเวอร์ "ค้าง" ทั้งที่ไม่มีอะไรเสียหาย การเพิ่มช่องว่าง (slots) สามารถทำได้โดยการแก้ไขเพียงสองบรรทัด สิ่งที่ต้องระวังคือหน่วยความจำ ช่องว่างแบบขนานแต่ละช่องต้องการ key/value cache (KV cache) ของตัวเอง ซึ่งเป็นบล็อกหน่วยความจำที่โมเดลใช้เก็บโทเค็นที่ประมวลผลไปแล้ว หากคุณเพิ่มช่องว่างโดยไม่เพิ่ม VRAM (หน่วยความจำวิดีโอบน GPU) จะทำให้การตอบสนองที่ช้ากลายเป็นการโหลดล้มเหลวแทน
การควบคุมของ OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE และ OLLAMA_MAX_LOADED_MODELS
นี่คือค่าเริ่มต้นใน Ollama รุ่นปัจจุบัน ณ เดือนสิงหาคม 2026 โปรดตรวจสอบค่าของคุณเองแทนการเชื่อตัวเลขที่ระบุไว้ ณ ที่นี้ โดยดูจากบรรทัด log ที่แสดงไว้ด้านล่าง
OLLAMA_NUM_PARALLELคือจำนวนคำขอที่โมเดลที่โหลดไว้หนึ่งตัวสามารถจัดการได้พร้อมกัน ค่าเริ่มต้นคือ 1 ซึ่งหมายความว่าคำขอจะถูกประมวลผลทีละรายการOLLAMA_MAX_LOADED_MODELSคือจำนวนโมเดลที่แตกต่างกันที่สามารถคงอยู่ในหน่วยความจำได้พร้อมกัน ค่าเริ่มต้นคือ 0 ซึ่งหมายความว่า Ollama จะเลือกค่าให้เอง: คือ 3 โมเดลต่อ GPU หนึ่งตัว และ 3 โมเดลสำหรับเครื่องที่ไม่มี GPUOLLAMA_MAX_QUEUEคือจำนวนคำขอที่สามารถรออยู่ในคิวได้ ค่าเริ่มต้นคือ 512 คำขอที่เข้ามาในขณะที่คิวเต็มจะถูกปฏิเสธทันที
หน่วยความจำในกรณีที่เลวร้ายที่สุดคือผลคูณของสองค่าแรก หากโหลดโมเดล 2 ตัวโดยมีช่องรองรับตัวละ 4 ช่อง จะเท่ากับการจัดสรรพื้นที่ KV cache ทั้งหมด 8 ช่องที่ต้องอยู่ในหน่วยความจำพร้อมกัน ซึ่ง Ollama จะพยายามจัดสรรให้ตามนั้น สำหรับเครื่องที่มี GPU เพียงตัวเดียว การเก็บโมเดลไว้เพียงตัวเดียวแล้วเพิ่มจำนวนช่องรองรับมักจะเป็นทางเลือกที่ดีกว่า เพราะการคำนวณจะยังคงอยู่ในระดับที่คุณสามารถประเมินได้ด้วยตัวเอง
เหตุผลที่ทุก parallel slot ต้องใช้ VRAM
เมื่อ Ollama โหลดโมเดล มันจะเปิดกระบวนการ runner แยกออกมาต่างหาก โดยมีอาร์กิวเมนต์สองตัวที่ส่งผ่านเข้ามาซึ่งมีความสำคัญในที่นี้ คือ -c ซึ่งเป็นบริบททั้งหมดที่ runner จัดสรร KV cache ไว้ให้ และ -np ซึ่งเป็นจำนวนลำดับงานแบบขนาน Ollama จะตั้งค่า -c ให้เท่ากับความยาวบริบทต่อคำขอของคุณคูณด้วยจำนวน slot จากนั้น runner จะแบ่งพื้นที่ทั้งหมดนั้นให้แต่ละ slot เท่าๆ กัน เพื่อให้แต่ละคำขอยังคงได้รับความยาวบริบทตามที่คุณต้องการ
นี่คือข้อจำกัดทั้งหมด และเป็นเหตุผลว่าทำไมการประมวลผลแบบขนานจึงไม่ใช่สิ่งที่ได้มาฟรีๆ การเพิ่มจาก 1 slot เป็น 4 slot หมายถึงการต้องการ KV cache เพิ่มขึ้น 4 เท่าที่ความยาวบริบทต่อคำขอเท่าเดิม ข้อมูลไม่มีการแชร์กันระหว่าง slot และ slot ที่ว่างอยู่ก็ไม่สามารถแบ่งพื้นที่ให้ slot ที่กำลังทำงานได้ เพราะการแบ่งพื้นที่ถูกกำหนดไว้ตายตัวตั้งแต่ตอนที่ runner เริ่มทำงาน
คุณสามารถอ่านค่าตัวเลขจริงแทนค่าที่คุณตั้งใจจะกำหนดได้จาก:
journalctl -u ollama --no-pager -n 500 | grep "starting llama-server"บรรทัดนั้นจะแสดงคำสั่ง runner ทั้งหมด รวมถึง -c และ -np หาก -np ยังคงเป็น 1 หลังจากที่คุณตั้งค่าตัวแปรไปแล้ว แสดงว่าการตั้งค่านั้นยังส่งไปไม่ถึงเซิร์ฟเวอร์ ซึ่งส่วนถัดไปจะอธิบายถึงสาเหตุ
หากน้ำหนักของโมเดลรวมกับ KV cache นั้นไม่พอดีกับ VRAM Ollama จะย้ายบางเลเยอร์ไปไว้ใน system RAM และเลเยอร์เหล่านั้นจะทำงานบน CPU ซึ่งเลเยอร์ที่ทำงานบน CPU จะช้ากว่าเลเยอร์บน GPU มาก ส่งผลให้ทุกคำขอช้าลง รวมถึงคำขอเดียวที่คุณเริ่มไว้ตั้งแต่แรก ดังนั้นการเพิ่มจำนวนการประมวลผลแบบขนานอาจทำให้ throughput ลดลงแทนที่จะเพิ่มขึ้น สำหรับโมเดลที่มีขนาดใหญ่มาก แค่น้ำหนักของโมเดลเพียงอย่างเดียวก็เป็นตัวตัดสินก่อนที่จะเริ่มคำนวณเรื่อง slot เสียอีก ซึ่งเป็นเหตุผลว่าทำไม การ self-host โมเดลขนาดเท่า Kimi K3 จึงเป็นการสนทนาเรื่องจำนวนการ์ดที่คุณมี มากกว่าจำนวน slot ที่คุณตั้งค่าไว้
ollama psคอลัมน์ PROCESSOR จะแสดงค่า 100% GPU เมื่อทุกอย่างโหลดลง VRAM ได้พอดี การแบ่งส่วนแบบ 35%/65% CPU/GPU หมายความว่าโมเดลบางส่วนกำลังทำงานบน CPU คอลัมน์ SIZE จะรวม KV cache ไว้ด้วย ดังนั้นมันจะเพิ่มขึ้นเมื่อคุณเพิ่มจำนวน slot และโหลดโมเดลใหม่ ให้ลองเพิ่ม OLLAMA_NUM_PARALLEL, รีสตาร์ท, ส่งคำขอหนึ่งรายการ แล้วรัน ollama ps อีกครั้ง นั่นคือต้นทุนหน่วยความจำจากการเปลี่ยนแปลงของคุณ ซึ่งเป็นการวัดค่าจริงไม่ใช่การคาดเดา หากการวัดนั้นระบุว่าโมเดลไม่พอดีกับหน่วยความจำอีกต่อไป โปรดจำไว้ว่าน้ำหนักของโมเดลคืออีกครึ่งหนึ่งของงบประมาณเดียวกัน และ การเปลี่ยนจาก fp16 ไปเป็น build แบบ q8 หรือ q4 มักจะช่วยคืนพื้นที่ VRAM ได้มากกว่าต้นทุนของ slot ที่คุณพยายามจะเพิ่มเข้าไป
ความยาวบริบทและจำนวน slot จะคูณกัน ดังนั้นจึงต้องเลือกไปพร้อมกัน บริบทขนาดใหญ่ที่มี 4 slot ก็คือบริบทขนาดใหญ่ 4 ชุด หากคุณกำลังปรับแต่ง หน้าต่างบริบท num_ctx สำหรับโมเดลของคุณ ให้เปลี่ยนทีละค่า มิฉะนั้นคุณจะไม่ทราบว่าค่าใดกันแน่ที่ทำให้การ์ดหน่วยความจำเต็ม
วิธีการตั้งค่าตัวแปรเหล่านี้ให้คงอยู่หลังการรีบูต
บน Linux นั้น Ollama ทำงานในรูปแบบของ systemd service การรัน export OLLAMA_NUM_PARALLEL=4 ใน shell ของคุณจะไม่ส่งผลใดๆ เนื่องจาก systemd เริ่มต้น service ด้วย environment ของตัวเองและไม่ได้รับรู้ถึง shell ของคุณ ให้ใช้ไฟล์ drop-in แทน
sudo systemctl edit ollama.serviceเพิ่มข้อความนี้ลงในโปรแกรมแก้ไขข้อความที่เปิดขึ้นมา:
[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_MAX_QUEUE=32"จากนั้นโหลดการตั้งค่าใหม่และรีสตาร์ท service:
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environmentsystemctl show จะแสดงสิ่งที่ systemd ส่งให้กับกระบวนการทำงาน หากตัวแปรของคุณไม่ปรากฏในนั้น แสดงว่าไฟล์ drop-in ไม่ได้ถูกบันทึกหรือมีการข้ามขั้นตอน daemon-reload ไป ให้ตรวจสอบจากฝั่งของเซิร์ฟเวอร์โดยตรงด้วย:
journalctl -u ollama --no-pager | grep "server config" | tail -1Ollama จะบันทึก environment ทั้งหมดของตนเองไว้ใน log เมื่อเริ่มต้นทำงานในบรรทัดที่มีข้อความว่า server config ข้อมูลในส่วนนั้นคือค่าจริงที่ถูกใช้งาน ซึ่งเป็นวิธีที่รวดเร็วที่สุดในการยุติข้อสงสัยว่าตัวแปรมีผลหรือไม่
โมเดลที่ถูกโหลดไว้แล้วจะยังคงใช้จำนวน slot เดิมที่ถูกกำหนดไว้ตอนเริ่มต้น เนื่องจากค่าดังกล่าวถูกกำหนดตายตัวในกระบวนการทำงาน (runner process) ตั้งแต่ตอนเปิดใช้งาน การรีสตาร์ทตามขั้นตอนข้างต้นจะทำการ unload ทุกอย่างออก ดังนั้นคำขอถัดไปจะทำการโหลดโมเดลใหม่ด้วยการตั้งค่าใหม่และใช้เวลาในการโหลดเพียงครั้งเดียว ส่วนระยะเวลาที่โมเดลจะยังคงอยู่ในหน่วยความจำหลังจากนั้นเป็นการควบคุมแยกต่างหาก ซึ่งอธิบายไว้ใน การคงโมเดล Ollama ไว้ในหน่วยความจำระหว่างคำขอ
สถานะ served, queued และ refused ในมุมมองของไคลเอนต์
ส่งคำขอหลายรายการพร้อมกันและจับเวลา การดำเนินการนี้จะรัน streaming requests แบบขนานจำนวน 8 รายการ และแสดงสถานะรวมถึงเวลาที่ใช้สำหรับแต่ละรายการ:
for i in $(seq 1 8); do
curl -s -o /dev/null \
-w "req$i http=%{http_code} ttfb=%{time_starttransfer}s total=%{time_total}s\n" \
http://127.0.0.1:11434/api/generate \
-d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":true}' &
done
waitttfb คือเวลาจนกว่าจะได้รับไบต์แรกของสตรีม ซึ่งใกล้เคียงกับเวลาจนกว่าจะได้รับโทเค็นแรก (TTFT) เนื่องจาก chunk แรกที่สตรีมมานั้นมีโทเค็นแรกอยู่ด้วย
Served in parallel (ให้บริการแบบขนาน): ทุกคำขอจะรายงานค่า ttfb ที่ใกล้เคียงกัน และ total จะเพิ่มขึ้นสำหรับทุกคำขอพร้อมกัน GPU จะถูกแชร์ระหว่างสล็อตที่กำลังทำงานอยู่ ดังนั้นคำตอบแต่ละรายการจึงช้ากว่าการรันเพียงลำพัง แต่จะมีจำนวนคำตอบที่เสร็จสิ้นต่อนาทีมากขึ้น นี่คือสภาวะที่คุณได้รับเมื่อเพิ่มค่า OLLAMA_NUM_PARALLEL
Queued (อยู่ในคิว): คำขอแรกๆ จะได้รับคำตอบอย่างรวดเร็ว ส่วนคำขอหลังๆ จะแสดงค่า ttfb ที่สูงตามด้วยการสร้างข้อความตามปกติ ระยะเวลาที่รอคือคิว ไม่ใช่ตัวโมเดล ผู้ใช้ที่ดูหน้าต่างแชทจะเห็นการหยุดชะงักที่ว่างเปล่านานๆ แล้วจึงเห็นข้อความปรากฏขึ้นด้วยความเร็วเต็มที่ รูปแบบที่เริ่มช้าแล้วเร็วในภายหลังนี้คือลักษณะเฉพาะของคิว ไม่ใช่การที่ GPU ทำงานหนักเกินไป
Refused (ถูกปฏิเสธ): ไคลเอนต์จะได้รับ http=503 เกือบจะทันที โดยมีเนื้อหาดังนี้:
{"error":"server busy, please try again. maximum pending requests exceeded"}ข้อความดังกล่าวหมายความว่าคิวเต็มในขณะที่คำขอส่งเข้ามา ไม่ได้ระบุถึง VRAM หรือตัวโมเดลแต่อย่างใด
ข้อจำกัดที่ชัดเจนประการหนึ่งคือ Ollama ไม่ได้เผยแพร่ความลึกของคิว ollama ps และ endpoint /api/ps จะรายงานเฉพาะโมเดลที่โหลดอยู่เท่านั้น ไม่ใช่จำนวนคำขอที่กำลังรออยู่ ดังนั้นคุณต้องวัดคิวจากฝั่งไคลเอนต์ โดยการสังเกตเวลาจนกว่าจะได้รับไบต์แรก หรือนับจำนวนการตอบกลับแบบ 503 จากสิ่งที่อยู่หน้าบริการของคุณ
เหตุใดการตั้งค่า MAX_QUEUE ให้มีขนาดเล็กลงจึงมักเป็นทางเลือกที่ดีกว่า
คิวขนาด 512 ฟังดูเหมือนจะมากพอ แต่ในทางปฏิบัติสำหรับช่องทางเดียว (single slot) นั้นแทบไม่มีประโยชน์เลย คำขอที่ 300 จะต้องรอให้คำขอก่อนหน้าประมวลผลเสร็จสิ้นถึง 299 รายการ ซึ่งในกรณีที่ดีที่สุดอาจใช้เวลาหลายนาที โดยปกติแล้ว HTTP client ทุกตัวจะยกเลิกการเชื่อมต่อก่อนหน้านั้นนานแล้ว ส่งผลให้ผู้เรียกใช้งานพบกับข้อผิดพลาด client side timeout ซึ่งไม่ได้ระบุสาเหตุที่แท้จริงและไม่ทำให้ระบบตรวจสอบของคุณแจ้งเตือนแต่อย่างใด
คุณควรตั้งค่าคิวให้มีขนาดใกล้เคียงกับจำนวนคำขอที่เซิร์ฟเวอร์ของคุณสามารถประมวลผลได้เสร็จสิ้นภายในระยะเวลา timeout ของ client เพื่อให้คำขอที่เกินมาได้รับสถานะ 503 ทันที การตอบกลับด้วย 503 นั้นมีประโยชน์มากกว่า เพราะ reverse proxy สามารถลองส่งคำขอใหม่ได้, client สามารถรอจังหวะส่งใหม่ (back off), แดชบอร์ดสามารถนับจำนวนข้อผิดพลาดได้ และผู้ดูแลระบบสามารถอ่านค่านี้ได้ คุณควรคำนวณตัวเลขนี้จากการวัดผลด้วยตนเอง หากการประมวลผลหนึ่งรายการใช้เวลาประมาณ 10 วินาทีและ client ของคุณรอได้ 60 วินาที แสดงว่าในหนึ่งช่องทางจะสามารถประมวลผลได้ประมาณ 6 คำขอภายในช่วงเวลานั้น ดังนั้นการตั้งค่าคิวให้ลึกกว่านั้นจึงมีแต่จะทำให้เกิด timeout เพิ่มขึ้นเท่านั้น
เมื่อใดที่ควรวางคิวไว้หน้า Ollama
คิวในตัวของ Ollama ทำงานแบบเข้าก่อนออกก่อน (FIFO) และไม่ทราบว่าใครเป็นผู้เรียกใช้งาน สำหรับแอปพลิเคชันเดียวที่ติดต่อกับเซิร์ฟเวอร์เดียว วิธีนี้เพียงพอแล้ว และการเพิ่มโครงสร้างพื้นฐานเข้าไปจะเพิ่มเพียงจุดที่อาจเกิดความล้มเหลวเท่านั้น ควรพิจารณาเพิ่มระบบคิวไว้ด้านหน้าเมื่อเข้าเงื่อนไขต่อไปนี้
- คุณต้องการจัดลำดับความสำคัญ: การแชทโต้ตอบไม่ควรต้องรอต่อคิวหลังงานสรุปผลแบบกลุ่ม (batch summarisation) คิวของ Ollama ไม่มีการจัดลำดับความสำคัญ ดังนั้นงานแบบกลุ่มจึงต้องถูกพักไว้ภายนอกและค่อยๆ ป้อนเข้าสู่ระบบ
- คุณต้องการความยุติธรรม: ไคลเอนต์รายเดียวอาจเติมคิวจนเต็มได้ด้วยตัวเอง ส่งผลให้ผู้ใช้งานรายอื่นได้รับข้อผิดพลาด 503 ทั้งหมด
- คุณต้องการให้งานยังคงอยู่หลังจากการรีสตาร์ท: คิวจะอยู่ในหน่วยความจำของเซิร์ฟเวอร์ หากรีสตาร์ท Ollama คำขอที่กำลังรออยู่ทั้งหมดจะหายไป
- คุณต้องการระบบการลองใหม่ (retry) พร้อมการหน่วงเวลา (backoff) ที่บันทึกไว้ในที่ที่คุณสามารถตรวจสอบย้อนหลังได้
ทางเลือกแบบเบาคือการใช้ reverse proxy ใน nginx คุณสามารถใช้ limit_conn เพื่อจำกัดจำนวนการเชื่อมต่อพร้อมกัน และใช้ limit_req เพื่อจำกัดอัตราการเข้ามาของคำขอต่อไคลเอนต์ ดังนั้นคำขอที่เกินกำหนดจะถูกปฏิเสธที่ตัว proxy และไม่เข้าสู่คิวของ Ollama ทางเลือกแบบหนักคือการใช้ job queue ร่วมกับฐานข้อมูลวางไว้หน้า worker ที่ทำหน้าที่เรียก Ollama ซึ่งเป็นสิ่งที่คุณต้องการเมื่อคำขอจำเป็นต้องคงอยู่แม้มีการรีสตาร์ทกระบวนการ การคำนวณขนาดระบบสำหรับ traffic จริงเป็นเรื่องเฉพาะตัว: การวางแผนสำหรับ LLM แบบ self-hosted เพื่อรองรับผู้ใช้พร้อมกัน จะอธิบายถึงการคำนวณ และ การรัน Ollama บน VPS จะครอบคลุมถึงการติดตั้งพื้นฐานที่ตัวแปรเหล่านี้อ้างอิงถึง
เมื่อคำตอบที่ถูกต้องคือการใช้เซิร์ฟเวอร์อื่น
มีขีดจำกัดที่คุณไม่สามารถแก้ไขได้ด้วยการปรับแต่งค่า Ollama จะแบ่ง KV cache ออกเป็นช่องที่มีขนาดเท่ากันและคงที่เมื่อโหลดโมเดล หน่วยความจำของช่องที่ว่างอยู่จะไม่สามารถนำไปใช้กับช่องที่กำลังทำงานอยู่ได้ และจำนวนช่องจะไม่สามารถเปลี่ยนแปลงได้หากไม่ยกเลิกการโหลดโมเดลก่อน การออกแบบนี้เหมาะสมสำหรับผู้ใช้คนเดียว ทีมขนาดเล็ก หรือ coding agent
เซิร์ฟเวอร์ที่สร้างมาเพื่อรองรับผู้ใช้จำนวนมากพร้อมกันจะทำงานต่างออกไป โดยจะจัดสรร KV cache เป็นหน้า (page) ขนาดเล็กตามความต้องการ และเพิ่มคำขอที่เข้ามาใหม่เข้าไปใน batch ที่กำลังทำงานอยู่ ดังนั้นหน่วยความจำจะถูกใช้ตามความต้องการจริงแทนที่จะแบ่งส่วนแบบคงที่ หากเป้าหมายของคุณคือการรองรับผู้ใช้จำนวนมากพร้อมกันบน GPU เดียว ความแตกต่างทางสถาปัตยกรรมนี้มีความสำคัญมากกว่าค่าใดๆ ของ OLLAMA_NUM_PARALLEL การเปรียบเทียบระหว่าง Ollama และ vLLM คือจุดที่คุณควรใช้ตัดสินใจ อย่างไรก็ตาม อย่าเปลี่ยนเพียงเพราะหลักการ เนื่องจากเซิร์ฟเวอร์อื่นต้องใช้การดูแลรักษามากกว่า และหากปริมาณการใช้งานของคุณมีเพียงไม่กี่คน พฤติกรรมที่มาพร้อมกับตัวโปรแกรมถือเป็นคำตอบที่ถูกต้องแล้ว
วัดปริมาณงานและเวลาจนถึงโทเค็นแรกของคุณเอง
ตัวเลขจำนวนโทเค็นต่อวินาทีที่เผยแพร่อยู่ทั่วไปนั้นมาจาก GPU, โมเดล, การทำ quantisation, ความยาวบริบท และ prompt ของผู้อื่น ซึ่งไม่มีสิ่งใดตรงกับของคุณ ดังนั้นให้ถือว่าตัวเลขเหล่านั้นเป็นเพียงแนวทางคร่าวๆ และให้วัดผลจากเครื่องที่อยู่ตรงหน้าคุณแทน
Ollama จะส่งคืนค่าเวลาไว้ในออบเจกต์ JSON สุดท้ายของทุกการตอบกลับ โดย eval_count คือจำนวนโทเค็นที่สร้างขึ้น และ eval_duration คือเวลาที่ใช้ในการสร้างโทเค็นเหล่านั้นในหน่วยนาโนวินาที
sudo apt install -y jq
curl -s http://127.0.0.1:11434/api/generate \
-d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":false}' \
| jq '{prompt_eval_count, eval_count, eval_duration, tokens_per_second: (.eval_count / (.eval_duration / 1000000000))}'ให้รันคำสั่งดังกล่าวด้วย 1 slot จากนั้นรันอีกครั้งด้วยระดับ concurrency ที่คุณคาดการณ์ไว้จริง แล้วเปรียบเทียบตัวเลขสองค่าที่เป็นตัวตัดสินว่าผู้ใช้งานจะพึงพอใจหรือไม่ ได้แก่ เวลาจนถึงโทเค็นแรก (time to first token) และจำนวนโทเค็นต่อวินาทีต่อคำขอ (tokens per second per request) ปริมาณงานต่อคำขอจะลดลงเสมอเมื่อมีการเพิ่มจำนวน slot คำถามคือมันลดลงเกินกว่าที่ผู้ใช้งานของคุณจะยอมรับได้หรือไม่ การวัดจำนวนโทเค็นต่อวินาทีบน LLM ในเครื่อง ครอบคลุมวิธีการดังกล่าวในรายละเอียดเพิ่มเติม รวมถึงวิธีรักษาค่า prompt ให้คงที่ระหว่างการทดสอบแต่ละครั้ง
Public endpoint ที่มีคิวขนาดใหญ่เป็นเป้าหมายของการโจมตีแบบ Denial of Service
การตั้งค่า OLLAMA_HOST=0.0.0.0:11434 จะทำให้ API เปิดใช้งานบนทุกอินเทอร์เฟซ และ Ollama ไม่มีระบบยืนยันตัวตนในตัว Endpoint ที่เปิดสาธารณะพร้อมคิวเริ่มต้นจะยอมรับคำขอที่รอประมวลผลได้ถึง 512 รายการจากใครก็ตามที่พบ endpoint นี้ การทำให้คิวเต็มนั้นแทบไม่มีต้นทุนสำหรับผู้โจมตี ไม่ว่าจะเป็นการส่ง prompt ที่ยาว การไม่ต้องล็อกอิน การไม่มีการจำกัดอัตราการเรียกใช้ (rate limit) หรือไม่มีค่าใช้จ่าย ผู้ใช้งานจริงของคุณจะได้รับข้อความตอบกลับเป็น 503 หรือต้องรอเป็นเวลานาน ในขณะที่เครื่องเซิร์ฟเวอร์ต้องทำงานหนักตลอดเวลา
ควรให้ listener ทำงานบน loopback เท่านั้นและเข้าถึงผ่าน SSH tunnel หรือเครือข่ายส่วนตัว หรือวางระบบยืนยันตัวตนและจำกัดอัตราการเรียกใช้ไว้ด้านหน้า การรักษาความปลอดภัยให้กับ Ollama API endpoint ครอบคลุมทั้งสองวิธี หลังจากดำเนินการดังกล่าวแล้วจึงค่อยปรับแต่งขนาดคิว เนื่องจากความยาวของคิวเป็นเพียงการตั้งค่าขีดความสามารถในการรองรับเท่านั้น และไม่ได้ช่วยป้องกันการโจมตีแต่อย่างใด
FAQ
ทำไมคำขอที่สองของฉันถึงต้องรอให้คำขอแรกของ Ollama ทำงานเสร็จก่อน?
เพราะ OLLAMA_NUM_PARALLEL มีค่าเริ่มต้นเป็น 1 ทำให้โมเดลที่โหลดอยู่ประมวลผลได้ทีละคำขอ ส่วนคำขอที่เหลือจะต้องรอตามลำดับ คำขอที่รออยู่จะค้างการเชื่อมต่อ HTTP ไว้และไม่ส่งข้อมูลใดๆ จนกว่าจะมีช่องว่างว่างลง ซึ่งในฝั่งไคลเอนต์จะดูเหมือนโมเดลทำงานช้า วิธีสังเกตคือดูรูปแบบของเวลา: หากมีการหยุดชะงักนานแล้วข้อความค่อยปรากฏออกมาด้วยความเร็วเต็มที่ แสดงว่าเกิดการเข้าคิว แต่ถ้าข้อความค่อยๆ ไหลออกมาอย่างช้าๆ ตั้งแต่โทเค็นแรก แสดงว่าโมเดลทำงานช้าจริง คุณสามารถเพิ่มจำนวนช่องว่าง (slot) ได้โดยการแก้ไขผ่าน systemd drop-in แล้วรีสตาร์ทเซอร์วิส
ข้อความ "server busy, please try again. maximum pending requests exceeded" หมายความว่าอย่างไร?
นี่คือข้อผิดพลาดเมื่อคิวของ Ollama เต็ม ซึ่งจะตอบกลับด้วยสถานะ HTTP 503 จำนวนคำขอที่รออยู่ในคิวได้ถึงขีดจำกัดของ OLLAMA_MAX_QUEUE แล้ว (ค่าเริ่มต้นคือ 512) คำขอใหม่ล่าสุดจึงถูกปฏิเสธแทนที่จะถูกเพิ่มเข้าไปในคิว นี่ไม่ใช่ข้อผิดพลาดเกี่ยวกับหน่วยความจำหรือโมเดล การเพิ่มขนาดคิวจะทำให้ผู้เรียกต้องรอคิวนานขึ้นก่อนที่จะถูกปฏิเสธเหมือนเดิม ดังนั้นวิธีแก้ไขที่แท้จริงคือการเพิ่มจำนวนช่องว่างหากคุณมี VRAM เพียงพอ, ลดปริมาณงานที่เข้ามา หรือใช้ระบบคิวหน้าเซิร์ฟเวอร์ที่สามารถลองใหม่และจัดลำดับความสำคัญได้
การเพิ่ม OLLAMA_NUM_PARALLEL ทำให้ Ollama ทำงานเร็วขึ้นหรือไม่?
ไม่ การตั้งค่านี้ช่วยให้คำขอจำนวนมากขึ้นทำงานพร้อมกันได้ แต่ละคำขอจะทำงานช้าลงกว่าการรันเพียงลำพังเพราะต้องแชร์ GPU ร่วมกัน นอกจากนี้ยังเป็นการเพิ่มการใช้ KV cache เนื่องจาก Ollama จะเริ่มกระบวนการรันโมเดลด้วยบริบททั้งหมดเท่ากับความยาวบริบทของคุณคูณด้วยจำนวนช่องว่าง หากผลลัพธ์ไม่สามารถเก็บใน VRAM ได้ Ollama จะผลักเลเยอร์ไปที่ CPU ซึ่งจะทำให้ทุกคำขอช้าลง แม้แต่คำขอเดียวที่ไม่มีการแย่งทรัพยากร ให้ตรวจสอบ ollama ps หลังจากเปลี่ยนค่าและยืนยันว่าคอลัมน์ PROCESSOR ยังคงแสดงค่าเป็น 100% GPU
ฉันจำเป็นต้องรีสตาร์ท Ollama หลังจากเปลี่ยนตัวแปรเหล่านี้หรือไม่?
ใช่ เซิร์ฟเวอร์จะอ่านค่าเหล่านี้ตอนเริ่มต้นทำงาน และโมเดลที่รันอยู่จะคงจำนวนช่องว่างที่กำหนดไว้ในกระบวนการรันโมเดลตั้งแต่ตอนเปิดใช้งาน ให้แก้ไขไฟล์ drop-in ด้วย sudo systemctl edit ollama.service จากนั้นรัน sudo systemctl daemon-reload และ sudo systemctl restart ollama เพื่อยืนยันด้วย systemctl show ollama --property=Environment แล้วตรวจสอบบรรทัด server config ใน journalctl -u ollama ซึ่งจะแสดงรายการ environment ที่เซิร์ฟเวอร์โหลดใช้งานจริง
ฉันควรตั้งค่าจำนวนช่องว่างขนานเท่าใด?
ให้เริ่มที่ 1 แล้วค่อยๆ เพิ่มทีละขั้น หลังจากแต่ละขั้นตอน ให้รีสตาร์ท Ollama ส่งคำขอหนึ่งครั้งเพื่อโหลดโมเดล แล้วรัน ollama ps ให้หยุดที่ค่าสุดท้ายที่ PROCESSOR ยังคงแสดงค่าเป็น 100% GPU และคอลัมน์ SIZE ยังมีพื้นที่เหลือเพียงพอสำหรับบริบทที่ยาวที่สุดที่คุณให้บริการ จากนั้นให้วัดเวลาจนถึงโทเค็นแรก (time to first token) และจำนวนโทเค็นต่อวินาทีที่การตั้งค่านั้นภายใต้การใช้งานจริงของคุณ หากความเร็วต่อคำขอลดลงจนต่ำกว่าระดับที่ผู้ใช้ของคุณยอมรับได้ ให้ลดค่าลงหนึ่งระดับ