SSD Nodes Learn Hosting plans →
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-30

Self-hosted LLM வேகம் ஏன் குறைகிறது? தீர்வுகள் என்ன?

ஒரே நேரத்தில் 5 பயனர்கள் பயன்படுத்தும்போது LLM ஏன் மெதுவாகிறது என்பதை அறியுங்கள். Batching, KV cache மற்றும் queue depth ஆகிய காரணிகள் உங்கள் server செயல்திறனை எவ்வாறு பாதிக்கின்றன?

அதிக பயனர்கள் வரும்போது self-hosted LLM ஏன் வேகம் குறைகிறது?

ஒரே நேரத்தில் 5 பயனர்கள் பயன்படுத்தும்போது self-hosted LLM வேகம் குறைகிறது, ஏனெனில் server ஒரு நேரத்தில் ஒரு பதிலை மட்டுமே உருவாக்குகிறது; மற்ற நான்கு பயனர்களும் வரிசையில் காத்திருக்கிறார்கள். Ollama-வின் ஆவணங்கள் இயல்புநிலை அமைப்பைப் பற்றி தெளிவாகக் கூறுகின்றன: OLLAMA_NUM_PARALLEL என்பது "ஒவ்வொரு model-ம் ஒரே நேரத்தில் கையாளக்கூடிய அதிகபட்ச parallel கோரிக்கைகளின் எண்ணிக்கை, இதன் இயல்புநிலை 1 ஆகும்." இதில் எந்தப் பிழையும் இல்லை. உங்கள் ஐந்து பயனர்களில் நான்கு பேர் தங்கள் முறைக்காகக் காத்திருக்கிறார்கள்.

இதற்கான தீர்வு அரிதாகவே பெரிய server-ஐ வாங்குவதாக அமையும். ஒரே forward pass-ல் பல கோரிக்கைகளை model-க்குள் செலுத்தும் ஒரு serving engine-ஐப் பயன்படுத்துவதே சரியான வழி. அத்துடன், அவ்வாறு செய்யும்போது அனைத்து பயனர்களின் உரையாடல்களையும் சேமித்து வைக்கத் தேவையான கூடுதல் memory-யும் இருக்க வேண்டும். இந்த இரண்டுமே முக்கியம், இதில் இரண்டாவது காரணிதான் உங்கள் system-ன் உச்சகட்டத் திறனைத் தீர்மானிக்கிறது.

ஒவ்வொரு கோரிக்கையும் கடந்து செல்லும் இரண்டு நிலைகள்

Prefill என்பது முழு prompt-ஐயும் ஒரே நேரத்தில் படித்து, அதற்கான attention cache-ஐ உருவாக்குகிறது. ஒவ்வொரு prompt token-ம் மாதிரியின் (model) வழியாக ஒன்றாகச் செல்வதால், prefill என்பது ஒரு பெரிய matrix multiply ஆகும்; இது arithmetic throughput-ஆல் கட்டுப்படுத்தப்படுகிறது. Decode நிலை, பதிலை ஒரு நேரத்தில் ஒரு token வீதம் எழுதுகிறது. ஒவ்வொரு token-க்கும் மாதிரியின் முழு weights-ஐயும் மீண்டும் நினைவகத்திலிருந்து (memory) படிக்க வேண்டியுள்ளது, ஆனால் அந்த ஒரு token-க்குச் செய்யப்படும் arithmetic மிகச் சிறியது. Decode நிலை memory bandwidth-ஆல் கட்டுப்படுத்தப்படுகிறது.

இந்த சமச்சீரற்ற தன்மையே batching செயல்படுவதற்கான முழுமையான காரணமாகும். ஒரு பயனருக்காக decoding செய்யும்போது, ஒரு token-க்கு சுமார் 5 GB weights படிக்கப்படுகிறது, ஆனால் பெரும்பாலான arithmetic units சும்மா இருக்கின்றன. இரண்டாவது கோரிக்கையைச் சேர்க்கும்போது, engine அதே 5 GB-ஐ ஒருமுறை படித்து, அதிலிருந்து இரண்டு token-களைக் கணக்கிடுகிறது. இரண்டாவது பயனருக்குக் கூடுதல் நேரம் கிட்டத்தட்ட தேவைப்படுவதில்லை. கோரிக்கைகளை ஒவ்வொன்றாக வரிசையாகச் செயல்படுத்துவது இந்த நன்மையை வீணாக்கிவிடும்.

பயனர் உணரும் அனுபவத்தை இரண்டு எண்கள் விவரிக்கின்றன. TTFT (time to first token) என்பது வரிசையில் காத்திருக்கும் நேரம் மற்றும் prefill ஆகியவற்றின் கூட்டுத்தொகை ஆகும். ITL (inter-token latency) என்பது stream செய்யப்படும் token-களுக்கு இடையே உள்ள இடைவெளி, இது decode நிலையால் தீர்மானிக்கப்படுகிறது. ஒரு server மெதுவாக இருந்தால், அது பொதுவாக இந்த இரண்டில் ஒன்றில் தான் சிக்கலைக் கொண்டிருக்கும், மேலும் இதற்கான தீர்வுகள் வெவ்வேறானவை. எந்தச் சிக்கலை நீங்கள் எதிர்கொள்கிறீர்கள் என்பதை எந்தவொரு அமைப்பையும் மாற்றுவதற்கு முன்பே கண்டறிவது அவசியம், prefill மற்றும் decode நேரத்தைத் தனித்தனியாகக் கணக்கிடுவது இதைக் கண்டறிய உதவும் வழியாகும்.

Static batching-ல் மிக மெதுவான பதிலுக்காக அனைவரும் காத்திருக்க வேண்டியுள்ளது

