Hyppää sisältöön

A new version of SD Connect and SD Desktop will be available from Monday, September 28. The major upgrade will introduce significant improvements, but also includes changes that are not compatible with the current version of the service. Click here to review the available support materials.

Warning!

Puhti and Mahti computing services have been decommissioned and no new jobs are accepted or executed on its compute nodes. Puhti and Mahti login nodes and storage services are planned to remain available until 15 October 2026. Clean up unnecessary files and move any data you need to keep by 31 August 2026. See the Roihu data migration guide for instructions on transferring your data to Roihu.

Suurten kielimallien käyttö supertietokoneilla

Tässä oppaassa annetaan esimerkkejä ja vinkkejä siihen, miten suurten kielimallien (LLM) kanssa työskennellään CSC:n supertietokoneilla. Se on osa koneoppimisen opas -kokonaisuuttamme.

LLM:t ja GPU-muisti

Jos teet inferenssiä (käytät mallia etkä kouluta sitä), voit joissakin tapauksissa pärjätä ilman GPU:ta, esimerkiksi jos malli on riittävän pieni tai sitä on pienennetty kvantisoinnilla. Useimmissa muissa tapauksissa sinun on kuitenkin käytettävä GPU:ta.

Jotta voit käyttää LLM:ää (tai mitä tahansa neuroverkkoa) GPU:n kanssa, malli on ladattava GPU-muistiin (VRAM). LLM:t voivat olla hyvin suuria, ja tällöin GPU-muistin koko on ratkaisevan tärkeä. Voit katsoa GPU-tilastotaulukostamme täydet tiedot, mutta GPU-laitteidemme VRAM-muistit ovat seuraavat:

  • 64 Gt LUMIssa (AMD MI250x:n yksi GCD)
  • 96 Gt Roihu-GPU:ssa (NVIDIA GH200)

Mallin koko muistissa riippuu siitä, miten painot on tallennettu. Tyypillisesti tavallinen liukulukuarvo tallennetaan tietokoneessa fp32-nimiseen muotoon, joka käyttää 32 bittiä muistia eli 4 tavua (muista, että 8 bittiä = 1 tavu). Syväoppimisessa 16-bittisiä liukulukumuotoja (fp16 tai bf16) on käytetty pitkään nopeuttamaan osaa laskennasta. Ne käyttävät 2 tavua muistia painoa kohden. Viime aikoina mallikokojen kasvaessa vieläkin matalamman tarkkuuden muodot, aina 8 tai jopa 4 bittiin asti, ovat yleistyneet. Yleisiä kvantisointimenetelmiä ovat GPTQ, SpQR ja GGML/GGUF. Jos kvantisointi ei ole sinulle tuttu, katso esimerkiksi tämä verkko-opas LLM:ien kvantisoinnista.

Mallin koko muistissa on tällöin parametrien määrä kerrottuna yhden painon tallentamiseen tarvittavien tavujen määrällä. Esimerkiksi 30 miljardin parametrin malli fp16-muodossa vie 60 Gt muistia. Käytännössä inferenssissä on jopa 20 % yleiskustannusta, joten saatat todellisuudessa tarvita noin 70 Gt muistia, jolloin edes yksi GCD LUMIssa ei ehkä riitä esimerkkimallillemme. Jos sen sijaan tallentaisit mallin 4-bittisellä kvantisoinnilla, se olisi noin 0,5 tavua parametria kohden, eli noin 15 Gt esimerkissämme (tai noin 18 Gt yleiskustannuksen kanssa).

Koulutuksessa muistia tarvitaan paljon enemmän, koska tallennettavana eivät ole vain malli, vaan myös optimoijan tilat, gradientit ja aktivoinnit. Hyvin karkeana arviona mallin hienosäätöön tarvitaan noin 4–6 kertaa mallin koko (gigatavuina), mutta tämä riippuu paljon yksityiskohdista. Esimerkkimme 30B parametrin fp16-malli saattaisi siis vaatia koulutukseen 60 Gt x 6 = 360 Gt GPU-muistia! Käsittelemme tämän ongelman ratkaisutapoja alla olevissa osioissa. Katso lisätietoja EleutherAI:n Transformer Math 101 -blogikirjoituksesta.

