SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-09-08

เปรียบเทียบ Ollama Quantization: q4_K_M, q8_0 และ fp16

เลือกขนาด Quantization ให้เหมาะสมกับ RAM ของคุณ เรียนรู้ความแตกต่างของ q4_K_M, q8_0 และ fp16 พร้อมวิเคราะห์ผลกระทบด้านความเร็วและคุณภาพโมเดล เพื่อตัดสินใจเลือกไฟล์ GGUF ที่คุ้มค่าที่สุด

การเปลี่ยนแปลงของการทำ quantization ใน Ollama

การทำ quantization ใน Ollama คือการจัดเก็บน้ำหนัก (weight) แต่ละตัวในโมเดลด้วยจำนวนบิตที่น้อยลงกว่าไฟล์ที่ใช้ฝึกฝน Tag ที่ลงท้ายด้วย q4_K_M จะเก็บข้อมูลประมาณ 4 บิตต่อน้ำหนัก ในขณะที่ fp16 จะเก็บ 16 บิต ดังนั้นขนาดไฟล์ดาวน์โหลดจึงลดลงเหลือประมาณหนึ่งในสี่ และเครื่องจะอ่านข้อมูลจำนวนไบต์น้อยลงหนึ่งในสี่เพื่อสร้างแต่ละ token น้ำหนักจะถูกปัดเศษลงบนตารางที่หยาบขึ้น ไม่ได้ถูกตัดทิ้ง และที่ระดับ 4 บิต โมเดลส่วนใหญ่ยังคงให้คำตอบใกล้เคียงกับระดับความแม่นยำเต็มรูปแบบ

นี่คือข้อแลกเปลี่ยนทั้งหมด: การใช้หน่วยความจำที่น้อยลงมากและจำนวน token ต่อวินาทีที่เพิ่มขึ้น โดยแลกกับความแม่นยำที่ลดลงเล็กน้อย เนื้อหาต่อไปนี้คือวิธีการคาดการณ์ผลกระทบทั้งสองด้านสำหรับโมเดลเฉพาะบนเครื่องเฉพาะ ก่อนที่คุณจะเสียเวลา 20 นาทีในการดาวน์โหลดไฟล์ที่ไม่สามารถใช้งานได้

หาก Ollama ยังไม่ทำงาน ให้เริ่มต้นด้วย การติดตั้ง Ollama บน VPS หน้าเว็บนี้อนุมานว่า ollama ls ทำงานได้ตามปกติแล้ว

วิธีอ่านแท็กการทำ quantization ของ Ollama เช่น q4_K_M

โมเดลในเครื่องจะมาในรูปแบบไฟล์ GGUF ซึ่งเป็นฟอร์แมตที่ llama.cpp ใช้สำหรับจัดเก็บน้ำหนัก (weights) ลงบนดิสก์ Ollama ถูกสร้างขึ้นบนพื้นฐานของ llama.cpp ดังนั้นแท็กของ Ollama จึงใช้ชื่อการทำ quantization ตามแบบฉบับของ llama.cpp โดยไม่มีการเปลี่ยนแปลง

ตัวเลขคือความกว้างเป้าหมาย (target width) q4 หมายความว่า weight tensor ส่วนใหญ่ถูกบีบอัดเหลือ 4 บิตต่อค่า q8 หมายถึง 8 บิต ส่วน fp16 คือการไม่ทำ quantization เลย ซึ่งก็คือโมเดลที่ความละเอียด 16-bit floating point อันเป็นความละเอียดที่โมเดลส่วนใหญ่ถูกเผยแพร่ออกมา

K ระบุว่าเป็น K-quant น้ำหนักจะถูกจัดกลุ่มเป็นบล็อกขนาดเล็ก และแต่ละบล็อกจะจัดเก็บค่าสเกลของตัวเองไว้ข้างๆ ค่าที่ถูกบีบอัด บล็อกที่น้ำหนักทั้งหมดอยู่ใกล้ 0.01 จะได้รับค่าสเกลที่ละเอียด ส่วนบล็อกที่มีค่าผิดปกติ (outlier) ขนาดใหญ่หนึ่งค่าจะได้รับค่าสเกลที่หยาบกว่า ค่าสเกลต่อบล็อกเหล่านี้คือสิ่งที่ทำให้ไฟล์ขนาด 4 บิตยังคงใช้งานได้ และยังเป็นเหตุผลว่าทำไมไฟล์ขนาด 4 บิตจึงไม่ได้มีขนาด 4 บิตต่อหนึ่งน้ำหนักอย่างแม่นยำเสมอไป