Static batching என்பது ஒரு எளிமையான முறையாகும்; நீங்கள் application code-ல் கோரிக்கைகளை (requests) நீங்களே தொகுக்கும்போது இது நிகழ்கிறது. Engine ஆனது N எண்ணிக்கையிலான கோரிக்கைகளைச் சேகரித்து, அவற்றை ஒன்றாக இயக்குகிறது. அந்தத் தொகுப்பில் உள்ள மிக நீண்ட generation முடிவடையும் வரை, ஒவ்வொரு slot-ம் பிடித்து வைக்கப்படுகிறது.

1,200 tokens கொண்ட சுருக்கத்தைக் கேட்கும் ஒரு பயனர், நான்கு ஒரு வரி பதில்களை அந்தத் தொகுப்பிலேயே முடக்கி வைக்கிறார். ஏனெனில், அந்தத் தொகுப்பில் உள்ள மிக மெதுவான கோரிக்கை முடியும் வரை எந்தவொரு slot-ம் விடுவிக்கப்படாது.

இதனால் இரண்டு பாதிப்புகள் ஏற்படுகின்றன. முடிவடைந்த sequences எவ்வித பயனுள்ள கணக்கீடும் செய்யாமல் slot-களை ஆக்கிரமித்துக் கொள்கின்றன. இதனால் output நீளம் மாறுபடும்போது, ஒட்டுமொத்த throughput குறைகிறது; chat output-ன் நீளம் அடிக்கடி மாறுபடும் தன்மை கொண்டது. ஒரு தொகுதி உருவான பிறகு வரும் கோரிக்கை, அந்த முழுத் தொகுதியும் முடிவடையும் வரை காத்திருக்க வேண்டும். அதன் prefill தொடங்குவதற்கு முன்பே இது நடப்பதால், அந்தப் புதிய கோரிக்கையின் TTFT மற்றவரின் நீண்ட பதிலால் தீர்மானிக்கப்படுகிறது.

Continuous batching ஒவ்வொரு token-க்கும் கோரிக்கைகளை ஏற்றுக்கொண்டு நிறைவு செய்கிறது

Continuous batching என்பது ஒரு decoding step மட்டத்தில் திட்டமிடப்படுகிறது. ஒவ்வொரு step-க்கு பிறகும், scheduler தனது stop token-ஐ வெளியிட்ட sequences-ஐ நீக்கிவிட்டு, காலியாக உள்ள இடங்களுக்குக் காத்திருக்கும் கோரிக்கைகளை அனுமதிக்கிறது. 40-வது step-ல் முடிவடையும் ஒரு பதில், batch-ன் இறுதியில் அல்லாமல், 40-வது step-லேயே அந்த இடத்தை விடுவிக்கிறது.

இது ஒன்றும் புதிய விஷயம் அல்ல. llama-server, -cb, --cont-batching என்பதை "continuous batching (அதாவது dynamic batching) செயல்படுத்த வேண்டுமா (default: enabled)" என்று ஆவணப்படுத்துகிறது, மேலும் vLLM இந்த அடிப்படையிலேயே கட்டமைக்கப்பட்டுள்ளது. Ollama-வும் இணையாக (parallel) கோரிக்கைகளை வழங்குகிறது. Default அமைப்பு எண்ணிக்கையை ஒன்றாகக் கட்டுப்படுத்துவதால், பல பயனர்கள் தங்கள் hardware-ஆல் concurrency-ஐ கையாள முடியாது என்று தவறாகக் கருதுகின்றனர்; உண்மையில் அவர்களின் configuration தான் அதைத் தடுத்திருக்கும்.

வெளியிடப்பட்ட continuous batching முடிவுகள் பொதுவாக datacenter cards-களில் அளவிடப்படுகின்றன; அவற்றில் உபரி compute வசதியும், cache-க்காக பல்லாயிரக்கணக்கான megabytes நினைவகமும் இருக்கும். அந்த முடிவுகளின் வடிவம் உங்கள் கணினிக்கும் பொருந்தும். ஆனால் அவற்றின் அளவு பொருந்தாது; அதற்கான காரணம் கீழே உள்ள memory பகுதியில் விளக்கப்பட்டுள்ளது.

Prefill மற்றும் decode ஒரே compute வளத்திற்காகப் போட்டியிடுகின்றன

நான்கு பதில்கள் streaming ஆகிக்கொண்டிருக்கும்போது ஒரு புதிய கோரிக்கை (request) வந்தால், அதன் prompt முதலில் prefill செய்யப்பட வேண்டும். Prefill அதிக compute திறனை எடுத்துக்கொள்ளும். Scheduler அந்த prefill-க்குத் தனி step ஒதுக்கினால், அந்த நேரத்தில் streaming-ல் உள்ள நான்கு பயனர்களுக்கும் எந்த token-ம் கிடைக்காது. நீண்ட prompt-களின் போது, திறந்திருக்கும் ஒவ்வொரு window-விலும் இது ஒரு சிறிய இடைவெளியாகத் தெரியும். வேறொருவர் 'send' பட்டனை அழுத்தும்போது server-ல் ஏற்படும் இந்தத் தடுமாற்றத்தையே பயனர்கள் 'hiccups' என்று குறிப்பிடுகின்றனர்.