LLM:ien hienosäätö

Meillä on git-repositorio, jossa on esimerkkiskriptejä LLM:ien hienosäätöön Roihulla tai LUMIssa. Esimerkissä käytetään Hugging Face (HF) -kirjastoja ja erityisesti HF Traineria annetun mallin kouluttamiseen (malli haetaan HF:n mallirepositorioista) IMDb-elokuva-arvio- aineistolla. Itse tehtävä ei ehkä ole kovin mielekäs, vaan sitä käytetään vain havainnollistamaan teknistä tehtävää, jossa mallia hienosäädetään annetulla aineistolla.

Esimerkeissä käytetään oletuksena EleutherAI/gpt-neo-1.3B -mallia, koska se mahtuisi yhden GPU:n muistiin Puhdissa (CSC:n aiempi supertietokone). Koska kyseessä on 1,37 miljardin parametrin malli, jossa on 32-bittiset painot, yllä mainitun nyrkkisääntömme mukaan se saattaisi vaatia koulutukseen jopa 1,37x4x6 = 32 Gt muistia, joten se juuri ja juuri mahtuisi Puhdin V100-GPU:n 32 Gt enimmäismuistiin (jos käy hyvä tuuri).

Repositoriossa on peruskäynnistysskriptit Roihulle ja LUMIlle yhdelle GPU:lle, kokonaiselle noodille (4 GPU:ta Roihulla ja 8 GPU:ta LUMIssa) sekä kahdelle kokonaiselle noodille (vastaavasti 8 ja 16 GPU:ta).

Monen GPU:n perusversiot käyttävät kaikki PyTorch Distributed Data Parallel (DDP) -tilaa, jossa jokaisella GPU:lla on täydellinen kopio mallista. Vain koulutusdata jaetaan eri GPU:iden kesken. Tämä tarkoittaa, että koko mallin on mahuttava yhden GPU:n muistiin.

Vahvistusoppiminen LLM:ien kanssa

Esimerkkiskriptejä vahvistusoppimiseen LLM:ien kanssa on saatavilla vahvistusoppimisen hienosäätörepositoriossa. Esimerkeissä käytetään verl-kirjastoa, joka on avoimen lähdekoodin kehys LLM:ien vahvistusoppimiseen perustuvaan jatkokoulutukseen. verl tukee monia olemassa olevia LLM-kehyksiä, ja esimerkeissä käytetään FSDP2:ta tai Megatronia mallin koulutukseen sekä vLLM:ää vastausten generointiin.

Esimerkit havainnollistavat vahvistusoppimista verifioitavilla palkkioilla (RLVR) käyttäen GRPO-algoritmia. Niissä hienosäädetään Qwen3-0.6B- ja Qwen3-8B-malleja GSM8K-matematiikka-aineistolla. Repositorio sisältää ympäristön asetukset ja Slurm-skriptit esimerkkien ajamiseen yhdellä ja kahdella LUMI-noodilla.

PEFT:n ja LoRAn käyttö

Jos mallisi mahtuisi GPU-muistiin, on silti mahdollista, että hienosäätöprosessin yleiskustannusten vaatima lisämuisti ei mahdukaan (huomaat tämän nopeasti, kun ohjelma kaatuu CUDA- tai ROCm out-of-memory -virheeseen!). Tällöin ratkaisuna voi olla Parameter Efficient Fine-Tuning (PEFT) -kirjaston käyttö, joka kouluttaa pienemmän määrän lisäparametreja ja vähentää siten koulutuksen yleiskustannusta merkittävästi. PEFT tukee monia menetelmiä, mukaan lukien LoRA ja QLoRA.

PEFT:llä on tyypillisesti noin 10 % alkuperäisestä parametrimäärästä, mutta säästetyn GPU-muistin määrä vaihtelee tilanteesta riippuen. Olemme nähneet säästöjä 5 prosentista 60 prosenttiin.

