เปรียบเทียบ Ollama Quantization: q4_K_M, q8_0 และ fp16
เลือกขนาด Quantization ใน Ollama ให้เหมาะกับ RAM ของคุณ เรียนรู้ความแตกต่างของ q4_K_M, q8_0 และ fp16 พร้อมวิเคราะห์จุดคุ้มทุนของประสิทธิภาพและความแม่นยำที่ลดลง
การเปลี่ยนแปลงของการทำ quantization ใน Ollama
การทำ quantization ใน Ollama คือการจัดเก็บน้ำหนัก (weight) แต่ละตัวในโมเดลด้วยจำนวนบิตที่น้อยลงกว่าไฟล์ที่ใช้ฝึกฝนมา แท็กที่ลงท้ายด้วย q4_K_M จะเก็บข้อมูลประมาณ 4 บิตต่อหนึ่งน้ำหนัก ในขณะที่ fp16 จะเก็บ 16 บิต ส่งผลให้ขนาดไฟล์ดาวน์โหลดลดลงเหลือประมาณหนึ่งในสาม และเครื่องจะอ่านข้อมูลจำนวนไบต์น้อยลงประมาณหนึ่งในสามเพื่อสร้างแต่ละโทเค็น น้ำหนักเหล่านี้จะถูกปัดเศษลงบนตารางที่หยาบขึ้น ไม่ได้ถูกตัดทิ้งไป และที่ระดับ 4 บิต โมเดลส่วนใหญ่ยังคงให้คำตอบได้ใกล้เคียงกับระดับความแม่นยำเต็มรูปแบบ
นี่คือข้อแลกเปลี่ยนทั้งหมด: การใช้หน่วยความจำที่น้อยลงมากและได้จำนวนโทเค็นต่อวินาทีที่มากขึ้น โดยแลกกับความแม่นยำที่ลดลงเล็กน้อย เนื้อหาต่อไปนี้คือวิธีการคาดการณ์ผลลัพธ์ทั้งสองด้านสำหรับโมเดลเฉพาะบนเครื่องเฉพาะ ก่อนที่คุณจะเสียเวลา 20 นาทีในการดาวน์โหลดไฟล์ที่ไม่สามารถใช้งานได้
หาก Ollama ยังไม่ทำงาน ให้เริ่มต้นด้วย การติดตั้ง Ollama บน VPS หน้าเว็บนี้อนุมานว่า ollama ls ทำงานได้ตามปกติแล้ว
วิธีอ่านแท็กการทำ quantization ของ Ollama เช่น q4_K_M
โมเดลในเครื่องจะถูกส่งมาในรูปแบบไฟล์ GGUF ซึ่งเป็นฟอร์แมตที่ llama.cpp ใช้สำหรับจัดเก็บค่าน้ำหนัก (weights) ลงบนดิสก์ เนื่องจาก Ollama สร้างขึ้นบนพื้นฐานของ llama.cpp แท็กของ Ollama จึงใช้ชื่อการทำ quantization เดียวกับ llama.cpp โดยไม่มีการเปลี่ยนแปลง
ตัวเลขคือความกว้างเป้าหมาย q4 หมายความว่า tensor ของค่าน้ำหนักส่วนใหญ่ถูกบีบอัดไว้ที่ 4 บิตต่อค่า q8 หมายถึง 8 บิต ส่วน fp16 คือการไม่ทำ quantization เลย ซึ่งก็คือโมเดลที่ความละเอียด 16-bit floating point อันเป็นความละเอียดที่โมเดลส่วนใหญ่ถูกเผยแพร่ออกมา
K คือเครื่องหมายของ K-quant ค่าน้ำหนักจะถูกจัดกลุ่มเป็นบล็อกขนาดเล็ก และแต่ละบล็อกจะเก็บค่าสเกลของตัวเองไว้ข้างๆ ค่าที่ถูกบีบอัด บล็อกที่ค่าน้ำหนักทั้งหมดอยู่ใกล้ 0.01 จะได้รับค่าสเกลที่ละเอียด ส่วนบล็อกที่มีค่าผิดปกติ (outlier) ขนาดใหญ่หนึ่งค่าจะได้รับค่าสเกลที่หยาบกว่า ค่าสเกลต่อบล็อกเหล่านี้คือสิ่งที่ทำให้ไฟล์ขนาด 4 บิตยังคงใช้งานได้ และยังเป็นเหตุผลว่าทำไมไฟล์ขนาด 4 บิตจึงไม่เคยมีขนาด 4 บิตต่อค่าน้ำหนักอย่างแท้จริง
ตัวอักษรตัวสุดท้ายคือส่วนผสม S, M และ L เป็นตัวกำหนดว่าจะมี tensor จำนวนเท่าใดที่ถูกปรับให้มีความกว้างมากกว่าค่าเป้าหมาย ใน q4_K_M tensor ที่ได้รับผลกระทบมากที่สุดเมื่อถูกปัดเศษจะถูกจัดเก็บด้วยความกว้างที่มากกว่า ในขณะที่ส่วนใหญ่ยังคงอยู่ที่ 4 บิต นี่คือเหตุผลที่ q4_K_M ให้ผลลัพธ์ที่ดีกว่า q4_0 รุ่นเก่าในขนาดไฟล์ที่ใกล้เคียงกัน
ให้ตรวจสอบกับ Ollama ว่ามีไฟล์อะไรอยู่ในดิสก์แทนการเดาจากชื่อที่คุณพิมพ์:
ollama pull qwen3:8b-q4_K_M
ollama show qwen3:8b-q4_K_Mollama show จะแสดง architecture, parameters, quantization, context length และ embedding length บรรทัด quantization คือข้อมูลจริงสำหรับโมเดลที่คุณดึงมาเมื่อหลายเดือนก่อนและจำไม่ได้แล้วว่าเลือกตัวไหนไว้
จำนวนบิตต่อค่าน้ำหนักคือที่มาของขนาดไฟล์
การประมาณขนาดไฟล์ทุกครั้งเริ่มต้นจากตัวเลขเดียว คือจำนวนบิตที่ฟอร์แมตนั้นใช้ต่อค่าน้ำหนักหนึ่งค่า โดยคำนวณเป็นค่าเฉลี่ยตลอดทั้งไฟล์ llama.cpp ได้เผยแพร่ตัวเลขที่วัดได้จริงสำหรับ Llama 3.1 8B ไว้ในเอกสารประกอบการทำ quantize ซึ่งตัวเลขเหล่านี้สามารถนำไปประยุกต์ใช้กับโมเดลแบบ dense ที่มีโครงสร้างใกล้เคียงกันได้เป็นอย่างดี
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"label": "F16",
"bits_per_weight": 16,
"file_gib": 14.96
},
{
"label": "Q8_0",
"bits_per_weight": 8.5,
"file_gib": 7.95
},
{
"label": "Q6_K",
"bits_per_weight": 6.56,
"file_gib": 6.14
},
{
"label": "Q5_K_M",
"bits_per_weight": 5.7,
"file_gib": 5.33
},
{
"label": "Q4_K_M",
"bits_per_weight": 4.89,
"file_gib": 4.58
},
{
"label": "Q3_K_M",
"bits_per_weight": 3.99,
"file_gib": 3.74
}
]สิ่งที่น่าประหลาดใจในตารางนั้นคือคอลัมน์ที่สอง Q4_K_M ไม่ได้ใช้ 4 บิตต่อค่าน้ำหนัก แต่มีค่าเท่ากับ 4.89 บิต เนื่องจาก block scales และ tensor ที่ถูกปรับระดับ (promoted tensors) ต่างก็ใช้พื้นที่จัดเก็บจริง ส่วน Q8_0 มีค่าเท่ากับ 8.5 บิต ไม่ใช่ 8 บิต ด้วยเหตุผลเดียวกัน หากใช้ตัวเลขที่วัดได้จริงนี้ในการคำนวณ ผลลัพธ์ที่ได้จะคลาดเคลื่อนจากขนาดไฟล์จริงเพียงไม่กี่เปอร์เซ็นต์เท่านั้น:
weight bytes = parameter count x bits per weight / 8
8.03e9 params x 4.89 bits / 8 = 4.91e9 bytes = 4.57 GiBนั่นคือไฟล์ Q4_K_M ขนาด 4.58 GiB ซึ่งคำนวณกลับมาจากตัวเลขสองค่า และยังเป็นขนาดหน่วยความจำที่ค่าน้ำหนักเหล่านั้นใช้เมื่อถูกโหลดเข้าสู่ระบบอีกด้วย Ollama ไม่มีการแตกไฟล์ใดๆ เมื่อโหลด: ค่าน้ำหนักที่ผ่านการทำ quantize จะถูกเก็บไว้ในหน่วยความจำในรูปแบบที่ถูกบีบอัดไว้เช่นเดิม และแต่ละบล็อกจะถูกแปลงในขณะที่เรียกใช้งาน
สิ่งที่ Ollama จัดส่งจริงสำหรับโมเดลแต่ละขนาด
ไลบรารีจะเผยแพร่แท็ก q4_K_M, q8_0 และ fp16 สำหรับตระกูลโมเดลส่วนใหญ่ ตระกูลใหม่บางรายการไม่ได้เป็นไปตามรูปแบบนี้และปรากฏในไลบรารีเป็นแท็กสำหรับใช้งานบนคลาวด์เท่านั้นโดยไม่มีไฟล์ให้ดึงข้อมูลในทุกขนาด ซึ่งเป็นปัญหาที่คุณพบเมื่อ พยายามรัน GLM 5.2 บน VPS ข้อมูลเหล่านี้คือขนาดของ Qwen3 ณ เดือนตุลาคม 2026 ซึ่งอ่านจากรายการแท็กในหน้าโมเดล ตัวเลขทุกค่าด้านล่างนี้คือขนาดบนดิสก์ก่อนที่จะโหลดเข้า RAM และหากดาวน์โหลดสองหรือสามโมเดลพร้อมกันอาจทำให้พื้นที่เก็บข้อมูล root ของ VPS ขนาดเล็กเต็มได้ ดังนั้นจึงควรทราบ ตำแหน่งที่ Ollama จัดเก็บโมเดลที่ดาวน์โหลดมา ก่อนที่คุณจะเริ่มสะสมแท็กต่างๆ
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"label": "Qwen3 4B",
"q4_K_M_gb": 2.6,
"q8_0_gb": 4.4,
"fp16_gb": 8.1
},
{
"label": "Qwen3 8B",
"q4_K_M_gb": 5.2,
"q8_0_gb": 8.9,
"fp16_gb": 16
},
{
"label": "Qwen3 14B",
"q4_K_M_gb": 9.3,
"q8_0_gb": 16,
"fp16_gb": 30
},
{
"label": "Qwen3 32B",
"q4_K_M_gb": 20,
"q8_0_gb": 35,
"fp16_gb": 66
}
]แท็กเริ่มต้นมีความสำคัญในกรณีนี้ ollama pull qwen3:8b จะดาวน์โหลดไฟล์ขนาด 5.2 GB เท่ากับ ollama pull qwen3:8b-q4_K_M ทุกประการ เนื่องจากแท็กที่ไม่มีส่วนต่อท้ายคือรุ่น q4_K_M นั่นเอง q4_K_M ไม่ใช่ตัวเลือกที่ไลบรารีเสนอให้แบบไม่เต็มใจ แต่เป็นค่าเริ่มต้นที่ต้นทางเลือกไว้ ดังนั้นการใช้ค่านี้จึงเป็นการเริ่มต้นที่สมเหตุสมผลที่สุดสำหรับโมเดลที่คุณยังไม่ได้ทดสอบด้วยตนเอง เหตุผลเดียวกันนี้เป็นตัวกำหนดการเลือกแท็กใน การรัน Qwen 3 บน VPS
อัตราส่วนนี้คงที่ในทุกแถว การเปลี่ยนจาก q4_K_M ไปเป็น q8_0 จะใช้พื้นที่เพิ่มขึ้นประมาณเจ็ดสิบเปอร์เซ็นต์แทนที่จะเป็นสองเท่าพอดี เนื่องจาก embedding และ output tensor ไม่ได้ขยายขนาดในอัตราเดียวกับส่วนอื่นๆ fp16 มีขนาดใหญ่กว่า q4_K_M ประมาณสามเท่า โมเดลขนาด 32B ที่ q4_K_M จะมีน้ำหนักไฟล์ 20 GB ซึ่งเกินกว่าที่เครื่องขนาด 16 GB จะรองรับได้หากมีการใช้ context window สำหรับมุมมองที่กว้างขึ้นว่าโมเดลใดเหมาะกับเครื่องระดับใด โปรดดู โมเดลที่คุณสามารถ self-host ได้
เหตุใด KV cache จึงเป็นต้นทุนส่วนที่สองที่ขึ้นอยู่กับบริบท
Weights คือต้นทุนคงที่ ส่วน KV cache (key and value cache) คือต้นทุนผันแปร ทุก token ใน context window จะเก็บเวกเตอร์ key และ value ไว้สำหรับทุก layer ดังนั้น cache จะขยายตัวเป็นเส้นตรงตามขนาด window ที่คุณกำหนด โดยระบบจะจัดสรรหน่วยความจำสำหรับ window ทั้งหมดตั้งแต่ตอนโหลดโมเดล ไม่ใช่ค่อยๆ เพิ่มตามการสนทนา นี่คือเหตุผลว่าทำไม window ขนาดใหญ่จึงกินหน่วยความจำแม้คุณจะป้อนคำสั่งเพียงคำเดียวก็ตาม
KV bytes per token = 2 (key and value) x layers x kv_heads x head_dim x bytes_per_element
Qwen3 8B at f16: 2 x 36 x 8 x 128 x 2 = 147456 bytes = 144 KiB per tokenตัวเลขของโมเดลเหล่านี้มาจาก configuration ของโมเดลเอง ได้แก่ 36 layers, 8 key/value heads และ head dimension ขนาด 128 โดย ollama show จะแสดงสถาปัตยกรรมและจำนวนพารามิเตอร์ ส่วน config.json ของโมเดลบน Hugging Face จะให้ข้อมูลส่วนที่เหลือ หากคุณนำต้นทุนต่อ token มาคูณกับขนาด window แล้ว คุณจะพบว่า cache ไม่ใช่แค่ค่าความคลาดเคลื่อนเล็กน้อยอีกต่อไป
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"label": "4k",
"kv_cache_gb": 0.6,
"floor_ram_gb": 5.8
},
{
"label": "8k",
"kv_cache_gb": 1.21,
"floor_ram_gb": 6.4
},
{
"label": "16k",
"kv_cache_gb": 2.42,
"floor_ram_gb": 7.6
},
{
"label": "32k",
"kv_cache_gb": 4.83,
"floor_ram_gb": 10
}
]ที่ขนาด 4096 tokens ซึ่งเป็น window เริ่มต้นที่ Ollama เลือกเมื่อมี VRAM น้อยกว่า 24 GiB (รวมถึง CPU-only VPS) cache จะเพิ่มขนาดขึ้นอีก 0.6 GB นอกเหนือจากตัว weights หากเพิ่ม window เป็น 32k ตัว cache เพียงอย่างเดียวจะสูงถึง 4.83 GB ซึ่งเกือบเท่ากับหน่วยความจำที่ใช้สำหรับ quantized weights และค่าต่ำสุดที่ต้องใช้สำหรับโมเดลทั้งหมดจะกลายเป็น 10 GB เราเรียกสิ่งนี้ว่าค่าต่ำสุดเพราะยังมี compute buffers และระบบปฏิบัติการที่ต้องใช้หน่วยความจำเพิ่มขึ้นไปอีก คุณสามารถอ่านตัวเลขจริงได้จากคอลัมน์ SIZE ของ ollama ps หลังจากโหลดโมเดลแล้ว บน GPU ที่มี VRAM 24 ถึง 48 GiB ค่า window เริ่มต้นจะเป็น 32k และตั้งแต่ 48 GiB ขึ้นไปจะเป็น 256k ดังนั้นหากใช้การ์ดจอขนาดใหญ่ อย่าทึกทักเอาเองว่าเป็นตัวเลข 4k
การตั้งค่า window จะทำที่ฝั่งเซิร์ฟเวอร์ ไม่ใช่ต่อคำขอ (request) เมื่อคุณรัน Ollama ในฐานะ service:
OLLAMA_CONTEXT_LENGTH=8192 ollama serveสำหรับการติดตั้งผ่าน systemd ให้ใส่ไว้ใน drop-in แทน:
sudo systemctl edit ollama[Service]
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"รีสตาร์ทด้วย sudo systemctl restart ollama จากนั้นตรวจสอบคอลัมน์ CONTEXT ของ ollama ps เพื่อยืนยันขนาด window ที่โมเดลที่กำลังรันอยู่ถูกโหลดขึ้นมาจริง OLLAMA_KV_CACHE_TYPE จะทำ quantization ให้กับตัว cache เอง โดย f16 คือค่าเริ่มต้น, q8_0 จะใช้หน่วยความจำประมาณครึ่งหนึ่งของ f16 และ q4_0 จะใช้ประมาณหนึ่งในสี่ นี่เป็นตัวเลือกแบบ global ดังนั้นทุกโมเดลบนเซิร์ฟเวอร์นั้นจะถูกจัดการด้วยวิธีเดียวกัน การทำ cache quantization จะมีผลก็ต่อเมื่อเปิดใช้งาน Flash Attention ซึ่ง Ollama จะเปิดให้โดยอัตโนมัติหาก backend รองรับ และ OLLAMA_FLASH_ATTENTION=1 จะเป็นการบังคับเปิดใช้งาน บนเครื่องขนาดเล็กที่มี window ขนาดใหญ่ การลดขนาด cache ลงครึ่งหนึ่งจะช่วยคืนหน่วยความจำได้มากกว่าการปรับเปลี่ยนค่าอื่นใด การตั้งค่า num_ctx และต้นทุนที่เกี่ยวข้อง จะอธิบายรายละเอียดเกี่ยวกับตัว window เอง นอกจากนี้ cache ยังถูกกำหนดขนาดต่อหนึ่งช่องคำขอพร้อมกัน (concurrent request slot) ไม่ใช่ต่อเซิร์ฟเวอร์ ดังนั้นการปล่อยให้ Ollama ตอบคำถามสองคำสั่งพร้อมกันจะทำให้ตัวเลขที่คุณคำนวณไว้เพิ่มขึ้นเป็นสองเท่า ซึ่งเป็นหลักการคำนวณเบื้องหลัง การเลือกจำนวนช่องคำขอขนานและขีดจำกัดของคิว
สิ่งที่สามารถรันได้บน VPS ขนาด 8, 16 หรือ 32 GB
พิจารณาน้ำหนักของโมเดล (weights) รวมกับ KV cache และเผื่อพื้นที่สำหรับระบบปฏิบัติการและโปรเซสอื่นๆ ที่ทำงานอยู่ การเผื่อพื้นที่ไว้ 2 GB ถือว่าเพียงพอสำหรับการใช้งานบน VPS ขนาดเล็ก
8 GB. โมเดลขนาด 4B ที่ระดับ q4_K_M มีขนาด 2.6 GB ซึ่งเหลือพื้นที่สำหรับ context window ที่ยาวได้ โมเดลขนาด 8B ที่ระดับ q4_K_M สามารถรันได้ด้วย context window เริ่มต้นที่ 4k โดยมีพื้นที่เหลือเพียงเล็กน้อย อย่าคาดหวังว่าจะรัน 8B ด้วย context window ขนาด 32k บนเครื่องนี้ เนื่องจากค่าพื้นฐานของ 10 GB นั้นเกินขีดจำกัดของเครื่องไปแล้ว
16 GB. โมเดลขนาด 8B ที่ระดับ q4_K_M พร้อม context window ขนาด 16k หรือ 32k สามารถรันได้อย่างราบรื่น โมเดลขนาด 14B ที่ระดับ q4_K_M มีขนาดน้ำหนัก 9.3 GB และสามารถรันได้ด้วย context window ขนาดปานกลาง ส่วนโมเดลขนาด 8B ที่ระดับ q8_0 มีขนาด 8.9 GB ซึ่งสามารถรันได้เช่นกัน การทดสอบเปรียบเทียบโมเดลทั้งสองนี้ด้วย prompt ของคุณเองเป็นวิธีที่มีประสิทธิภาพที่สุดในการทำความเข้าใจเรื่องนี้
32 GB. โมเดลขนาด 14B ที่ระดับ q8_0 (16 GB) และ 32B ที่ระดับ q4_K_M (20 GB) สามารถโหลดเข้าหน่วยความจำได้ทั้งคู่ การรันโมเดล 32B พร้อม context window ขนาดใหญ่จะใช้ทรัพยากรจนเกือบเต็มขีดจำกัด ดังนั้นควรตรวจสอบ ollama ps แทนการคาดเดาเอาเอง
การสูญเสียคุณภาพจากการทำ Quantization เริ่มต้นที่จุดใด
ข้อผิดพลาดจากการทำ Quantization ไม่ได้กระจายตัวอย่างสม่ำเสมอในทุกการทำงานของโมเดล ความลื่นไหลของภาษาจะคงอยู่ได้นานที่สุด ซึ่งเป็นเหตุผลว่าทำไมความเสียหายนี้จึงสังเกตเห็นได้ยาก โมเดลที่ถูกทำ Quantization มาไม่ดีก็ยังคงเขียนประโยคที่อ่านรู้เรื่องได้ ความแม่นยำ (Precision) คือสิ่งแรกที่สูญเสียไป เช่น การเรียกคืนข้อมูลที่ถูกต้องแม่นยำของเลขเวอร์ชัน, ลายเซ็นของ API หรือวันที่ รวมถึงกระบวนการคิดที่เป็นลำดับยาวๆ ซึ่งข้อผิดพลาดเล็กน้อยในขั้นตอนที่ 2 อาจกลายเป็นคำตอบที่ผิดในขั้นตอนที่ 8 และรูปแบบผลลัพธ์ที่เข้มงวด ซึ่งการวางวงเล็บผิดเพียงจุดเดียวก็ทำให้การเรียกใช้เครื่องมือ (tool call) ล้มเหลว
กรณีสุดท้ายคือบททดสอบในทางปฏิบัติ เมื่อโมเดลต้องส่งผลลัพธ์เป็น JSON เพื่อให้โค้ดของคุณนำไปประมวลผล ความเสียหายจากการทำ Quantization จะปรากฏออกมาในรูปแบบของข้อผิดพลาดในการแยกวิเคราะห์ (parse error) แทนที่จะเป็นเพียงภาษาที่ดูแย่ลงเล็กน้อย ทำให้คุณสังเกตเห็นปัญหาได้ทันทีภายในวันเดียวกัน ตัวแทนอัจฉริยะที่เขียนโค้ด (coding agent) คือบททดสอบที่เข้มงวดที่สุดในเรื่องนี้ เพราะมันจะบังคับให้โมเดลต้องเรียกใช้เครื่องมือครั้งแล้วครั้งเล่า ดังนั้นการ ชี้เป้าตัวแทนอัจฉริยะไปยังเซิร์ฟเวอร์ Ollama ของคุณ จะทำให้เห็นผลกระทบจากการทำ Quantization ที่รุนแรงเกินไปได้ภายในช่วงบ่าย
หากต่ำกว่า 4 บิต การสูญเสียคุณภาพจะเพิ่มขึ้นอย่างรวดเร็ว ประเภท q3 และ 2 บิตมีไว้สำหรับผู้ที่ต้องการบีบอัดโมเดลขนาดใหญ่ลงในฮาร์ดแวร์ที่มีทรัพยากรจำกัด ซึ่งถือเป็นทางเลือกที่ใช้งานได้จริงในกรณีที่ทางเลือกอื่นคือการไม่สามารถรันโมเดลนั้นได้เลย แต่ไม่ควรใช้เป็นค่าเริ่มต้นที่แนะนำ สำหรับช่วงระหว่าง q4_K_M และ q8_0 นั้น ช่องว่างของคุณภาพมีน้อยมากจนตารางค่า perplexity ที่เผยแพร่ทั่วไปไม่สามารถตัดสินได้ว่าแบบใดเหมาะกับภาระงานของคุณ ดังนั้นอย่าพยายามตัดสินด้วยวิธีนั้น ให้ทดสอบรันทั้งสองแบบกับ prompt ของคุณเองจำนวน 30 รายการแล้วอ่านผลลัพธ์ที่ได้ด้วยตนเอง
เมื่อใดที่ q8_0 หรือ fp16 คุ้มค่ากับ RAM
ให้ดึง q8_0 มาใช้เมื่อคุณมีหน่วยความจำเหลือเฟือจริงๆ และงานนั้นไม่ยอมรับความผิดพลาดเล็กน้อย เช่น การสกัดข้อมูลที่มีโครงสร้าง (structured extraction), การเรียกใช้เครื่องมือ (tool calling) หรือโค้ดที่ต้องคอมไพล์ผ่าน นี่คือการซื้อประกันความเสี่ยง ไม่ใช่การทำให้โมเดลฉลาดขึ้นอย่างเห็นได้ชัด
ให้ดึง fp16 มาใช้ด้วยเหตุผลเพียง 2 ประการเท่านั้น คือคุณกำลังทำ quantization โมเดลด้วยตัวเองและต้องการไฟล์ต้นฉบับ หรือคุณกำลังวัดค่าพื้นฐาน (baseline) เพื่อเปรียบเทียบว่าการ build แบบ 4-bit ของคุณสูญเสียประสิทธิภาพไปเท่าใด การให้บริการจาก fp16 ใช้หน่วยความจำมากกว่า q4_K_M ถึง 3 เท่า ซึ่งเป็นความแตกต่างที่คนส่วนใหญ่แยกไม่ออกในการทดสอบแบบ blind test และบนเครื่องที่ใช้เฉพาะ CPU มันจะลดอัตราการสร้าง token ของคุณลงเหลือเพียง 1 ใน 3 เท่านั้น
กฎที่สำคัญกว่าภายใต้งบประมาณหน่วยความจำที่จำกัดคือ โมเดลขนาดใหญ่ที่ใช้ q4_K_M มักจะให้ผลลัพธ์ดีกว่าโมเดลขนาดเล็กที่ใช้ q8_0 โดยน้ำหนัก 14B ขนาด 9.3 GB เทียบกับน้ำหนัก 8B ขนาด 8.9 GB นั้นใช้ RAM (random access memory) ใกล้เคียงกัน แต่โมเดลที่ใหญ่กว่ามีความรู้มากกว่า ให้ทดสอบเรื่องนี้ด้วย prompt ของคุณเองแทนที่จะเชื่อตามคำบอกเล่าเพียงอย่างเดียว
การอนุมานด้วย CPU เพียงอย่างเดียวถูกจำกัดด้วยแบนด์วิดท์ของหน่วยความจำ
VPS ส่วนใหญ่ไม่มี GPU ดังนั้นโมเดลจึงทำงานในหน่วยความจำระบบบน CPU ของโฮสต์ การสร้างข้อความ (generation) จึงถูกจำกัดด้วยแบนด์วิดท์ของหน่วยความจำ ไม่ใช่ความสามารถในการคำนวณ เพราะการสร้างหนึ่ง token จำเป็นต้องอ่านค่าน้ำหนัก (weight) ทั้งหมดหนึ่งครั้ง ซึ่งทำให้เกิดเพดานความเร็วที่ไม่เกี่ยวข้องกับจำนวนคอร์ที่คุณซื้อมา
tokens per second ceiling = memory bandwidth / bytes read per token
50 GB/s / 5.2 GB = 9.6 tokens/s qwen3 8B q4_K_M
50 GB/s / 8.9 GB = 5.6 tokens/s qwen3 8B q8_0
50 GB/s / 16 GB = 3.1 tokens/s qwen3 8B fp1650 GB/s คือตัวเลขทางทฤษฎีโดยประมาณสำหรับโฮสต์ที่ใช้ DDR4-3200 แบบ dual channel ส่วนแบ่งของคุณนั้นน้อยกว่านั้น เพราะ VPS ต้องแชร์บัสนี้กับผู้เช่ารายอื่นทุกคนบนเครื่องเดียวกัน ดังนั้นให้ถือว่าตัวเลขเหล่านั้นเป็นเพดานที่ไม่มีใครไปถึง รูปแบบการทำงานคือส่วนที่สำคัญ: บน CPU การลดจำนวนบิตต่อน้ำหนักลงครึ่งหนึ่งจะทำให้ความเร็วในการสร้าง token เพิ่มขึ้นประมาณสองเท่า การทำ Quantization จึงเป็นเครื่องมือเพิ่มความเร็วที่สำคัญที่สุดบนเครื่องที่ไม่มี GPU ส่วนอัตราความเร็วที่เหลืออยู่จะยอมรับได้หรือไม่นั้นขึ้นอยู่กับโมเดล และ Nemotron 3.5 Lightning บน VPS ได้คำนวณการแบ่งส่วนนี้ไว้สำหรับ build, tag และปริมาณ RAM ที่ระบุไว้ อีกครึ่งหนึ่งของเวลาที่ต้องรอขึ้นอยู่กับว่าโมเดลตัดสินใจเขียนออกมามากน้อยเพียงใด เนื่องจากที่ความเร็ว 10 token ต่อวินาที คำตอบที่มีความยาว 600 token จะใช้เวลาเต็มหนึ่งนาที ดังนั้น การจำกัดคำตอบด้วย num_predict มักจะช่วยลดเวลาในการรอได้มากกว่าการลดระดับความแม่นยำลงอีกขั้น
การประมวลผล Prompt มีพฤติกรรมที่แตกต่างออกไป การอ่าน Prompt ที่ยาวจะถูกจำกัดด้วยพลังการคำนวณ (compute bound) มากกว่าแบนด์วิดท์ ดังนั้นการเพิ่มจำนวนคอร์จะช่วยในส่วนนี้ได้ ในขณะที่แทบไม่มีผลต่อความเร็วในการสร้างข้อความ เครื่องที่รับ Prompt ขนาด 4k ได้อย่างรวดเร็วแล้วสร้างข้อความออกมาอย่างช้าๆ ถือว่ามีพฤติกรรมปกติ
อย่าเชื่อการคำนวณทั้งหมดโดยปราศจากการพิสูจน์ วัดค่า tokens ต่อวินาทีบนเครื่องของคุณเอง ด้วย Prompt เดียวกันในแต่ละระดับการทำ Quantization และให้ตัวเลขของคุณเป็นตัวตัดสินเหนือข้อมูลเหล่านี้
การทำ Quantization โมเดลด้วยตนเอง
ขั้นตอนนี้มีความสำคัญเมื่อคุณได้ทำการ fine-tune โมเดลขึ้นมาเองและไม่มี tag ใน library รองรับ เส้นทางในการดำเนินการขึ้นอยู่กับรูปแบบไฟล์ปลายทางที่คุณต้องการ เนื่องจากปัจจุบัน Ollama ไม่ได้สร้าง GGUF K-quants ตามที่ระบุไว้ในตารางของหน้านี้อีกต่อไป
สำหรับการทำ K-quant เช่น q4_K_M ให้ทำ quantization ก่อนที่ Ollama จะอ่านไฟล์ Ollama ไม่รองรับการทำ quantization ให้กับโมเดล GGUF ในระหว่างการ import และจะปฏิเสธ --quantize หากแหล่งที่มาเป็นไฟล์ GGUF ให้คุณทำ quantization ไฟล์ GGUF ที่ยังไม่ได้ผ่านการบีบอัดด้วย llama-quantize ของ llama.cpp จากนั้นจึงค่อย import ไฟล์ที่เสร็จสมบูรณ์เข้าไป เส้นทางการ import นี้มีข้อควรระวังเรื่องความไม่สอดคล้องกันของ chat template ซึ่งอาจทำให้โมเดลตอบกลับเป็นข้อความที่อ่านไม่รู้เรื่อง โดยคุณสามารถดูขั้นตอนแก้ไขได้ที่ การ import ไฟล์ GGUF เข้าสู่ Ollama คุณสามารถใช้บรรทัด quantization จาก ollama show เพื่อตรวจสอบว่าไฟล์ที่ import เข้าไปนั้นเป็นรุ่นที่คุณต้องการจริงหรือไม่
คำสั่ง --quantize ของ Ollama เองจะทำงานได้เฉพาะกับการ import รูปแบบ safetensors เท่านั้น ให้ชี้ Modelfile ไปยังไดเรกทอรีที่เก็บไฟล์น้ำหนัก (weights) แบบ unquantized safetensors:
FROM /path/to/safetensors/directoryจากนั้นทำการ build:
ollama create --quantize int4 mymodelณ Ollama v0.40.2 (ตรวจสอบเมื่อ 2026-10-11) คำสั่ง --quantize รองรับ int4, int8, nvfp4, mxfp4 และ mxfp8 โดยที่ q4 และ q8 (รวมถึง fp4 และ fp8) จะถูกใช้เป็นชื่อเรียกแทน (alias) ของ int4 และ int8 สำหรับชื่อรูปแบบ GGUF เช่น q4_K_M, q4_K_S, q8_0, q6_K และ q5_K_M จะถูกปฏิเสธพร้อมข้อผิดพลาด unsupported quantize type ประเภทเหล่านี้ไม่ใช่ GGUF K-quants ตามตารางด้านบน ดังนั้นอย่าใช้ค่า bits per weight และขนาดไฟล์ในหน้านี้เป็นตัวเลขคาดการณ์สำหรับรูปแบบดังกล่าว
สิ่งที่คุณจะพบเมื่อเกิดข้อผิดพลาด
ทุกอย่างทำงานบน CPU ในขณะที่คุณคาดหวังให้ทำงานบน GPU ให้ตรวจสอบคอลัมน์ PROCESSOR:
ollama psระบบจะแสดงค่า 100% GPU, 100% CPU หรือค่าแบบแยกส่วนเช่น 48%/52% CPU/GPU การแยกส่วนหมายความว่าน้ำหนักของโมเดลรวมกับ KV cache ไม่สามารถบรรจุลงใน VRAM (video RAM ซึ่งเป็นหน่วยความจำบนการ์ดจอ) ได้ทั้งหมด ทำให้ส่วนหนึ่งของโมเดลถูกย้ายไปเก็บไว้ในหน่วยความจำหลักของระบบ ส่งผลให้ความเร็วลดลงจนใกล้เคียงกับการประมวลผลด้วย CPU เพียงอย่างเดียว เนื่องจากทุก token ต้องรอการประมวลผลจากส่วนที่ช้ากว่า ให้ลดขนาด context window, ทำการ quantize cache หรือเลือกใช้ build ที่มีขนาดเล็กลง การเพิ่มจำนวน core ไม่สามารถช่วยแก้ปัญหานี้ได้
โมเดลถูกสั่งยุติการทำงาน (killed) ขณะกำลังโหลด ให้ตรวจสอบ log ของ kernel และ service:
sudo dmesg -T | grep -i "out of memory"
sudo journalctl -u ollama -n 50บรรทัดที่มีข้อความ Out of memory: Killed process หมายความว่าผลรวมของน้ำหนักโมเดล, KV cache และบัฟเฟอร์ มีขนาดเกินกว่าหน่วยความจำทั้งหมดที่มีในเครื่อง สำหรับ VPS ที่ไม่ได้ตั้งค่า swap ไว้ เครื่องอาจค้างไปหลายวินาทีก่อนที่บรรทัดดังกล่าวจะปรากฏขึ้น
คำตอบที่ได้แย่ลงทั้งที่คุณไม่ได้เปลี่ยนแปลงการตั้งค่าใดๆ build สองชุดของโมเดลเดียวกันสามารถวางอยู่เคียงข้างกันใน ollama ls ภายใต้ tag ที่แตกต่างกัน และสคริปต์ที่ดึงชื่อแบบไม่มี suffix จะดึงข้อมูลตามที่ library ชี้ไปในขณะนั้น ให้รันคำสั่ง ollama show เทียบกับ tag ที่ client ของคุณเรียกใช้จริง แล้วอ่านบรรทัด quantization แทนที่จะเชื่อชื่อที่ระบุไว้ในไฟล์ configuration ของคุณ
FAQ
ฉันควรดึง Ollama quantization รุ่นไหน?
ให้เริ่มจาก q4_K_M ซึ่งเป็นค่าเริ่มต้นที่ไลบรารีของ Ollama จัดส่งมาให้สำหรับโมเดลส่วนใหญ่ ดังนั้น ollama pull qwen3:8b และ ollama pull qwen3:8b-q4_K_M จึงดึงไฟล์เดียวกัน ให้เปลี่ยนไปใช้ q8_0 ก็ต่อเมื่อมีหน่วยความจำเหลือเฟือและงานที่ทำต้องการความแม่นยำสูงเพื่อลดข้อผิดพลาด เช่น การเรียกใช้เครื่องมือ (tool calling) หรือการสร้างผลลัพธ์แบบ JSON ที่มีโครงสร้าง หากมีงบประมาณหน่วยความจำจำกัด การใช้โมเดลขนาดใหญ่ที่ q4_K_M มักจะให้ผลลัพธ์ที่ดีกว่าโมเดลขนาดเล็กที่ q8_0 ดังนั้นควรทดสอบการจับคู่ดังกล่าวก่อนที่จะเพิ่ม RAM เพื่อความแม่นยำ
q4_K_M หมายถึงสี่บิตต่อหนึ่งน้ำหนักจริงหรือไม่?
ไม่จริง จากการวัดผลบน Llama 3.1 8B พบว่ามีค่า 4.89 บิตต่อน้ำหนัก เนื่องจากบล็อกของน้ำหนักแต่ละบล็อกจะเก็บค่าสเกลของตัวเอง และเทนเซอร์ที่สำคัญที่สุดจะถูกปรับให้เป็นประเภทที่กว้างขึ้น ส่วน Q8_0 มีค่า 8.5 บิตแทนที่จะเป็นแปดด้วยเหตุผลเดียวกัน ให้ใช้ตัวเลขที่วัดได้จริงในการประเมิน: จำนวนพารามิเตอร์คูณด้วยบิตต่อน้ำหนัก แล้วหารด้วยแปด จะได้ขนาดไฟล์เป็นไบต์
โมเดล 8B ต้องการ RAM เท่าใดบน VPS ที่ใช้เฉพาะ CPU?
ให้รวมน้ำหนัก (weights), KV cache และพื้นที่สำรอง (headroom) เข้าด้วยกัน Qwen3 8B ที่ q4_K_M มีขนาดน้ำหนัก 5.2 GB ที่หน้าต่างบริบท (context window) เริ่มต้น 4096 token แคชจะเพิ่มขนาดอีก 0.6 GB ทำให้ได้ค่าพื้นฐานใกล้เคียง 5.8 GB ก่อนจะรวม compute buffers และระบบปฏิบัติการ หากใช้หน้าต่างขนาด 32k แคชเพียงอย่างเดียวจะมีขนาด 4.83 GB ควรวางแผนใช้ RAM 8 GB สำหรับหน้าต่างขนาดสั้น และ 16 GB หากต้องการหน้าต่างขนาดยาว
ทำไมโมเดลของฉันถึงใช้ CPU 100% ทั้งที่เซิร์ฟเวอร์มี GPU?
ให้รัน ollama ps แล้วอ่านคอลัมน์ PROCESSOR หากเป็น 100% CPU หรือการแบ่งส่วนเช่น 48%/52% CPU/GPU หมายความว่าน้ำหนักรวมกับ KV cache ไม่สามารถบรรจุลงใน VRAM ได้ทั้งหมด Ollama จึงย้ายบางส่วนหรือทั้งหมดของโมเดลไปไว้ในหน่วยความจำหลักของระบบ สาเหตุที่พบบ่อยคือหน้าต่างบริบทมีขนาดใหญ่เกินกว่าที่การ์ดจะรองรับได้ เนื่องจากแคชจะถูกจองไว้สำหรับหน้าต่างทั้งหมดเมื่อโหลดโมเดล ให้ลดขนาดหน้าต่างลงด้วย OLLAMA_CONTEXT_LENGTH, ตั้งค่า OLLAMA_KV_CACHE_TYPE=q8_0 เพื่อลดขนาดแคชลงครึ่งหนึ่ง หรือดึง quantization ที่มีขนาดเล็กลงมาใช้งานแทน