Liger Kernel Tutorial: Efficient LLM Training with Triton Kernels

# Tutorial Lengkap Liger Kernel: Efisiensi Training LLM dengan Triton Kernels **Penulis: Ruby Abdullah — PT RUBYTHALIB DATA KONSULTA** **Tanggal: 1 Oktober 2026** ## Pendahuluan Training dan fine-...

By Ruby Abdullah · · tutorial
Liger KernelLLM TrainingTritonPyTorchGPU Optimization

Complete Guide to Liger Kernel: Efficient LLM Training with Triton Kernels

Author: Ruby Abdullah — PT RUBYTHALIB DATA KONSULTA Date: October 1, 2026

Introduction

Training and fine-tuning Large Language Models (LLMs) demands enormous computational resources, particularly GPU VRAM. For many machine learning practitioners, VRAM limitations represent the primary bottleneck — whether performing full fine-tuning or parameter-efficient approaches like LoRA. This is where Liger Kernel comes in as an exceptionally practical solution.

Liger Kernel is a collection of Triton kernels developed by LinkedIn's engineering team, specifically designed to accelerate LLM training while significantly reducing VRAM consumption. The name "Liger" stands for LinkedIn GPU Efficient Runtimes. By replacing standard PyTorch operations with optimized Triton kernels, Liger Kernel can deliver up to 60% memory savings and 20% throughput improvement across popular model architectures like LLaMA, Mistral, Gemma, and Qwen.

In this tutorial, we will explore how to use Liger Kernel across various scenarios — from simple one-line integration with HuggingFace Transformers to individual kernel usage in custom training loops. This tutorial is aimed at ML practitioners who want to maximize their hardware efficiency without sacrificing training quality.

Why Liger Kernel?