PEFT on erittäin helppo ottaa käyttöön; katso esimerkki PEFT:n pikakäyttöoppaasta. PEFT voidaan ottaa käyttöön yllä olevassa esimerkissä yksinkertaisesti lisäämällä lippu --peft. Voi olla hyödyllistä perehtyä hieman syvemmin esimerkiksi LoRAn parhaisiin parametreihin.

Acceleraten ja FSDP:n käyttö

Suuremmille malleille, jotka eivät mahdu GPU-muistiin (edes inferenssissä), on käytettävä lähestymistapaa, jossa itse malli (ja koulutuksen yleiskustannus) jaetaan usealle GPU:lle. Emme voi enää säilyttää täydellistä kopiota mallista jokaisella GPU:lla.

Hyvä lähestymistapa, jota PyTorch tukee natiivisti, on Fully Sharded Data Parallel (FSDP). FSDP:ssä mallin parametreja, gradientteja ja optimoijan tiloja ei tallenneta kokonaan jokaiselle GPU:lle, vaan ne jaetaan (shardataan) kaikkien GPU:iden kesken ja kootaan yhteen vain tarvittaessa koulutuksen kulloisessakin vaiheessa.

Ehkä helpoin tapa ottaa FSDP käyttöön suurille kielimalleille on käyttää Hugging Facen Accelerate-kehystä. PyTorch-skriptiin ei tarvita muutoksia, vaan tarvitsee vain vaihtaa käynnistimeksi accelerate. GitHub- repositoriossamme on esimerkkiskriptejä käynnistämiseen yhdellä tai kahdella täydellä noodilla Roihulla:

(Repositoriossa on myös skriptejä LUMIlle, jos katsot tiedostolistausta.)

Myös Monen GPU:n ja monen noodin koneoppimisoppaassamme on Slurm-skriptiesimerkkejä Acceleraten käytöstä FSDP:n kanssa.

Acceleratea käytettäessä on huomioitava kaksi asiaa:

  1. accelerate-käynnistin odottaa konfiguraatio-YAML-tiedostoa. Olemme toimittaneet GitHub-repositorioon kaksi esimerkkiä: accelerate_config.yaml perusesimerkkiä varten ja accelerate_config_fsdp.yaml FSDP:n käyttöä varten. Nämä konfiguraatiot käyttävät järkeviä oletusparametreja, mutta niiden säätäminen voi olla hyödyllistä; erityisesti kannattaa katsoa FSDP:n parametreja.

  2. Monen noodin ajoissa accelerate-käynnistin on käynnistettävä erikseen jokaisella noodilla siten, että --machine_rank-argumentti asetetaan noodin rankin mukaan (0 = ensimmäinen noodi, 1 = toinen noodi jne.). Tämän asettamiseen voidaan käyttää $SLURM_NODEID-muuttujaa, mutta tarvitsemme shell-kikan, jotta sitä ei evaluoida ennen kuin se todella suoritetaan kyseisellä noodilla. (Katso esimerkki siitä, miten tämä voidaan tehdä, skriptistä run-finetuning-roihu-gpu8-accelerate.sh.)

Voit käyttää myös PEFT:iä (LoRA) Acceleraten kanssa esimerkkiskriptissämme lipulla --peft.

Vaihtoehtoiset trainerit

Vaihtoehto tavalliselle Hugging Face Trainerille LLM:ien hienosäätöön on TRL-kirjaston SFTTrainer. Näitä ei käsitellä tässä oppaassa. Suosittelemme tutustumaan esimerkiksi tähän Hugging Facen hienosäätöoppaaseen, joka käsittelee myös Unsloth-kirjastoa.

Hienosäätöesimerkki ilmastodatalla

Käytännön hienosäätöesimerkki on saatavilla repositoriossamme. Esimerkki keskittyy ilmastoon liittyvien tieteellisten artikkeleiden hyödyntämiseen Copernicuksesta pienempikokoisten LLM:ien hienosäätöön (tässä tapauksessa Llama-3.1-8B-Instruct-malli).

Kvantisointi

Kvantisointi on prosessi, jossa LLM:n painot ja aktivoinnit muunnetaan korkean tarkkuuden arvoista, kuten 32-bittisistä liukuluvuista, matalamman tarkkuuden arvoiksi, kuten 8-bittisiksi kokonaisluvuiksi. Tämä pienentää merkittävästi mallin kokonaiskokoa, mikä vähentää muistitarvetta pienen tarkkuuden heikkenemisen kustannuksella. Voit lukea lisää kvantisoinnista esimerkiksi tästä oppaasta.