Chunked prefill, ஒரு நீண்ட prompt-ஐ சிறு பகுதிகளாகப் பிரித்து, ஒவ்வொரு பகுதியையும் இயங்கிக்கொண்டிருக்கும் decode-களுடன் ஒரே step-ல் கலக்கிறது. vLLM-ன் tuning வழிகாட்டி இதிலுள்ள சமநிலையைத் தெளிவாகக் கூறுகிறது: சிறிய chunk budget-கள் "குறைவான prefill-களே decode-களைத் தாமதப்படுத்துவதால், சிறந்த ITL-ஐத் தருகின்றன"; அதேசமயம் அதிக மதிப்புகள் "ஒரே தொகுப்பில் அதிக prefill token-களைச் செயலாக்க முடிவதால், சிறந்த time to first token (TTFT)-ஐத் தருகின்றன". நீங்கள் யாருடைய அனுபவத்திற்கு முன்னுரிமை அளிக்கிறீர்கள் என்பதைத் தீர்மானிக்க வேண்டும்: பதிலுக்காகக் காத்திருக்கும் புதிய பயனரா அல்லது உரை (text) திரையில் வருவதைப் பார்த்துக்கொண்டிருக்கும் பயனர்களா?

Prompt-ன் நீளமே இந்தத் தாக்கம் எவ்வளவு இருக்கும் என்பதைத் தீர்மானிக்கிறது. 6,000 token கொண்ட prompt மற்றும் 200 token கொண்ட பதில் எனில், அது 200 decode step-களுக்கு எதிராக 6,000 token-களுக்கான prefill வேலையாகிறது. Retrieval-augmented chat மற்றும் நீண்ட system prompt-கள் உங்களை இந்த நிலைக்குத் தள்ளுகின்றன. இதனால் prefill என்பது புறக்கணிக்கக்கூடிய ஒன்றாக இல்லாமல், பயனர்கள் காத்திருக்க வேண்டிய முக்கிய காரணியாக மாறுகிறது. நீண்ட prompt-ன் பகுதி மீண்டும் மீண்டும் வரும்போது Prefix caching உதவுகிறது. vLLM இதற்காக --enable-prefix-caching-ஐ வழங்குகிறது; இது ஒவ்வொரு கோரிக்கைக்கும் மீண்டும் கணக்கிடுவதற்குப் பதிலாக, பகிரப்பட்ட prompt prefix-க்கான cache-ஐ மீண்டும் பயன்படுத்திக்கொள்கிறது.

முதலில் தீர்ந்துபோகும் நினைவகம் KV cache ஆகும்

ஒவ்வொரு active conversation-லும் உள்ள ஒவ்வொரு token-ம், model-ன் ஒவ்வொரு layer-லும் ஒரு key vector மற்றும் value vector-ஐ விட்டுச் செல்கிறது. இதுவே KV cache (key/value cache) ஆகும். இதுவே, ஒவ்வொரு புதிய token-க்கும் முழு prompt-ஐயும் மீண்டும் கணக்கிடுவதைத் தவிர்க்க decode-க்கு உதவுகிறது. ஒரு token-க்கான இதன் அளவு model-ன் அமைப்பால் தீர்மானிக்கப்படுகிறது: 2 (ஒரு key, ஒரு value) பெருக்கல் layer எண்ணிக்கை, பெருக்கல் key/value heads எண்ணிக்கை, பெருக்கல் head dimension, பெருக்கல் ஒரு value-க்கான bytes. இந்த எண்களை model-ன் config.json-லிருந்து கண்டறியலாம்.

இதை ஒருமுறை கணக்கிட்டால், நினைவக வரம்பு குறித்த குழப்பம் நீங்கும். 36 layers, 8 key/value heads, 128 head dimension மற்றும் 16-bit cache கொண்ட ஒரு பொதுவான 8B model-க்கு, ஒரு token-க்கு 2 36 8 128 2 bytes தேவைப்படுகிறது. இது 147,456 bytes, அதாவது சுமார் 144 KiB ஆகும். எனவே, 8,192 token கொண்ட ஒரு conversation-க்கு சுமார் 1.2 GB cache தேவைப்படும். ஐந்து conversation-களுக்கு, weights-ஐத் தவிர்த்து சுமார் 6 GB தேவைப்படும். எத்தனை பயனர்கள் ஒரு server-ல் இயங்க முடியும் என்பதற்கான உண்மையான பதில் இதுவே.

Concurrency என்பது context-ஐப் பெருக்குகிறது, இதை கருவிகள் வெளிப்படையாகவே தெரிவிக்கின்றன. Ollama-வின் FAQ: "ஒரு குறிப்பிட்ட model-க்கு இணையாக (parallel) கோரிக்கைகளைச் செயலாக்கும்போது, அந்த parallel கோரிக்கைகளின் எண்ணிக்கைக்கு ஏற்ப context அளவு அதிகரிக்கிறது. உதாரணமாக, 4 parallel கோரிக்கைகளுடன் 2K context பயன்படுத்தினால், அது 8K context ஆகி கூடுதல் நினைவகத்தை ஒதுக்கீடு செய்யும்." தேவையான RAM என்பது OLLAMA_NUM_PARALLEL பெருக்கல் OLLAMA_CONTEXT_LENGTH என்ற அளவில் அமையும். llama-server-ல், -c மூலம் நீங்கள் கேட்கும் context, -np slots-க்கு இடையே பகிரப்படுகிறது. எனவே, slot எண்ணிக்கையை மட்டும் அதிகரிப்பது ஒவ்வொரு கோரிக்கைக்கும் கிடைக்கும் நினைவகத்தைக் குறைக்கும். startup log-ஐப் பார்த்து, ஒவ்வொரு slot-க்கும் எவ்வளவு context கிடைக்கிறது என்பதை உறுதிப்படுத்தவும், ஊகிக்க வேண்டாம்.