There are several compelling reasons to consider Liger Kernel:

  • Significant VRAM savings: Up to 60% memory reduction on average, enabling you to train larger models or use larger batch sizes on the same GPU.
  • Throughput improvement: Up to 20% faster training thanks to Triton kernels optimized for GPU memory access patterns.
  • Broad compatibility: Supports popular architectures including LLaMA, Mistral, Gemma, Qwen, Phi, and more.
  • Easy integration: Just one line of code to enable with HuggingFace Transformers.
  • Numerically accurate: All kernels are tested to ensure computation results are identical to standard PyTorch implementations.
  • Open source: Available on GitHub under the BSD-2-Clause license.
  • Available Kernels

    Liger Kernel provides optimized Triton implementations for the following operations:

    • RMSNorm: Root Mean Square Layer Normalization
    • RoPE (Rotary Positional Embedding): Rotary positional encoding
    • SwiGLU: The SwiGLU activation function used in LLaMA and similar models
    • CrossEntropyLoss: Memory-efficient cross-entropy loss function
    • FusedLinearCrossEntropy: Fusion of the final linear layer with cross-entropy loss
    • GeGLU and ReGLU: Other gated linear unit variants
    • Layer Norm: Standard layer normalization
    • GroupNorm: Group normalization

    Installation

    Prerequisites

    Before installing Liger Kernel, ensure your environment meets these requirements:

    • Python 3.8 or newer
    • PyTorch 2.1.2 or newer
    • CUDA toolkit compatible with your PyTorch version
    • NVIDIA GPU with compute capability 7.0 or higher (Volta, Turing, Ampere, Hopper, or Ada Lovelace)

    Installation via pip

    The easiest way to install Liger Kernel:

    pip install liger-kernel
    

    Installation from Source

    To use the latest version directly from the repository:

    git clone https://github.com/linkedin/Liger-Kernel.git
    

    cd Liger-Kernel

    pip install -e .

    Installation with Additional Dependencies

    For development and testing:

    pip install liger-kernel[dev]
    

    Verifying Installation

    After installation, verify that Liger Kernel is properly installed:

    import ligerkernel
    

    print(f"Liger Kernel version: {ligerkernel.version}")

    Verify Triton is available

    import triton

    print(f"Triton version: {triton.version}")

    Quick test

    from ligerkernel.transformers import LigerRMSNorm

    import torch

    norm = LigerRMSNorm(hiddensize=4096).cuda()

    x = torch.randn(2, 128, 4096, device="cuda")

    output = norm(x)

    print(f"RMSNorm output shape: {output.shape}")

    print("Liger Kernel successfully installed and working!")

    Basic Usage

    Integration with HuggingFace Transformers (One Line of Code)

    The easiest way to use Liger Kernel is through the monkey-patching approach. With this method, you only need to add one line of code before loading your model, and Liger Kernel will automatically replace the model's built-in operations with optimized Triton implementations.

    import torch
    

    from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments

    from trl import SFTTrainer

    from datasets import loaddataset

    This one line activates Liger Kernel!

    from ligerkernel.transformers import applyligerkerneltollama

    applyligerkerneltollama()

    Now load the model as usual — kernels are automatically patched

    modelname = "meta-llama/Llama-3.1-8B"

    model = AutoModelForCausalLM.frompretrained(

    modelname,

    torchdtype=torch.bfloat16,

    devicemap="auto",

    )

    tokenizer = AutoTokenizer.frompretrained(modelname)

    tokenizer.padtoken = tokenizer.eostoken

    Prepare dataset

    dataset = loaddataset("tatsu-lab/alpaca", split="train[:1000]")

    def formatprompt(example):

    if example["input"]:

    return f"### Instruction:\n{example['instruction']}\n\n### Input:\n{example['input']}\n\n### Response:\n{example['output']}"

    return f"### Instruction:\n{example['instruction']}\n\n### Response:\n{example['output']}"

    dataset = dataset.map(lambda x: {"text": formatprompt(x)})

    Training arguments

    trainingargs = TrainingArguments(

    outputdir="./output",

    numtrainepochs=1,

    perdevicetrainbatchsize=4,

    gradientaccumulationsteps=4,

    learningrate=2e-5,

    bf16=True,

    loggingsteps=10,

    savestrategy="epoch",

    reportto="none",

    )

    Create trainer and start training

    trainer = SFTTrainer(

    model=model,

    args=trainingargs,

    traindataset=dataset,

    tokenizer=tokenizer,

    datasettextfield="text",

    maxseqlength=2048,

    )

    trainer.train()

    Monkey-Patch Functions for Different Architectures

    Liger Kernel provides architecture-specific monkey-patch functions for each supported model:

    # For LLaMA models (LLaMA 2, LLaMA 3, LLaMA 3.1, etc.)
    

    from ligerkernel.transformers import applyligerkerneltollama

    applyligerkerneltollama()

    For Mistral models

    from ligerkernel.transformers import applyligerkerneltomistral

    applyligerkerneltomistral()

    For Gemma and Gemma 2

    from ligerkernel.transformers import applyligerkerneltogemma

    applyligerkerneltogemma()

    from ligerkernel.transformers import applyligerkerneltogemma2

    applyligerkerneltogemma2()

    For Qwen 2 and Qwen 2.5

    from ligerkernel.transformers import applyligerkerneltoqwen2

    applyligerkerneltoqwen2()

    For Phi-3

    from ligerkernel.transformers import applyligerkerneltophi3

    applyligerkerneltophi3()

    Controlling Monkey-Patch Parameters

    Each monkey-patch function accepts optional parameters to control which kernels are activated:

    from ligerkernel.transformers import applyligerkerneltollama
    
    

    applyligerkerneltollama(

    rope=True, # Enable Triton RoPE (default: True)

    crossentropy=True, # Enable Triton CrossEntropy (default: True)

    fusedlinearcrossentropy=True, # Enable FusedLinearCrossEntropy (default: True)

    rmsnorm=True, # Enable Triton RMSNorm (default: True)

    swiglu=True, # Enable Triton SwiGLU (default: True)

    )

    Example: only enable RMSNorm and SwiGLU

    applyligerkerneltollama(

    rope=False,

    crossentropy=False,

    fusedlinearcrossentropy=False,

    rmsnorm=True,

    swiglu=True,

    )

    Integration via HuggingFace Trainer Flag

    Starting from recent versions of HuggingFace Transformers, you can enable Liger Kernel directly through TrainingArguments:

    from transformers import TrainingArguments
    
    

    trainingargs = TrainingArguments(

    outputdir="./output",

    useligerkernel=True, # Automatically enable Liger Kernel

    # ... other parameters

    )

    This is the simplest approach as HuggingFace will automatically detect the model architecture and apply the appropriate kernels.

    Advanced Usage

    Using Individual Kernels

    Beyond monkey-patching, you can use Liger kernels individually in custom models or training loops. This gives you full control over which components use Triton kernels.

    LigerRMSNorm

    RMSNorm is a more efficient variant of layer normalization widely used in modern model architectures like LLaMA. Liger's implementation reduces memory footprint by avoiding storage of intermediate tensors.

    import torch
    

    from ligerkernel.transformers import LigerRMSNorm

    Replace nn.RMSNorm or custom RMSNorm implementations

    rmsnorm = LigerRMSNorm(hiddensize=4096, eps=1e-6).cuda()

    Forward pass

    hiddenstates = torch.randn(2, 512, 4096, device="cuda", dtype=torch.bfloat16)

    output = rmsnorm(hiddenstates)

    print(f"Input shape: {hiddenstates.shape}, Output shape: {output.shape}")

    LigerSwiGLUMLP

    SwiGLU is an activation function combining Swish and Gated Linear Unit, used in LLaMA, Mistral, and similar models. Liger's implementation fuses the gate and up projection operations for efficiency.

    import torch
    

    from ligerkernel.transformers import LigerSwiGLUMLP

    Create SwiGLU MLP layer

    swiglumlp = LigerSwiGLUMLP(

    hiddensize=4096,

    intermediatesize=11008,

    ).cuda().to(torch.bfloat16)

    Forward pass

    hiddenstates = torch.randn(2, 512, 4096, device="cuda", dtype=torch.bfloat16)

    output = swiglumlp(hiddenstates)

    print(f"SwiGLU MLP output shape: {output.shape}")

    LigerRoPE (Rotary Positional Embedding)

    RoPE is a popular positional encoding method in modern transformer architectures. Liger's kernel optimizes rotary embedding computation.

    import torch
    

    from ligerkernel.transformers.rope import ligerrotaryposemb

    Simulate query and key tensors

    batchsize, numheads, seqlen, headdim = 2, 32, 512, 128

    q = torch.randn(batchsize, numheads, seqlen, headdim, device="cuda", dtype=torch.bfloat16)

    k = torch.randn(batchsize, numheads, seqlen, headdim, device="cuda", dtype=torch.bfloat16)

    Create cos and sin embeddings

    cos = torch.randn(1, 1, seqlen, headdim, device="cuda", dtype=torch.bfloat16)

    sin = torch.randn(1, 1, seqlen, headdim, device="cuda", dtype=torch.bfloat16)

    Apply rotary embedding using Liger

    qembed, kembed = ligerrotaryposemb(q, k, cos, sin)

    print(f"Q embedded shape: {qembed.shape}")

    print(f"K embedded shape: {kembed.shape}")

    LigerCrossEntropyLoss

    Liger's optimized cross-entropy loss uses chunked computation to drastically reduce memory footprint, especially for large vocabularies.

    import torch
    

    from ligerkernel.transformers import LigerCrossEntropyLoss

    Create loss function

    lossfn = LigerCrossEntropyLoss()

    Simulate logits and labels

    vocabsize = 128256 # LLaMA 3 vocabulary size

    batchsize, seqlen = 2, 512

    logits = torch.randn(batchsize seqlen, vocabsize, device="cuda", dtype=torch.bfloat16)

    labels = torch.randint(0, vocabsize, (batchsize seqlen,), device="cuda")

    Compute loss

    loss = lossfn(logits, labels)

    print(f"Cross-entropy loss: {loss.item():.4f}")

    LigerFusedLinearCrossEntropyLoss

    This is Liger Kernel's most powerful kernel. It fuses the final linear layer (lmhead) with cross-entropy loss, eliminating the need to store the full logits tensor in memory. For models with large vocabularies (e.g., 128K tokens), this provides massive memory savings.

    import torch
    

    from ligerkernel.transformers import LigerFusedLinearCrossEntropyLoss

    Create fused loss function

    fusedlossfn = LigerFusedLinearCrossEntropyLoss()

    Simulate hidden states and weight matrix

    hiddensize = 4096

    vocabsize = 128256

    batchseqlen = 1024 # batchsize seqlen

    hiddenstates = torch.randn(batchseqlen, hiddensize, device="cuda", dtype=torch.bfloat16)

    weight = torch.randn(vocabsize, hiddensize, device="cuda", dtype=torch.bfloat16)

    labels = torch.randint(0, vocabsize, (batchseqlen,), device="cuda")

    Compute loss without materializing the full logits tensor!

    loss = fusedlossfn(hiddenstates, weight, labels)

    print(f"Fused linear cross-entropy loss: {loss.item():.4f}")

    Custom Training Loop with Liger Kernel

    Here is a complete example of using Liger Kernel in a custom training loop without HuggingFace Trainer:

    import torch
    

    from transformers import AutoModelForCausalLM, AutoTokenizer

    from ligerkernel.transformers import applyligerkerneltollama

    Activate Liger Kernel before loading the model

    applyligerkerneltollama()

    Load model and tokenizer

    modelname = "meta-llama/Llama-3.1-8B"

    model = AutoModelForCausalLM.frompretrained(

    modelname,

    torchdtype=torch.bfloat16,

    devicemap="auto",

    )

    tokenizer = AutoTokenizer.frompretrained(modelname)

    tokenizer.padtoken = tokenizer.eostoken

    Setup optimizer

    optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weightdecay=0.01)

    Training loop

    model.train()

    numepochs = 3

    gradientaccumulationsteps = 4

    for epoch in range(numepochs):

    totalloss = 0

    optimizer.zerograd()

    # In practice, use a DataLoader with your dataset

    for step in range(100):

    inputids = torch.randint(0, 32000, (2, 512), device="cuda")

    attentionmask = torch.oneslike(inputids)

    labels = inputids.clone()

    # Forward pass - Liger Kernel is used automatically

    outputs = model(

    inputids=inputids,

    attentionmask=attentionmask,

    labels=labels,

    )

    loss = outputs.loss / gradientaccumulationsteps

    totalloss += loss.item()

    # Backward pass

    loss.backward()

    # Update weights every N steps

    if (step + 1) % gradientaccumulationsteps == 0:

    torch.nn.utils.clipgradnorm(model.parameters(), maxnorm=1.0)

    optimizer.step()

    optimizer.zerograd()

    if (step + 1) % 20 == 0:

    avgloss = totalloss / (step + 1)

    print(f"Epoch {epoch+1}, Step {step+1}, Loss: {avgloss:.4f}")

    print(f"Epoch {epoch+1} complete. Average loss: {totalloss / 100:.4f}")

    Using Liger Kernel with LoRA (PEFT)

    Liger Kernel is fully compatible with parameter-efficient fine-tuning using PEFT/LoRA:

    import torch
    

    from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments

    from peft import LoraConfig, getpeftmodel, TaskType

    from trl import SFTTrainer

    from datasets import loaddataset

    from ligerkernel.transformers import applyligerkerneltollama

    Activate Liger Kernel

    applyligerkerneltollama()

    Load base model

    model = AutoModelForCausalLM.frompretrained(

    "meta-llama/Llama-3.1-8B",

    torchdtype=torch.bfloat16,

    devicemap="auto",

    )

    tokenizer = AutoTokenizer.frompretrained("meta-llama/Llama-3.1-8B")

    tokenizer.padtoken = tokenizer.eostoken

    LoRA configuration

    loraconfig = LoraConfig(

    tasktype=TaskType.CAUSALLM,

    r=16,

    loraalpha=32,

    loradropout=0.05,

    targetmodules=["qproj", "kproj", "vproj", "oproj",

    "gateproj", "upproj", "downproj"],

    )

    Apply LoRA

    model = getpeftmodel(model, loraconfig)

    model.printtrainableparameters()

    Training arguments with Liger Kernel active

    trainingargs = TrainingArguments(

    outputdir="./lora-output",

    numtrainepochs=1,

    perdevicetrainbatchsize=8, # Larger batch size thanks to Liger!

    gradientaccumulationsteps=2,

    learningrate=2e-4,

    bf16=True,

    loggingsteps=10,

    savestrategy="epoch",

    reportto="none",

    )

    Prepare dataset

    dataset = loaddataset("tatsu-lab/alpaca", split="train[:5000]")

    dataset = dataset.map(lambda x: {

    "text": f"### Instruction:\n{x['instruction']}\n\n### Response:\n{x['output']}"

    })

    trainer = SFTTrainer(

    model=model,

    args=trainingargs,

    traindataset=dataset,

    tokenizer=tokenizer,

    datasettextfield="text",

    maxseqlength=2048,

    )

    trainer.train()

    Integration with Axolotl

    Axolotl is a popular fine-tuning framework that natively supports Liger Kernel. You just need to add one line to your YAML configuration:

    # axolotlconfig.yml
    

    basemodel: meta-llama/Llama-3.1-8B

    modeltype: LlamaForCausalLM

    Enable Liger Kernel - just this one line!

    plugins:

    • ligerkernel

    loadin8bit: false

    loadin4bit: true

    adapter: qlora

    lorar: 16

    loraalpha: 32

    loradropout: 0.05

    loratargetmodules:

    • qproj
    • kproj
    • vproj
    • oproj
    • gateproj
    • upproj
    • downproj

    datasetpreparedpath: lastrunprepared

    datasets:

    • path: tatsu-lab/alpaca
    type: alpaca

    sequencelen: 4096

    microbatchsize: 4

    gradientaccumulationsteps: 4

    numepochs: 3

    learningrate: 2e-4

    bf16: true

    Then run training as usual:

    accelerate launch -m axolotl.cli.train axolotlconfig.yml
    

    Integration with LLaMA-Factory

    LLaMA-Factory also supports Liger Kernel. Enable it through the enableligerkernel parameter:

    llamafactory-cli train \
    

    --modelnameorpath meta-llama/Llama-3.1-8B \

    --stage sft \

    --dotrain \

    --finetuningtype lora \

    --lorarank 16 \

    --loraalpha 32 \

    --loratarget qproj,kproj,vproj,oproj,gateproj,upproj,downproj \

    --dataset alpacaen \

    --template llama3 \

    --outputdir ./output \

    --perdevicetrainbatchsize 4 \

    --gradientaccumulationsteps 4 \

    --learningrate 2e-4 \

    --numtrainepochs 3 \

    --bf16 \

    --enableligerkernel true

    Or through a LLaMA-Factory YAML configuration file:

    # trainingconfig.yaml
    

    modelnameorpath: meta-llama/Llama-3.1-8B

    stage: sft

    dotrain: true

    finetuningtype: lora

    lorarank: 16

    loraalpha: 32

    dataset: alpacaen

    template: llama3

    outputdir: ./output

    perdevicetrainbatchsize: 4

    gradientaccumulationsteps: 4

    learningrate: 2.0e-4

    numtrainepochs: 3

    bf16: true

    enableligerkernel: true

    Integration with TRL (Transformer Reinforcement Learning)

    HuggingFace's TRL also supports Liger Kernel directly through training arguments:

    from trl import SFTTrainer, SFTConfig
    
    

    sftconfig = SFTConfig(

    outputdir="./output",

    useligerkernel=True,

    perdevicetrainbatchsize=4,

    numtrainepochs=3,

    learningrate=2e-5,

    bf16=True,

    )

    Benchmarks: Memory Savings and Speed Improvements

    Here are benchmark results demonstrating Liger Kernel's effectiveness across various models and configurations. These benchmarks were conducted on NVIDIA A100 80GB GPUs.

    LLaMA 3.1 8B (Full Fine-Tuning)

    | Metric | Without Liger | With Liger | Change |

    |--------|--------------|------------|--------|

    | Peak VRAM | 72.3 GB | 45.1 GB | -37.6% |

    | Throughput (tokens/sec) | 2,850 | 3,420 | +20.0% |

    | Maximum Batch Size | 2 | 4 | +100% |

    LLaMA 3.1 8B (LoRA Fine-Tuning, rank=16)

    | Metric | Without Liger | With Liger | Change |

    |--------|--------------|------------|--------|

    | Peak VRAM | 24.8 GB | 15.2 GB | -38.7% |

    | Throughput (tokens/sec) | 5,100 | 5,950 | +16.7% |

    | Max Batch Size (24GB GPU) | 4 | 8 | +100% |

    Mistral 7B (Full Fine-Tuning)

    | Metric | Without Liger | With Liger | Change |

    |--------|--------------|------------|--------|

    | Peak VRAM | 68.5 GB | 41.8 GB | -39.0% |

    | Throughput (tokens/sec) | 3,100 | 3,680 | +18.7% |

    Per-Kernel Impact

    To understand each kernel's contribution, here is a memory savings breakdown for LLaMA 3.1 8B:

    | Kernel | VRAM Savings | Speed Improvement |

    |--------|-------------|-------------------|

    | FusedLinearCrossEntropy | ~25-35% | ~5-8% |

    | SwiGLU | ~10-15% | ~5-7% |

    | RMSNorm | ~3-5% | ~2-3% |

    | RoPE | ~2-3% | ~3-5% |

    | CrossEntropy (standalone) | ~5-10% | ~2-3% |

    The FusedLinearCrossEntropy kernel provides the largest impact because it eliminates the need to store the full logits tensor in memory. For models with a 128K token vocabulary and 4096 sequence length, this can save tens of gigabytes of VRAM.

    Running Your Own Benchmarks

    You can run benchmarks on your own hardware:

    import torch
    

    import time

    from transformers import AutoModelForCausalLM, AutoTokenizer

    def benchmarktraining(modelname, useliger=False, numsteps=50):

    """Benchmark training throughput and VRAM usage."""

    torch.cuda.resetpeakmemorystats()

    torch.cuda.emptycache()

    if useliger:

    from ligerkernel.transformers import applyligerkerneltollama

    applyligerkerneltollama()

    model = AutoModelForCausalLM.frompretrained(

    modelname,

    torchdtype=torch.bfloat16,

    devicemap="cuda",

    )

    tokenizer = AutoTokenizer.frompretrained(modelname)

    optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)

    model.train()

    # Warmup

    for in range(3):

    inputids = torch.randint(0, 32000, (2, 512), device="cuda")

    outputs = model(inputids=inputids, labels=inputids)

    outputs.loss.backward()

    optimizer.step()

    optimizer.zerograd()

    torch.cuda.resetpeakmemorystats()

    # Benchmark

    starttime = time.time()

    totaltokens = 0

    for step in range(numsteps):

    inputids = torch.randint(0, 32000, (2, 512), device="cuda")

    outputs = model(inputids=inputids, labels=inputids)

    outputs.loss.backward()

    optimizer.step()

    optimizer.zerograd()

    totaltokens += 2 512

    elapsed = time.time() - starttime

    peakvram = torch.cuda.maxmemoryallocated() / 10243

    print(f"{'With Liger' if useliger else 'Without Liger'}:")

    print(f" Peak VRAM: {peakvram:.2f} GB")

    print(f" Throughput: {totaltokens / elapsed:.0f} tokens/sec")

    print(f" Total time: {elapsed:.1f} sec")

    print()

    del model, optimizer

    torch.cuda.emptycache()

    Run benchmark

    modelname = "meta-llama/Llama-3.1-8B"

    benchmarktraining(modelname, useliger=False)

    benchmarktraining(modelname, useliger=True)

    Best Practices

    1. Always Enable FusedLinearCrossEntropy

    The FusedLinearCrossEntropy kernel provides the largest memory savings. Ensure this kernel is always active, especially for models with large vocabularies:

    applyligerkerneltollama(
    

    fusedlinearcrossentropy=True, # This is the most important one!

    rmsnorm=True,

    swiglu=True,

    rope=True,

    )

    2. Leverage the Saved VRAM

    VRAM savings from Liger Kernel can be leveraged for:

    • Increasing batch size: Larger batch sizes generally result in more stable training and faster convergence.
    • Extending sequence length: Longer context helps models learn long-range dependencies.
    • Avoiding gradient checkpointing: If VRAM is sufficient, disable gradient checkpointing for maximum throughput.

    trainingargs = TrainingArguments(
    

    perdevicetrainbatchsize=8, # Increased from 4

    gradientcheckpointing=False, # Disable if VRAM is sufficient

    maxseqlength=4096, # Longer sequence length

    )

    3. Combine with Other Efficiency Techniques

    Liger Kernel can be combined with other optimization techniques for maximum efficiency:

    from transformers import TrainingArguments, BitsAndBytesConfig
    
    

    Combination: Liger Kernel + QLoRA + Flash Attention

    bnbconfig = BitsAndBytesConfig(

    loadin4bit=True,

    bnb4bitquanttype="nf4",

    bnb4bitcomputedtype=torch.bfloat16,

    bnb4bitusedoublequant=True,

    )

    model = AutoModelForCausalLM.frompretrained(

    modelname,

    quantizationconfig=bnbconfig,

    attnimplementation="flashattention2", # Flash Attention

    devicemap="auto",

    )

    trainingargs = TrainingArguments(

    useligerkernel=True, # Liger Kernel

    perdevicetrainbatchsize=16, # Large batch size!

    bf16=True,

    gradientcheckpointing=True, # For very large models

    gradientcheckpointingkwargs={"usereentrant": False},

    )

    4. Debugging and Validation

    When first using Liger Kernel, validate that model outputs remain consistent:

    import torch
    

    from transformers import AutoModelForCausalLM

    Load model WITHOUT Liger

    modelvanilla = AutoModelForCausalLM.frompretrained(

    modelname, torchdtype=torch.float32, devicemap="cuda"

    )

    Load model WITH Liger

    from ligerkernel.transformers import applyligerkerneltollama

    applyligerkerneltollama()

    modelliger = AutoModelForCausalLM.frompretrained(

    modelname, torchdtype=torch.float32, devicemap="cuda"

    )

    Compare outputs

    inputids = torch.randint(0, 32000, (1, 128), device="cuda")

    with torch.nograd():

    outvanilla = modelvanilla(inputids).logits

    outliger = modelliger(inputids).logits

    diff = (outvanilla - outliger).abs().max()

    print(f"Max absolute difference: {diff.item()}")

    Should be very small (< 1e-5 for float32)

    5. Monitor VRAM Usage

    Always monitor VRAM usage to ensure Liger Kernel is providing the expected benefits:

    import torch
    
    

    def printgpumemory():

    """Print current GPU memory usage."""

    allocated = torch.cuda.memoryallocated() / 10243

    reserved = torch.cuda.memoryreserved() / 10243

    peak = torch.cuda.maxmemoryallocated() / 10243

    print(f"GPU Memory - Allocated: {allocated:.2f} GB, "

    f"Reserved: {reserved:.2f} GB, Peak: {peak:.2f} GB")

    Call at various points in your training loop

    printgpumemory()

    6. Check Version Compatibility

    Ensure Liger Kernel version is compatible with your other libraries:

    # Check installed versions
    

    pip show liger-kernel torch transformers triton

    Update if needed

    pip install --upgrade liger-kernel

    7. Be Selective with torch.compile

    Some Liger kernels may not be fully compatible with torch.compile. If you use torch.compile, test first and disable problematic kernels:

    # If using torch.compile, test compatibility
    

    model = torch.compile(model)

    If errors occur, try disabling specific kernels

    applyligerkerneltollama(

    fusedlinearcrossentropy=False, # Sometimes conflicts with compile

    )

    Common Troubleshooting

    Error: Triton Not Found

    # Install Triton explicitly
    

    pip install triton>=2.1.0

    Error: CUDA Version Mismatch

    Ensure your CUDA toolkit is compatible:

    # Check CUDA version
    

    nvcc --version

    python -c "import torch; print(torch.version.cuda)"

    Kernel Crash or NaN Loss

    If you experience NaN loss after enabling Liger Kernel:

  • Ensure you are using bfloat16 instead of float16 (some kernels are more stable with bf16).
  • Reduce the learning rate.
  • Try disabling kernels one by one to identify the source.
  • # Debug: enable kernels one at a time
    

    applyligerkerneltollama(

    rope=False,

    crossentropy=False,

    fusedlinearcrossentropy=False,

    rmsnorm=True, # Try one at a time

    swiglu=False,

    )

    Conclusion

    Liger Kernel is an invaluable tool for every ML practitioner working with LLMs. With minimal investment of just one additional line of code, you can achieve significant VRAM savings and measurable throughput improvements. This enables you to:

    • Train larger models on the same hardware
    • Use larger batch sizes and sequence lengths for better training quality
    • Reduce cloud computing costs by using smaller GPUs
    • Accelerate experiment iteration cycles

    Key takeaways to remember:

  • Start with monkey-patching: Use applyligerkernelto() or useliger_kernel=True for the easiest approach.
  • FusedLinearCrossEntropy is key: This kernel provides the largest memory savings, especially for models with large vocabularies.
  • Combine with other techniques: QLoRA + Flash Attention + Liger Kernel is an extremely powerful combination for efficient fine-tuning.
  • Validate results: Always compare model outputs with and without Liger to ensure numerical consistency.
  • Framework compatibility: Liger Kernel is natively supported by HuggingFace Transformers, Axolotl, LLaMA-Factory, and TRL.
  • By adopting Liger Kernel in your training workflow, you can focus on what truly matters — data quality, model architecture, and hyperparameter tuning — without worrying about hardware limitations. Happy training!

    For further questions about LLM training optimization, feel free to reach out at ruby@rubythalib.ai.

    Related Articles

    bitsandbytes Tutorial: 4-bit and 8-bit Quantization for Large Language Models

    Tutorial bitsandbytes: Kuantisasi 4-bit dan 8-bit untuk Large Language Models Menjalankan Large Language Model (LLM) sep...

    LitGPT Tutorial: A Framework for Training and Fine-Tuning Large Language Models

    Tutorial LitGPT: Framework untuk Melatih dan Fine-Tuning Large Language Models LitGPT adalah framework open-source dari ...

    TensorRT-LLM: Squeezing Maximum Throughput Out of NVIDIA GPUs for LLM Inference

    TensorRT-LLM: Memeras Throughput Maksimal dari GPU NVIDIA untuk Inference LLM Halo temen-temen, kali ini kita bahas sala...

    DeepSpeed: Training Huge Models on Limited GPUs with ZeRO and Offload

    DeepSpeed: Melatih Model Raksasa di GPU Terbatas dengan ZeRO dan Offload Halo temen-temen, kali ini kita masuk ke topik ...