ตัวอักษรตัวสุดท้ายคือส่วนผสม (mixture) 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_M

ollama show จะแสดง architecture, parameters, quantization, context length และ embedding length บรรทัด quantization คือข้อมูลจริงสำหรับโมเดลที่คุณดึงมาเมื่อหลายเดือนก่อนและจำไม่ได้แล้วว่าเลือกเวอร์ชันไหนไว้

จำนวนบิตต่อค่าน้ำหนัก (bits per weight) คือที่มาของขนาดไฟล์

การประมาณขนาดไฟล์ทุกครั้งเริ่มต้นจากตัวเลขเดียว คือรูปแบบไฟล์ใช้จำนวนบิตต่อค่าน้ำหนักเฉลี่ยเท่าใดตลอดทั้งไฟล์ llama.cpp ได้เผยแพร่ตัวเลขที่วัดได้สำหรับ Llama 3.1 8B ไว้ในเอกสารประกอบการทำ quantize ซึ่งสามารถนำไปประยุกต์ใช้กับโมเดลแบบ dense ที่มีโครงสร้างใกล้เคียงกันได้เป็นอย่างดี

ChartGGUF quantization types measured on Llama 3.1 8B (published llama.cpp figures)
The data behind this chart
[
  {
    "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.89 บิต เนื่องจากทั้งการปรับสเกลของบล็อก (block scales) และเทนเซอร์ที่ถูกโปรโมต (promoted tensors) ต่างก็ใช้พื้นที่จัดเก็บจริง ส่วน Q8_0 มีค่าอยู่ที่ 8.5 บิต ไม่ใช่แปดบิตด้วยเหตุผลเดียวกัน หากใช้ตัวเลขที่วัดได้จริงนี้ในการคำนวณ ผลลัพธ์จะใกล้เคียงกับขนาดไฟล์จริงภายในความคลาดเคลื่อนเพียงไม่กี่เปอร์เซ็นต์:

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 จัดเก็บโมเดลที่ดาวน์โหลดไว้ที่ไหน ก่อนที่คุณจะเริ่มสะสมแท็กต่างๆ

ChartDownload size of Qwen3 tags in the Ollama library, GB
The data behind this chart
[
  {
    "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) คือต้นทุนผันแปร ทุกโทเค็นใน context window จะเก็บเวกเตอร์ key และ value ไว้สำหรับทุกเลเยอร์ ดังนั้น 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 เลเยอร์, 8 key/value heads และ head dimension ขนาด 128 โดย ollama show จะระบุสถาปัตยกรรมและจำนวนพารามิเตอร์ ส่วน config.json ของโมเดลบน Hugging Face จะให้ข้อมูลส่วนที่เหลือ เมื่อนำต้นทุนต่อโทเค็นมาคูณกับขนาด window แล้ว cache จะไม่ใช่แค่ค่าความคลาดเคลื่อนเล็กน้อยอีกต่อไป

Chartqwen3:8b-q4_K_M: KV cache and floor RAM by context length, GB
The data behind this chart
[
  {
    "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
  }
]

ที่ค่าเริ่มต้นของ Ollama ซึ่งกำหนด window ไว้ที่ 4096 โทเค็น cache จะเพิ่มหน่วยความจำขึ้นอีก 0.6 GB นอกเหนือจากตัว weights หากเพิ่ม window เป็น 32k เฉพาะตัว cache จะมีขนาดถึง 4.83 GB ซึ่งเกือบเท่ากับหน่วยความจำที่ใช้สำหรับ quantized weights และค่าต่ำสุดของหน่วยความจำสำหรับโมเดลทั้งหมดจะกลายเป็น 10 GB ที่เรียกว่าค่าต่ำสุดเพราะยังมี compute buffers และระบบปฏิบัติการที่ต้องใช้หน่วยความจำเพิ่มขึ้นไปอีก คุณสามารถอ่านค่าจริงได้จากคอลัมน์ SIZE ของ ollama ps หลังจากโหลดโมเดลแล้ว

การกำหนด window จะทำที่ฝั่งเซิร์ฟเวอร์ ไม่ใช่ต่อคำขอ เมื่อคุณรัน 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 ดังนั้นทุกโมเดลบนเซิร์ฟเวอร์นั้นจะถูกตั้งค่าเหมือนกัน ในเครื่องขนาดเล็กที่มี window ยาว การลดขนาด cache ลงครึ่งหนึ่งจะช่วยคืนหน่วยความจำได้มากกว่าการปรับแต่งอื่นใด การตั้งค่า num_ctx และต้นทุนที่เกี่ยวข้อง จะอธิบายรายละเอียดเกี่ยวกับตัว window เอง นอกจากนี้ cache ยังถูกกำหนดขนาดต่อหนึ่ง concurrent request slot ไม่ใช่ต่อเซิร์ฟเวอร์ ดังนั้นการปล่อยให้ Ollama ตอบคำถามสองคำขอพร้อมกันจะทำให้ตัวเลขที่คุณคำนวณไว้เพิ่มขึ้นเป็นสองเท่า ซึ่งเป็นหลักการคำนวณเบื้องหลัง การเลือกจำนวน parallel slot และขีดจำกัดของคิว

ขนาดโมเดลที่เหมาะสมสำหรับ 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 ไม่ได้กระจายตัวอย่างสม่ำเสมอในทุกการทำงานของโมเดล ความลื่นไหลของภาษา (Fluency) จะคงอยู่ได้นานที่สุด ซึ่งเป็นสาเหตุที่ทำให้สังเกตเห็นความเสียหายได้ยาก เพราะโมเดลที่ถูกทำ Quantization มาไม่ดีก็ยังคงเขียนประโยคที่อ่านรู้เรื่องได้ ความแม่นยำ (Precision) คือส่วนแรกที่สูญเสียไป เช่น การเรียกคืนหมายเลขเวอร์ชัน ลายเซ็นของ API หรือวันที่ได้อย่างถูกต้องแม่นยำ รวมถึงกระบวนการคิดที่เป็นลำดับขั้นยาวๆ ซึ่งข้อผิดพลาดเพียงเล็กน้อยในขั้นตอนที่ 2 อาจนำไปสู่คำตอบที่ผิดพลาดในขั้นตอนที่ 8 และรูปแบบผลลัพธ์ที่เข้มงวด ซึ่งการวางวงเล็บผิดเพียงจุดเดียวก็ทำให้การเรียกใช้เครื่องมือ (tool call) ล้มเหลว

กรณีสุดท้ายคือบททดสอบในทางปฏิบัติ เมื่อโมเดลต้องส่งผลลัพธ์เป็น JSON เพื่อให้โค้ดของคุณนำไปประมวลผล ความเสียหายจากการทำ Quantization จะปรากฏออกมาในรูปแบบของข้อผิดพลาดในการแยกวิเคราะห์ (parse error) แทนที่จะเป็นเพียงภาษาที่ดูแย่ลงเล็กน้อย ทำให้คุณสังเกตเห็นปัญหาได้ทันทีในวันนั้น การใช้ coding agent เป็นบททดสอบที่เข้มงวดที่สุด เพราะมันจะบังคับให้โมเดลต้องเรียกใช้เครื่องมือซ้ำแล้วซ้ำเล่า ดังนั้นการ ชี้เป้า agent ไปยังเซิร์ฟเวอร์ Ollama ของคุณ จะทำให้เห็นผลกระทบของการทำ Quantization ที่รุนแรงเกินไปได้ภายในช่วงบ่าย

หากต่ำกว่า 4 บิต การสูญเสียคุณภาพจะเพิ่มขึ้นอย่างรวดเร็ว ประเภท q3 และ 2 บิต มีไว้สำหรับผู้ที่ต้องการบีบอัดโมเดลขนาดใหญ่ลงในฮาร์ดแวร์ที่มีจำกัด ซึ่งเป็นทางเลือกที่ใช้งานได้จริงในกรณีที่ไม่มีทางเลือกอื่นนอกจากต้องรันโมเดลนั้น แต่ไม่ใช่ค่าเริ่มต้นที่ดี สำหรับช่องว่างระหว่าง q4_K_M และ q8_0 นั้นถือว่าน้อยมากจนตารางค่า perplexity ที่เผยแพร่อยู่ไม่สามารถตัดสินได้ว่าแบบใดเหมาะกับภาระงานของคุณ ดังนั้นอย่าพยายามตัดสินด้วยวิธีนั้น ให้ลองรันทั้งสองแบบกับ prompt ของคุณเองจำนวน 30 รายการแล้วอ่านผลลัพธ์ที่ได้ด้วยตนเอง

เมื่อใดที่ควรใช้ q8_0 หรือ fp16

ให้ดึง q8_0 มาใช้เมื่อคุณมีหน่วยความจำเหลือเฟือและงานของคุณไม่ยอมรับความผิดพลาดเล็กน้อย เช่น การสกัดข้อมูลแบบมีโครงสร้าง (structured extraction), การเรียกใช้เครื่องมือ (tool calling) หรือการเขียนโค้ดที่ต้องคอมไพล์ผ่าน นี่คือการซื้อประกันความเสี่ยง ไม่ใช่การทำให้โมเดลฉลาดขึ้นอย่างเห็นได้ชัด

ให้ดึง fp16 มาใช้ด้วยเหตุผลเพียง 2 ประการเท่านั้น คือคุณกำลังทำ quantization โมเดลด้วยตัวเองและต้องการไฟล์ต้นฉบับ หรือคุณกำลังวัดค่าพื้นฐาน (baseline) เพื่อเปรียบเทียบว่าการทำ build แบบ 4-bit ของคุณสูญเสียประสิทธิภาพไปเท่าใด การรันโมเดลจาก fp16 ใช้หน่วยความจำมากกว่า q4_K_M ถึง 3 เท่า ในขณะที่ความแตกต่างนั้นคนส่วนใหญ่ไม่สามารถแยกออกได้ในการทดสอบแบบ blind test และหากรันบนเครื่องที่ใช้ CPU เพียงอย่างเดียว มันจะลดอัตราการสร้างโทเค็น (token rate) ของคุณลงเหลือเพียง 1 ใน 3 เท่านั้น

กฎที่สำคัญกว่าภายใต้ข้อจำกัดด้านหน่วยความจำคือ โมเดลขนาดใหญ่ที่ใช้ q4_K_M มักจะให้ผลลัพธ์ดีกว่าโมเดลขนาดเล็กที่ใช้ q8_0 การใช้ 9.3 GB สำหรับน้ำหนักโมเดลขนาด 14B เทียบกับ 8.9 GB สำหรับน้ำหนักโมเดลขนาด 8B นั้นใช้ 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 fp16

50 GB/s เป็นตัวเลขทางทฤษฎีโดยประมาณสำหรับโฮสต์ที่ใช้ DDR4-3200 แบบ dual channel ส่วนแบ่งของคุณจะน้อยกว่านั้นเนื่องจาก VPS ต้องใช้บัสร่วมกับผู้เช่ารายอื่นบนเครื่องเดียวกัน ดังนั้นให้ถือว่าตัวเลขเหล่านั้นเป็นเพดานที่ไม่มีใครเข้าถึงได้ รูปแบบที่สำคัญคือ: บน CPU การลดจำนวนบิตต่อค่าน้ำหนักลงครึ่งหนึ่งจะทำให้ความเร็วในการสร้าง token เพิ่มขึ้นประมาณสองเท่า การทำ Quantization จึงเป็นกลไกที่ช่วยเพิ่มความเร็วได้มากที่สุดบนเครื่องที่ไม่มี GPU ส่วนอัตราความเร็วที่เหลืออยู่จะยอมรับได้หรือไม่นั้นขึ้นอยู่กับโมเดล และ Nemotron 3.5 Lightning บน VPS ได้คำนวณการแบ่งส่วนนั้นไว้สำหรับรุ่น, tag และค่า RAM ที่ระบุไว้โดยเฉพาะ อีกครึ่งหนึ่งของเวลาที่ต้องรอคือปริมาณที่โมเดลตัดสินใจเขียนออกมา เนื่องจากที่ความเร็ว 10 token ต่อวินาที คำตอบที่มีความยาว 600 token จะใช้เวลาถึงหนึ่งนาทีเต็ม ดังนั้นการ จำกัดการตอบกลับด้วย num_predict มักจะช่วยประหยัดเวลาในการรอได้มากกว่าการลดระดับความแม่นยำลงอีกขั้น

การประมวลผล prompt มีพฤติกรรมที่แตกต่างออกไป การอ่าน prompt ที่ยาวจะถูกจำกัดด้วยพลังการคำนวณ (compute bound) มากกว่าแบนด์วิดท์ ดังนั้นการเพิ่มคอร์จึงช่วยในส่วนนี้ได้ ในขณะที่แทบไม่มีผลต่อความเร็วในการสร้างข้อความ เครื่องที่รับ prompt ขนาด 4k ได้อย่างรวดเร็วแต่สร้างข้อความออกมาอย่างช้าๆ ถือว่ามีพฤติกรรมที่เป็นปกติ

อย่าเชื่อการคำนวณทั้งหมดโดยปราศจากการพิสูจน์ ให้ วัดค่า tokens ต่อวินาทีบนเครื่องของคุณเอง ด้วย prompt เดียวกันในแต่ละระดับ quantization และให้ตัวเลขของคุณเป็นตัวตัดสินเหนือข้อมูลเหล่านี้

การทำ Quantization โมเดลด้วยตนเอง

Ollama สามารถสร้างโมเดลที่ผ่านการทำ quantization จากไฟล์ต้นฉบับที่เป็น fp16 หรือ fp32 ได้ ซึ่งมีความสำคัญเมื่อคุณได้ทำการ fine-tune โมเดลขึ้นมาเองและยังไม่มี library tag รองรับ ให้ระบุตำแหน่งของ unquantized weights ไว้ใน Modelfile:

FROM /path/to/my/model/f16

จากนั้นทำการ build และตรวจสอบผลลัพธ์:

ollama create --quantize q4_K_M mymodel
ollama show mymodel

--quantize รองรับ q8_0, q4_K_S และ q4_K_M ในส่วนนี้จะไม่มีตัวเลือก q6_K หรือ q5_K_M ดังนั้นสำหรับรูปแบบดังกล่าว คุณต้องทำ quantization ด้วยเครื่องมือของ llama.cpp เองแล้วจึงนำเข้าไฟล์ GGUF ที่เสร็จสมบูรณ์เข้ามา วิธีการนำเข้านี้มีข้อควรระวังเฉพาะตัวคือปัญหา chat template ไม่ตรงกัน ซึ่งจะทำให้โมเดลตอบกลับเป็นข้อความที่อ่านไม่รู้เรื่อง โดยคุณสามารถดูรายละเอียดได้ที่ การนำเข้าไฟล์ GGUF เข้าสู่ Ollama บรรทัด quantization จาก ollama show คือวิธีที่คุณใช้ตรวจสอบว่าการ build ได้ผลลัพธ์ตามที่คุณต้องการหรือไม่

สิ่งที่คุณจะพบเมื่อเกิดข้อผิดพลาด

ทุกอย่างทำงานบน 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 แทนที่จะเชื่อชื่อไฟล์ในไฟล์คอนฟิกูเรชันของคุณ

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 หมายถึงสี่บิตต่อหนึ่งน้ำหนัก (weight) จริงหรือไม่?

ไม่จริง จากการวัดผลบน 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 buffer และระบบปฏิบัติการ หากใช้หน้าต่างบริบทขนาด 32k เฉพาะตัวแคชอย่างเดียวก็จะมีขนาดถึง 4.83 GB ดังนั้นควรวางแผนไว้ที่ 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 ขนาดเล็กลงมาใช้งานแทน