vLLM இதற்கு மாறாக முன்கூட்டியே நினைவகத்தை ஒதுக்குகிறது (preallocate). --gpu-memory-utilization (default 0.92) என்பது "model executor-க்காகப் பயன்படுத்தப்பட வேண்டிய GPU நினைவகத்தின் அளவு" ஆகும். weights-க்கு ஒதுக்கியது போக மீதமுள்ள நினைவகம் paged KV pool ஆக மாறுகிறது. அந்த pool தீர்ந்துவிட்டால், scheduler கோரிக்கையைத் தோல்வியடையச் செய்வதற்குப் பதிலாக அதை நீக்குகிறது (evict):

WARNING 05-09 00:49:33 scheduler.py:1057] Sequence group 0 is preempted by PreemptionMode.RECOMPUTE mode because there is not enough KV cache space.

vLLM-ன் V1 engine-ல், default preemption mode என்பது RECOMPUTE ஆகும். எனவே, நீக்கப்பட்ட ஒரு கோரிக்கை அதன் cache-ஐ இழந்து, மீண்டும் அனுமதிக்கப்படும்போது prefills-ஐச் செய்யும். இந்த வேலை இருமுறை செய்யப்படுகிறது. "preemption மற்றும் recomputation ஆகியவை end-to-end latency-ஐப் பாதிக்கலாம்" என்று ஆவணங்கள் எச்சரிக்கின்றன. உங்கள் சராசரி latency சரியாகத் தெரிந்தாலும், ஒரு பயனர் மட்டும் ஏன் நீண்ட நேரம் காத்திருந்தார் என்பதற்கு இந்த log வரிதான் மிகச்சிறந்த விளக்கம். மொத்த எண்ணிக்கையைப் பதிவு செய்ய disable_log_stats=False-ஐ அமைக்கவும், அல்லது vLLM வழங்கும் Prometheus metrics-லிருந்து preemption counter-ஐப் பார்க்கவும்.

2, 5 மற்றும் 20 ஒரேநேர பயனர்கள் இருக்கும்போது ஏற்படும் மாற்றங்கள்

இரண்டு பயனர்கள். போதுமான cache வசதி கொண்ட GPU-வில் இது பெரிய தாக்கத்தை ஏற்படுத்தாது, ஏனெனில் இரண்டாவது decode stream முதலாவதோடு இணைந்து மிகக் குறைந்த கூடுதல் நேரத்திலேயே முடிந்துவிடும். 4 முதல் 8 GB RAM கொண்ட CPU-மட்டும் உள்ள VPS-ல் இது இலவசமல்ல: இரண்டு stream-களும் ஒரே எண்ணிக்கையிலான vCPU-களையும் RAM bandwidth-ஐயும் பகிர்ந்துகொள்கின்றன. எனவே, ஒவ்வொரு பயனருக்கும் வினாடிக்கு கிடைக்கும் tokens எண்ணிக்கை பாதியாகக் குறையும், மேலும் சிறிய பட்ஜெட்டில் cache தேவை இருமடங்காகும்.

ஐந்து பயனர்கள். இங்குதான் default அமைப்புகள் போதுமானதாக இருக்காது, இது ஒரு queue பிரச்சினையாகத் தொடங்குகிறது. OLLAMA_NUM_PARALLEL 1-ஆக இருக்கும்போது, நீண்ட பதிலை எதிர்பார்த்திருப்பவர் முடிக்கும் வரை மற்ற நால்வர் காத்திருக்க வேண்டும், அவர்களின் முறை வரும்போது மட்டுமே அவர்களுக்கு இயல்பான வேகம் கிடைக்கும். Parallel count-ஐ உயர்த்தினால் பிரச்சினையின் வடிவம் மாறும்: தலா 8K context கொண்ட ஐந்து slots-க்கு 40K token cache தேவைப்படும். இது VRAM-ல் பொருந்தவில்லை என்றால், engine layers-ஐ system RAM-க்கு மாற்றும்; அதுவும் பொருந்தவில்லை என்றால், box swap ஆகி வினாடிக்கு கிடைக்கும் tokens எண்ணிக்கை சரிந்துவிடும்.

இருபது பயனர்கள். ஒரு chat UI-ல் இருக்கும் இருபது நபர்கள் பொதுவாக இருபது concurrent requests-ஐ உருவாக்குவதில்லை, வன்பொருளை வாங்குவதற்கு முன் இதைப் புரிந்துகொள்வது மிகவும் முக்கியம். ஒரு பயனர் பதிலை வாசித்துவிட்டு அடுத்த கேள்விக்கு முன் 20 முதல் 60 வினாடிகள் வரை சிந்திப்பார், எனவே அவர்களின் session-ன் பெரும்பகுதி idle-ஆகவே இருக்கும். இருபது agents அல்லது இருபது document summarisation பணிகள் என்பவை, idle நேரம் இல்லாத இருபது உண்மையான streams ஆகும். அதற்கு முற்றிலும் மாறுபட்ட இயந்திரம் தேவை. தனது சொந்த Ollama server-ல் coding agent-ஐ இணைத்த ஒரு developer, முதல் நிலையை விட இரண்டாவது நிலைக்கு அருகிலேயே இருப்பார், ஏனெனில் பணி முடியும் வரை அந்த agent தொடர்ந்து requests-ஐ அனுப்பிக்கொண்டே இருக்கும், மனிதர்கள் வாசிக்கும்போது எடுக்கும் இடைவெளி அதில் இருக்காது.

உங்கள் பயனர்கள் ஒரே நேரத்தில் செயல்படுபவர்களா அல்லது உள்நுழைந்திருப்பவர்கள் மட்டுமா?