Kvantisointi voidaan tehdä inferenssin tai koulutuksen aikana. Post-Training Quantization (PTQ) tarkoittaa valmiiksi koulutetun mallin kvantisointia inferenssivaiheessa. Quantization-Aware Training (QAT) puolestaan tehdään koulutuksen aikana kvantisoinnin vaikutusten simuloimiseksi, jolloin tuloksena on kvantisointikohinaa paremmin sietävä malli. Tämä opas keskittyy Post-Training Quantizationiin.

Hyvin suurten mallien kvantisointi voi kestää tunteja, mutta onneksi monista malleista on jo saatavilla kvantisoitu versio esimerkiksi Hugging Facessa. Voit etsiä kvantisoituja malleja mallinimen loppuliitteestä, joka ilmaisee kvantisointimenetelmän, kuten AWQ, GPTQ tai GGUF, tai vaihtoehtoisesti mallin tarkkuuden, kuten 8bit tai 4bit.

bitsandbytes-kvantisoinnin käyttö

Hugging Face Transformersin bitsandbytes-kirjasto tarjoaa ajonaikaisen kvantisoinnin, joka pakkaa painot 8- tai 4-bittisiksi lennossa inferenssin aikana muistin säästämiseksi.

from transformers import BitsAndBytesConfig, AutoModelForCausalLM

bnb_config = BitsAndBytesConfig(
   load_in_4bit=True,
   bnb_4bit_quant_type="nf4",
   bnb_4bit_compute_dtype=torch.bfloat16,
   bnb_4bit_use_double_quant=True,
   bnb_4bit_quant_storage=torch.bfloat16,
)

model = AutoModelForCausalLM.from_pretrained(
   args.model,
   quantization_config=bnb_config,
   ...
)

Voit käyttää sitä LLM:ien hienosäätöesimerkissämme (katso yllä oleva osio) argumentilla --4bit. Vaihtoehtoisesti katso täydellinen esimerkki mallin kvantisoinnista bitsandbytesilla Roihulla tai LUMIssa Github-repositoriostamme.

GPTQ-kvantisoinnin käyttö

bitsandbytesin lisäksi Hugging Face Transformersiin on integroitu myös Gradient Post-Training Quantization (GPTQ). GPTQ suorittaa painomatriisien rivikohtaisen kvantisoinnin optimoimalla jokaisen rivin erikseen niin, että kvantisoidut painot approksimoivat alkuperäisiä arvoja mahdollisimman hyvin minimaalisella rekonstruktio-virheellä.

Toisin kuin ajonaikaiset kvantisointikirjastot, kuten bitsandbytes, GPTQ suorittaa kertaluonteisen pakkausvaiheen kalibrointiaineiston avulla, minkä tuloksena syntyy uusi kvantisoitu malli, joka voidaan tallentaa ja ladata ilman alkuperäisiä täystarkkuuspainoja. Jos haluat käyttää GPTQ-kvantisointia transformersista, luo GPTQConfig -luokka, jossa määritetään kvantisointiin käytettävien bittien määrä, painojen kvantisoinnin kalibrointiaineisto sekä tokenisaattori.

from transformers import GPTQConfig, AutoModelForCausalLM

gptq_config = GPTQConfig(
    bits=4,            
    dataset="c4",        
    tokenizer=tokenizer   
)

model = AutoModelForCausalLM.from_pretrained(
    args.model,
    quantization_config=gptq_config,
    ...
)

GPTQ tukee erilaisia taustajärjestelmiä nopeampaa inferenssiä varten, kuten Marlinia (optimoitu A100:lle) ja ExLlamaV2:ta (optimoitu LLaMA-malleille kuluttajatason GPU:illa). Ota tietty taustajärjestelmä käyttöön välittämällä backend="marlin" tai exllama_config={"version": 2} GPTQConfig-luokalle.

Hugging Facen blogikirjoitus vertailee bitsandbytesin ja GPTQ:n ominaisuuksia, mikä voi auttaa päättämään, kumpi sopii paremmin omaan käyttötapaukseesi. Katso myös täydellinen esimerkki mallin kvantisoinnista GPTQ:lla Hugging Face Transformersin avulla Roihulla tai LUMIssa Github-repositoriostamme.

GPTQ-kvantisoinnin käyttö LLM Compressorin kautta

Toinen tapa tehdä kvantisointia on käyttää GPTQ-modifioijaa LLM Compressor -kirjastosta. LLM Compressor on Hugging Face -malleille tarkoitettu koulutuksen jälkeinen pakkaustyökalupakki. Se soveltaa jo koulutettuun malliin reseptiä (esim. GPTQ-kvantisointia) ja tallentaa pakatun checkpointin, joka voidaan ladata takaisin transformers-kirjastoon. Ajonaikana se vaihtaa mallin lineaarikerrokset pakattuihin ytimiin, jolloin generointi käyttää kvantisoituja matriisikertolaskuja ilman, että inferenssikoodiasi tarvitsee muuttaa. GPTQModifier on kvantisointireseptin komponentti, joka suorittaa GPTQ:n ja kvantisoi painot esimerkiksi muotoon W4A16 (4-bittiset painot, 16-bittiset aktivoinnit) käyttäen pientä kalibrointijoukkoa. Sen avulla voit kvantisoida kohdekerroksia (esim. Linear) ja ohittaa päät (esim. lm_head) tulosteen laadun säilyttämiseksi.

from llmcompressor.entrypoints.oneshot import oneshot
from llmcompressor.modifiers.quantization import GPTQModifier

# Define a GPTQ recipe: 4-bit weights (W4A16), target Linear layers, skip the LM head
recipe = GPTQModifier(targets="Linear", scheme="W4A16", ignore=["lm_head"])

# Apply GPTQ using a small calibration dataset (internally sampled by your script/flags).
# The dataset below ("HuggingFaceH4/ultrachat_200k") is only an example—replace with one suited to your model.
oneshot(model=model, dataset="HuggingFaceH4/ultrachat_200k", recipe=recipe)
Katso täydellinen esimerkki mallin kvantisoinnista GPTQ:lla LLM Compressorin kautta Roihulla tai LUMIssa Github-repositoriostamme.

AWQ-kvantisoinnin käyttö LLM Compressorin kautta

LLM Compressor -kirjaston avulla voit kvantisoida mallin myös Activation-Aware Weight Quantization (AWQ) -menetelmällä. AWQ perustuu havaintoon, että kaikki LLM:n painot eivät vaikuta mallin suorituskykyyn yhtä paljon. Suojaamalla vain noin 1 % kaikkein merkittävimmistä painokanavista kvantisointivirhettä voidaan vähentää merkittävästi. Nämä merkittävät kanavat tunnistetaan aktivaatioiden jakaumien perusteella raakojen painoarvojen sijaan.

from llmcompressor.entrypoints.oneshot import oneshot
from llmcompressor.modifiers.quantization import GPTQModifier

# Define AWQ recipe: 4-bit weights (W4A16_ASYM), target Linear layers, skip LM head
recipe = [AWQModifier(targets=["Linear"], scheme="W4A16_ASYM", ignore=["lm_head"])]

# Apply AWQ with a small calibration set (dataset can be your own or a public one)
# The dataset below ("HuggingFaceH4/ultrachat_200k") is only an example—replace with one suited to your model.
oneshot(  
    model=model,  
    dataset="HuggingFaceH4/ultrachat_200k",  # uses 'validation' split by default inside your script/flags
    recipe=recipe,
)
Katso täydellinen esimerkki mallin kvantisoinnista AWQ:lla LLM Compressorin kautta Roihulla tai LUMIssa Github-repositoriostamme.

Retrieval-augmented generation (RAG)

Retrieval-augmented generation (RAG) on tapa käyttää valmiiksi koulutettua suurta kielimallia yhdessä käyttäjän oman aineiston kanssa ilman laskennallisesti raskasta hienosäätöä tai mallin uudelleenkoulutusta. Lyhyesti tämä toimii tekemällä haku aineistosta ja käyttämällä parhaita hakutuloksia lisäkontekstina kielimallille.