எந்தவொரு அளவீட்டையும் தீர்மானிக்கும் முன், ஒரே நேரத்தில் எத்தனை கோரிக்கைகள் (requests in flight) வருகின்றன என்பதைக் கணக்கிடுங்கள். இதற்கான கணக்கீடு எளிதானது: ஒரே நேரத்தில் வரும் கோரிக்கைகள் என்பது, பயனர்களின் எண்ணிக்கை பெருக்கல் ஒரு முறைக்குத் தேவைப்படும் generation வினாடிகள், வகுத்தல் கோரிக்கைகளுக்கு இடையிலான கால இடைவெளி (வினாடிகளில்).

  1. முதலில் உங்கள் சொந்த single-stream வேகத்தை அளவிடுங்கள்; prefill மற்றும் decode இரண்டையும் கணக்கில் கொள்ளுங்கள். மற்றவர்களின் hardware விவரங்களிலிருந்து எண்களை எடுக்காதீர்கள்: உங்கள் கணினியில் tokens per second-ஐ அளவிடுங்கள் மற்றும் உங்களுக்குக் கிடைக்கும் முடிவைப் பயன்படுத்துங்கள்.
  2. Duty cycle-ஐக் கணக்கிடுங்கள். 20 chat பயனர்கள், ஒரு முறைக்கு 12 வினாடிகள் generation, ஒவ்வொரு 90 வினாடிகளுக்கும் ஒரு முறை எனில், 20 * 12 / 90 என்பது சுமார் 2.7 கோரிக்கைகள் ஒரே நேரத்தில் வருவதைக் குறிக்கும்.
  3. Slot எண்ணிக்கையை இதைவிடச் சற்று அதிகமாக வையுங்கள், பின்னர் அதை நினைவகத்துடன் (memory) ஒப்பிட்டுச் சரிபார்க்கவும்: slots எண்ணிக்கை பெருக்கல் ஒரு கோரிக்கைக்கான context அளவு, உங்களிடம் உள்ள cache tokens-க்குள் அடங்க வேண்டும்.
  4. Queue-வைச் சிறியதாக வைத்திருங்கள், அப்போதுதான் overflow ஏற்பட்டால் அது விரைவாகவும் தெளிவாகவும் தெரியும்.

கிடைக்கக்கூடிய cache tokens என்பது, weights-க்குச் சென்றது போக மீதமுள்ள நினைவகம், அதை மேலே குறிப்பிட்ட per-token செலவால் வகுக்க வேண்டும். 24 GB card-ல் 16-bit-ல் 8B model-ஐ இயக்கும்போது, சுமார் 16 GB weights-க்குச் செலவாகும். இயல்பான பயன்பாட்டில் சுமார் 6 GB cache மட்டுமே கிடைக்கும், இது ஐந்து 8K உரையாடல்களுக்குச் சமம். அதிக உரையாடல்களைச் சேர்க்க, per-request context-ஐக் குறைக்கவும் அல்லது cache-ஐ 8-bit-ல் சேமிக்கவும் (llama-server இதற்கு --cache-type-k q8_0-ஐப் பயன்படுத்தும்). இவை இரண்டுமே சில சமரசங்களுடன் concurrency-ஐ அதிகரிக்கின்றன. பணத்தை hardware-ல் முதலீடு செய்வதற்கு முன், இந்தச் சமரசங்களைப் புரிந்துகொள்வது அவசியம்: GPU VPS எப்போது API tokens-ஐ விட லாபகரமாகிறது.

Ollama-ன் இயல்புநிலை அமைப்புகள் போதுமானதாக இல்லாதபோது

Service unit மூலம் parallel count-ஐ அதிகரிக்கவும். ஏனெனில், shell export மூலம் செய்யப்படும் மாற்றங்கள் systemd நிர்வகிக்கும் daemon-க்குச் சென்றடையாது.

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_MAX_QUEUE=64"
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment
ollama ps

systemctl show நீங்கள் இப்போது அமைத்த மூன்று மாறிகளையும் (variables) காட்ட வேண்டும். அவ்வாறு காட்டவில்லை என்றால், drop-in கோப்பு சேமிக்கப்படவில்லை என்று அர்த்தம்; அதன் பிறகு நீங்கள் செய்யும் எந்த மாற்றமும் பலனளிக்காது. ollama ps கட்டளை, எடையை (weights) விட அதிக அளவு கொண்ட ஏற்றப்பட்ட மாதிரியை (loaded model) பட்டியலிடும். ஏனெனில், 8,192 tokens கொண்ட நான்கு slots, அவற்றுக்கு அருகில் 32,768 tokens cache-ஐ ஒதுக்குகின்றன. மாதிரியின் ஒரு பகுதி GPU-வில் இருக்கும் என எதிர்பார்த்த நிலையில், PROCESSOR நெடுவரிசையில் அது CPU-வில் இருப்பதாகக் காட்டினால், கிராபிக்ஸ் கார்டின் கொள்ளளவை விட அதிக cache-ஐ நீங்கள் கோரியுள்ளீர்கள் என்று பொருள். இந்த இரண்டு எண்களில் ஒன்றைக் குறைக்கவும். பொதுவாக context-ஐக் குறைப்பது பாதுகாப்பானது; ஆனால், மிகச் சிறிய window அளவு பிழையைக் காட்டாமல் நீண்ட prompts-ஐ அமைதியாக வெட்டிவிடும் (truncate). எனவே, மாதிரியின் அளவிற்கு ஏற்ப num_ctx-ஐ கவனமாகத் தீர்மானித்தல் சிறந்தது.

Queue இயல்புநிலை அமைப்பை மீண்டும் கவனிக்க வேண்டும். Ollama OLLAMA_MAX_QUEUE கோரிக்கைகள் வரை வரிசைப்படுத்தும், மேலும் "இயல்புநிலை 512 ஆகும்". அதைத் தாண்டினால், "server அதிக சுமையுடன் உள்ளது என்பதைக் குறிக்கும் 503 பிழையை" அது வழங்கும். ஒரே நேரத்தில் நான்கு கோரிக்கைகளை மட்டும் கையாளும் ஒரு server-ல் 512 ஆழமான வரிசை என்பது நிறைவேற்ற முடியாத வாக்குறுதியாகும். ஏனெனில், 300-வது இடத்தில் உள்ள client, தனது முறை வருவதற்கு முன்பே காலாவதியாகிவிடும் (timeout). குறுகிய வரிசை ஒரு பிழையைத் திருப்பி அனுப்பும், அதை உங்கள் application மீண்டும் முயற்சி செய்யவோ அல்லது தெரிவிக்கவோ முடியும்; இது முடிவே இல்லாத காத்திருப்பை விடச் சிறந்தது.

இதைச் சோதித்துப் பார்க்கவும். இரண்டு terminal-களிலிருந்து ஒரே நேரத்தில் இரண்டு கோரிக்கைகளை அனுப்பி இரண்டையும் கவனிக்கவும். முதல் கோரிக்கை முடியும் வரை இரண்டாவது கோரிக்கை எந்த முடிவையும் தராவிட்டால், parallel அமைப்பு செயல்படவில்லை என்று அர்த்தம்.

ஒரு உண்மையான serving engine எப்போது லாபகரமாக மாறுகிறது

உங்களிடம் கூடுதல் திறன் கொண்ட GPU இருந்து, நான்குக்கும் மேற்பட்ட கோரிக்கைகள் (requests) ஒரே நேரத்தில் செயல்பாட்டில் இருக்கும்போது, vLLM-ஐ அமைப்பதற்கான கூடுதல் முயற்சி பயனுள்ளதாக இருக்கும். இதன் scheduler ஒவ்வொரு token-க்கும் தனித்தனியாகச் செயல்படுகிறது, இதன் cache paged முறையில் இருப்பதால் காலியான பகுதிகள் மீண்டும் பயன்படுத்தப்படுகின்றன, மேலும் இது பயன்படுத்தப்படாத VRAM-ஐ செயலற்ற நிலையில் விடாமல் concurrency-ஆக மாற்றுகிறது. ஆகஸ்ட் 2026 நிலவரப்படி, இதற்கான நிறுவல் மற்றும் தொடக்கக் கட்டளைகள் கீழே கொடுக்கப்பட்டுள்ளன:

uv pip install vllm --torch-backend=auto
vllm serve Qwen/Qwen2.5-1.5B-Instruct
curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "Qwen/Qwen2.5-1.5B-Instruct",
        "messages": [{"role": "user", "content": "Say hello."}]
    }'

choices array அடங்கிய பதில் கிடைத்தால், server இயங்குகிறது மற்றும் model ஏற்றப்பட்டுள்ளது என்று அர்த்தம். சுமை (load) அதிகமாக இருக்கும்போது, கவனிக்க வேண்டிய இரண்டு முக்கிய அமைப்புகள்: --max-num-seqs, இது "ஒரே iteration-ல் செயலாக்கப்பட வேண்டிய அதிகபட்ச sequences எண்ணிக்கை", மற்றும் --max-num-batched-tokens, இது "ஒரே iteration-ல் செயலாக்கப்பட வேண்டிய அதிகபட்ச tokens எண்ணிக்கை". முதலாவது concurrency-ஐக் கட்டுப்படுத்துகிறது. இரண்டாவது, முன்னரே விவரிக்கப்பட்ட chunked prefill budget ஆகும்.

நான்குக்கும் குறைவான கோரிக்கைகள் இருக்கும்போது, அல்லது ஆதரவு இல்லாத GPU உள்ள கணினிகளில், vLLM-ஐப் பயன்படுத்துவது சிக்கலை அதிகரிக்குமே தவிர பெரிய பலனைத் தராது. இது CUDA-வகை கார்டுகளை எதிர்பார்க்கிறது மற்றும் தொடக்கத்திலேயே பெரும்பாலான நினைவகத்தை (memory) எடுத்துக்கொள்கிறது; இது 4 முதல் 8 GB VPS-களில் தவறான அணுகுமுறையாகும். அத்தகைய சூழலில், சிறிய model, குறைந்த context மற்றும் நீங்கள் கட்டுப்படுத்தும் queue ஆகியவையே சரியான தீர்வாகும். Ollama மற்றும் vLLM ஆகிய serving engines-களுக்கு இடையிலான வேறுபாடுகள் இந்தத் தேர்வை விரிவாக விளக்குகிறது, மேலும் VPS-ல் Qwen 3 8B-ஐ இயக்குதல் ஒரு நடுத்தர அளவிலான model-க்கு, கூடுதல் பயனர் ஒருவரைச் சேர்ப்பதற்கு முன்பே எவ்வளவு தேவைப்படும் என்பதைக் காட்டுகிறது.

நாட்டுப்புறக் கதைகள் மறைக்கும் வர்த்தக சமநிலை (Tradeoff)

Continuous batching ஒட்டுமொத்த throughput-ஐ அதிகரிக்கிறது, மேலும் வரிசையில் உள்ள கோரிக்கை விரைவில் தொடங்குவதால் இது median latency-ஐயும் மேம்படுத்துகிறது. ஆனால் Tail latency எதிர் திசையில் மாறுகிறது, இந்த பாதிப்பு பெரும்பாலும் குறிப்பிடப்படுவதில்லை.

ஒவ்வொரு படியிலும் சேர்க்கப்படும் கூடுதல் sequence சிறிது கூடுதல் வேலையை உருவாக்குகிறது, எனவே batch நிரம்பும்போது அனைவருக்கும் ITL அதிகரிக்கிறது. புதிதாக வரும் ஒரு கோரிக்கையின் prefill, streaming பயனர்களுக்குக் கிடைக்க வேண்டிய நேரத்தின் ஒரு பகுதியை எடுத்துக்கொள்கிறது. Cache அழுத்தம் இருக்கும்போது scheduler முன்னுரிமை அளித்து (preempt), பாதியிலேயே உருவாக்கப்பட்ட கோரிக்கையை அதன் prefill தொடக்கத்திற்கே திருப்பி அனுப்புகிறது.

ஒரு chat UI சராசரிகளை அல்ல, tails-ஐயே காட்டுகிறது. வாக்கியத்தின் நடுவில் இரண்டு வினாடிகள் நின்றுவிடும் stream, முழுமையாக முடிவடைவதற்கான மொத்த நேரம் குறைவாக இருந்தாலும், பழுதடைந்ததாகவே கருதப்படுகிறது. நீங்கள் எதிர்பார்க்கும் சுமையின் கீழ் p95 TTFT மற்றும் p95 ITL ஆகியவற்றை அளவிடவும். Mean tokens per second என்பதை அனுபவத்தின் விளக்கமாகப் பார்க்காமல், ஒரு capacity அளவீடாகக் கருதவும்.

இதிலிருந்து நடைமுறை அமைப்பு தெளிவாகிறது. நினைவகம் அனுமதிக்கும் அளவை விட concurrency-ஐச் சற்று குறைவாக வைக்கவும், அப்போதுதான் engine எதையும் preempt செய்ய வேண்டிய அவசியம் இருக்காது. தத்தளிக்கும் (thrashes) பெரிய batch-ஐ விட, குறுகிய மற்றும் கணிக்கக்கூடிய வரிசையே சிறந்தது. ஏனெனில், நான்கு வினாடிகள் காத்திருந்து சீராக stream செய்யும் பயனர், உடனடியாகத் தொடங்கி இரண்டு முறை தடைபடும் பயனரை விட மகிழ்ச்சியாக இருப்பார்.

வேகம் குறைவாக இருக்கும்போது எதைச் சரிபார்க்க வேண்டும்

ஒவ்வொரு பயனரும் சாதாரணமாக உள்ளனர், ஆனால் காத்திருப்பு நேரம் அதிகமாக உள்ளது. இது ஒரு வரிசை (queue) சார்ந்த சிக்கல், வேகப் பிரச்சினை அல்ல. முதலில் parallel அமைப்பைச் சரிபார்க்கவும். இந்த model ஒரு நேரத்தில் ஒரு கோரிக்கையை மட்டுமே கையாளும் வகையில் சரியாகச் செயல்படுகிறது.

Ollama-விலிருந்து HTTP 503 பிழை. வரிசை நிரம்பிவிட்டது. சர்வர் அதன் முழுத் திறனில் இயங்குகிறது அல்லது சுமையைக் குறைப்பதற்காக OLLAMA_MAX_QUEUE வேண்டுமென்றே குறைவாக அமைக்கப்பட்டுள்ளது; இது நீங்கள் எதிர்பார்க்கும் செயல்பாடே ஆகும்.

CPU சர்வரில் சுமை அதிகரிக்கும்போது Tokens per second குறைகிறது. இது நடக்கும்போது vmstat 1 கட்டளையை இயக்கவும். si மற்றும் so நெடுவரிசைகளில் பூஜ்ஜியமற்ற மதிப்புகள் இருந்தால், கணினி swapping செய்கிறது என்று அர்த்தம்; அதாவது ஒவ்வொரு token-க்கும் weights வட்டில் (disk) இருந்து படிக்கப்படுகின்றன. எந்தவொரு configuration மாற்றமும் இதைச் சரிசெய்யாது. model-ன் அளவைக் குறைக்கவும் அல்லது slot எண்ணிக்கையைக் குறைக்கவும்.

பத்து பயனர்களில் ஒருவர் மட்டும் மற்றவர்களை விட நீண்ட நேரம் காத்திருக்கிறார். vLLM log-ல் preempted என்பதைத் தேடவும். Preemption மற்றும் அதன் recompute ஆகியவையே இதற்கான பொதுவான காரணங்கள்; நீங்கள் அனுமதிக்கும் context நீளத்திற்கு cache போதவில்லை என்று இது குறிக்கிறது.

சர்வர் சும்மா இருக்கும்போதும் TTFT மோசமாக உள்ளது. இது concurrency அல்ல, prefill சிக்கல். நீண்ட prompts முதல் token தோன்றுவதற்கு முன்பே அதிக நேரத்தை எடுத்துக்கொள்ளும். எனவே வன்பொருளை (hardware) ஆராய்வதற்கு முன் prompt அளவு மற்றும் prefix caching ஆகியவற்றைச் சரிபார்க்கவும். நீண்ட இடைவெளிக்குப் பிறகு வரும் முதல் நபருக்கு மட்டும் அதிக காத்திருப்பு நேரம் இருந்து, அதன் பிறகு வரும் அனைவருக்கும் சரியாக இருந்தால், அது prefill அல்ல. அது Ollama model-ஐ நீக்கிவிட்டு மீண்டும் வட்டில் இருந்து weights-ஐப் படிப்பதால் ஏற்படுகிறது. இதைத் தவிர்க்க கோரிக்கைகளுக்கு இடையே model-ஐ நினைவகத்தில் வைத்திருப்பது சிறந்தது.

FAQ

எனது self-hosted LLM-ஐ இரண்டாவது நபர் பயன்படுத்தும்போது ஏன் வேகம் குறைகிறது?

பெரும்பாலான நேரங்களில் வேகம் குறைவதில்லை, மாறாக அது வரிசையில் (queue) காத்திருக்கிறது. Ollama OLLAMA_NUM_PARALLEL-ஐ 1 என அமைத்து வெளியிடுகிறது, எனவே இரண்டாவது கோரிக்கை முதலாவது கோரிக்கை அதன் இறுதி token-ஐ வெளியிடும் வரை காத்திருக்கும். ஒரு பயனர் stream செய்யும்போது மற்றவர் காத்திருந்தால், அதை வைத்து இரண்டையும் வேறுபடுத்தி அறியலாம்: அவர்கள் stream செய்யத் தொடங்கியதும் அவர்களின் tokens per second வேகம் சாதாரணமாக இருந்தால், அது வரிசைப் பிரச்சினை; parallel count-ஐ அதிகரிப்பதன் மூலம் இதைச் சரிசெய்யலாம். இரண்டு stream-களும் பாதி வேகத்தில் இயங்கினால், நீங்கள் memory bandwidth-ஐப் பகிர்ந்து கொள்கிறீர்கள் என்று அர்த்தம்; இது ஒரு hardware வரம்பு.

ஒரு சிறிய GPU எத்தனை concurrent பயனர்களுக்குச் சேவை வழங்க முடியும்?

பயனர்களைக் கணக்கிடாதீர்கள், memory-ஐக் கணக்கிடுங்கள். முதலில் weights, பிறகு KV cache. இது 2 layers key/value heads head dimension bytes என்ற கணக்கில், ஒவ்வொரு token-க்கும், ஒவ்வொரு active conversation-க்கும் செலவாகும். 36 layers, 8 key/value heads மற்றும் 128 head dimension கொண்ட ஒரு பொதுவான 8B model-க்கு 16-bit-ல் ஒரு token-க்கு சுமார் 144 KiB தேவைப்படும். எனவே, 8,192 token கொண்ட ஒரு உரையாடலுக்கு சுமார் 1.2 GB தேவைப்படும். அந்த model-ஐ 16-bit-ல் வைத்திருக்கும் 24 GB card-ல் cache-க்காக சுமார் 6 GB மீதம் இருக்கும். இது முழு context-ல் சுமார் ஐந்து உரையாடல்களுக்குச் சமம், அல்லது context-ஐக் குறைத்தால் இன்னும் பல உரையாடல்களைச் சேர்க்கலாம்.

Continuous batching ஒவ்வொரு பயனரின் பதிலையும் மெதுவாக்குகிறதா?

பொதுவாக median latency மேம்படும், ஏனெனில் ஒரு batch முடியும் வரை கோரிக்கைகள் காத்திருக்க வேண்டியதில்லை. ஆனால் tail latency மோசமடையும். ஒவ்வொரு கூடுதல் sequence-ம் decoding step-ல் கூடுதல் வேலையைச் சேர்க்கிறது. புதிதாக வரும் கோரிக்கையின் prefill, streaming பயனர்களின் ஒரு பகுதியை எடுத்துக்கொள்கிறது, மேலும் ஒரு preempted கோரிக்கை இரண்டு முறை prefill செய்யப்பட வேண்டும். சராசரி மதிப்பை (average) பார்க்காமல், p95 inter-token latency-ஐ அளவிடுங்கள், ஏனெனில் சராசரி மதிப்புகள் மறைக்கும் இடைவெளிகளை chat window-ல் எளிதாகக் கவனிக்க முடியும்.

நான் OLLAMA_NUM_PARALLEL-ஐ அதிகரிக்க வேண்டுமா அல்லது vLLM-க்கு மாற வேண்டுமா?

முதலில் parallel count-ஐ அதிகரிக்கவும். இது இலவசமானது மற்றும் ஒரு drop-in file மூலம் செய்துவிடலாம். நான்கு பேர் ஒரு நீண்ட பதிலுக்காகக் காத்திருக்கும் பொதுவான சிக்கலை இது சரிசெய்துவிடும். Memory தான் இங்கு வரம்பு: parallel கோரிக்கைகள் நீங்கள் வைத்திருக்க வேண்டிய context-ஐப் பெருக்குகின்றன, எனவே layers CPU-க்குச் செல்கிறதா என்பதைக் கவனியுங்கள். உங்களிடம் கூடுதல் VRAM கொண்ட GPU இருந்து, நான்குக்கும் மேற்பட்ட கோரிக்கைகள் ஒரே நேரத்தில் இயங்கினால் vLLM-க்கு மாறுங்கள். அந்த நிலையில் தான் paged cache மற்றும் per-token scheduling ஆகியவை அதன் செலவை விட அதிக பலனைத் தருகின்றன.

கூடுதல் CPU cores LLM server-ன் வேகத்தை அதிகரிக்குமா?

பயனர்கள் கவனிக்கும் முக்கியப் பகுதியில் இது உதவாது. Decode செய்யும்போது ஒவ்வொரு token-க்கும் முழு model-ம் memory-லிருந்து வாசிக்கப்படுகிறது, எனவே இது RAM bandwidth-ஆல் கட்டுப்படுத்தப்படுகிறது. Bandwidth முழுமையாகப் பயன்படுத்தப்பட்ட பிறகு கூடுதல் cores உதவுவதில்லை. Prefill செய்யும்போது cores-ன் எண்ணிக்கை முக்கியம், எனவே அதிக cores நீண்ட prompts-க்கான time to first token-ஐக் குறைக்கும். 4 முதல் 8 GB VPS-ல் பொதுவாக memory கொள்ளளவுதான் தடையாக இருக்கும். இதற்கு கூடுதல் vCPU-களை விட, சிறிய model-ஐப் பயன்படுத்துவது அல்லது context-ஐக் குறைப்பதுதான் சரியான தீர்வாகும்.