RAG:ssa haku on järjestelmän kriittinen osa, sillä epäonnistunut haku antaa LLM:lle väärän kontekstin, mikä saa LLM:n helposti tuottamaan epäolennaista tietoa. Tehokkaaseen hakuun voidaan hyödyntää upotusmalleja ja nopeita vektorihaun menetelmiä. Katso esimerkki siitä, miten supertietokoneita voidaan hyödyntää Faiss-vektorivaraston valmisteluun uusinta tekniikkaa edustavilla upotusmalleilla, RAG-60K-repositoriostamme.

Inferenssi

Inferenssi eli mallin käyttö kouluttamisen sijaan on yleensä paljon yksinkertaisempaa. Esimerkki-git-repositoriossamme on inferenssiesimerkki tiedostoissa inference-demo.py ja run-inference-roihu.sh. Jos mallisi ei mahdu yhdelle GPU:lle, voit yksinkertaisesti varata lisää GPU:ita ja antaa sitten Hugging Facen hoitaa asian asettamalla mallia ladattaessa device_map='auto', esimerkiksi näin:

model = AutoModelForCausalLM.from_pretrained(args.model, device_map='auto')

Inferenssi Ollamalla

Ollama on suosittu työkalu LLM:ien käyttöön, sillä se tukee useita uusinta tekniikkaa edustavia malleja, joita voidaan käyttää API:n kautta. Ollama on suunniteltu toimimaan palveluna, eikä se siksi sovellu suoraan ajettavaksi eräajona supertietokoneilla. Sitä voidaan kuitenkin ajaa osana eräajoa käynnistämällä palvelu työn alussa ja pysäyttämällä se työn päättyessä.

Ensin voit asentaa Ollaman projektikansioosi näin:

cd /projappl/project_2001234  # replace with the appropriate path for you
mkdir ollama
cd ollama
wget https://ollama.com/download/ollama-linux-amd64.tar.zst
tar -xf ollama-linux-amd64.tar.zst
rm ollama-linux-amd64.tar.zst

LUMIssa sinun on tehtävä lisäksi tämä (samassa hakemistossa kuin yllä). Huomaa, että ylimääräisten ROCm-tiedostojen kanssa asennus vie 14 Gt levytilaa!

wget https://ollama.com/download/ollama-linux-amd64-rocm.tar.zst
tar xf ollama-linux-amd64-rocm.tar.zst
rm ollama-linux-amd64-rocm.tar.zst

Eräajossasi sinun tarvitsee sitten vain käynnistää palvelu komennolla ollama serve. Sen jälkeen työsi voi käyttää API:a localhost-osoitteessa portissa 11434. On myös hyvä idea asettaa ympäristömuuttuja OLLAMA_MODELS osoittamaan projektin scratch-alueelle, koska muuten se lataa valtavat mallitiedostot kotihakemistoosi. Katso esimerkkimme Slurm-skriptistä run-ollama.sh Ollaman kanssa ajamiseen.

Myös ai-inference-examples-repositoriossa on joitakin esimerkkejä Ollaman ajamisesta.

Inferenssi vLLM:llä

vLLM on toinen kirjasto LLM-inferenssin ajamiseen. vLLM tukee offline-eräinferenssiä, joka on supertietokoneella ajamiseen parhaiten soveltuva tila. Tämä toimii aivan tavallisena Python-eräajona.

Tässä on käyttäjän laatima esimerkki suuren aineiston tehokkaasta käsittelystä vLLM:llä: https://github.com/TurkuNLP/ECCO-ocr-large-run.

Joissakin tilanteissa tarvitaan silti OpenAI-yhteensopiva palvelin, esimerkiksi rajapintaa käytettäessä muiden ohjelmien kanssa. Esimerkkiskriptejä vLLM:n ajamiseen Roihulla ja LUMIssa löytyy ai-inference-examples-repositoriostamme. Mukana on myös esimerkki ajamisesta usealla noodilla LUMIssa (run-vllm-lumi16.sh).

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta