How to Compile the TimesFM Model for Forecasting: PyTorch and JAX Guide

To compile the TimesFM model, load the pretrained weights for your chosen backend, configure the context and horizon lengths, and call model.compile() to build an optimized decode kernel that validates input dimensions and enables high-performance batched inference.

The google-research/timesfm repository provides a 200M parameter time-series foundation model with dual backend support. Compiling the TimesFM model is a mandatory initialization step that prepares the architecture for inference by aligning patch sizes, enforcing context limits, and generating backend-specific execution kernels. This guide details the compilation API for both PyTorch and Flax/JAX implementations using the exact source paths and method signatures from the codebase.

Why Compile the TimesFM Model?

Compilation performs three critical functions before you can call model.forecast():

  • Kernel Generation: Creates a custom decode closure (PyTorch) or nnx.pmap kernel (Flax) that executes the forward pass with fixed max_context and max_horizon dimensions.
  • Validation: Automatically adjusts input and output lengths to be multiples of the model's patch sizes (p for input patches, o for output patches) and verifies that max_context + max_horizon does not exceed the model's internal context limit.
  • Configuration Storage: Persists a ForecastConfig object (PyTorch) or scalar parameters (Flax) that control optional behaviors including input normalization, flip invariance, and continuous quantile heads.

According to src/timesfm/timesfm_2p5/timesfm_2p5_base.py:59-61, the base class explicitly checks that self.compiled_decode exists and raises a clear error if compilation was skipped.

Compiling the PyTorch Backend

The PyTorch implementation requires a ForecastConfig dataclass and performs rigorous limit checking during compilation.

Step-by-Step Compilation Process

In src/timesfm/timesfm_2p5/timesfm_2p5_torch.py, the compile() method executes the following sequence (lines 68-124):

  1. Size Alignment: Adjusts max_context and max_horizon to be multiples of patch sizes p and o (lines 68-84).
  2. Limit Enforcement: Validates that max_context + max_horizon does not exceed self.model.config.context_limit, raising an error if violated (lines 84-89).
  3. Config Storage: Assigns the ForecastConfig instance to self.forecast_config (line 94).
  4. Kernel Construction: Builds a _compiled_decode closure that handles tensor casting, optional normalization, and quantile processing (lines 96-124).
  5. Assignment: Stores the closure in self.compiled_decode (line 87).

PyTorch Compilation Example

import torch
import numpy as np
import timesfm
from timesfm import ForecastConfig

# Load the pretrained TimesFM-2.5 200M PyTorch model

model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
    "google/timesfm-2.5-200m-pytorch"
)

# Configure forecasting parameters

fc = ForecastConfig(
    max_context=1024,          # Input window length (adjusted to patch multiple)

    max_horizon=256,           # Prediction steps (adjusted to patch multiple)

    normalize_inputs=True,     # Enable Revin normalization

    use_continuous_quantile_head=True,
    force_flip_invariance=True,
    infer_is_positive=True,
    fix_quantile_crossing=True,
)

# Compile the model (creates optimized decode kernel)

model.compile(fc)

# Execute forecast

inputs = [np.linspace(0, 1, 100), np.sin(np.linspace(0, 20, 67))]
point, quantile = model.forecast(horizon=12, inputs=inputs)

The ForecastConfig dataclass is defined in src/timesfm/configs.py, while the compilation logic resides in src/timesfm/timesfm_2p5/timesfm_2p5_torch.py.

Compiling the Flax/JAX Backend

The Flax implementation uses direct integer arguments rather than a configuration object and leverages JAX's nnx.pmap for parallel execution.

JAX Compilation Parameters

In src/timesfm/timesfm_2p5/timesfm_2p5_flax.py, the compile() method (lines 43-73) performs:

  • Patch Alignment: Rounds context and horizon to valid patch multiples using the same logic as PyTorch (lines 43-56).
  • Parameter Storage: Assigns self.context, self.horizon, and self.per_core_batch_size (lines 58-60).
  • Parallel Kernel: Constructs compiled_decode_kernel using nnx.pmap to call model.decode across all available devices (lines 62-73).

Unlike the PyTorch backend, the Flax implementation does not explicitly check context limits during compilation; out-of-bounds errors surface during kernel execution.

Flax Compilation Example

import jax.numpy as jnp
import timesfm
from timesfm import TimesFM_2p5_200M_flax

# Load the Flax/JAX checkpoint

model = TimesFM_2p5_200M_flax.from_pretrained(
    "google/timesfm-2.5-200m-flax"
)

# Compile with explicit integers (must be patch multiples)

model.compile(context=1024, horizon=256, per_core_batch_size=1)

# Prepare inputs and forecast

inputs = [jnp.linspace(0, 1, 100), jnp.sin(jnp.linspace(0, 20, 67))]
point, quantile = model.forecast(horizon=12, inputs=inputs)

Post-decode processing in Flax (flip invariance, quantile head application, and crossing fixes) occurs in separate JIT-compiled helpers invoked during forecast(), as seen in src/timesfm/timesfm_2p5/timesfm_2p5_flax.py around lines 70-150.

Summary

Compiling the TimesFM model is a required prerequisite for inference that ensures optimal performance and valid input dimensions:

  • PyTorch: Pass a ForecastConfig object to compile(); the method validates context limits at src/timesfm/timesfm_2p5/timesfm_2p5_torch.py:84-89.
  • Flax/JAX: Pass integer context and horizon values; compilation builds an nnx.pmap kernel at src/timesfm/timesfm_2p5/timesfm_2p5_flax.py:62-73.
  • Both backends validate patch-size alignment and store compilation state required by the base class check in src/timesfm/timesfm_2p5/timesfm_2p5_base.py:59-61.
  • Execute compilation once after from_pretrained() and before the first forecast() call.

Frequently Asked Questions

What happens if I call forecast() without compiling the TimesFM model?

The base class implementation in src/timesfm/timesfm_2p5/timesfm_2p5_base.py:59-61 explicitly checks for the presence of self.compiled_decode. If you attempt to run inference before compilation, the model raises a clear runtime error indicating that the decode kernel has not been initialized.

Can I change the context length after compilation?

No. The compilation process fixes max_context and max_horizon to create an optimized decode kernel. If you need to forecast with different input or output lengths, you must re-invoke model.compile() with the new dimensions. This constraint applies to both the PyTorch and Flax/JAX backends.

How do the PyTorch and JAX compilation approaches differ?

PyTorch compilation uses a ForecastConfig dataclass from src/timesfm/configs.py and enforces strict context limit checks during the compile phase. JAX compilation accepts direct integer arguments for context and horizon, builds a parallelized kernel using nnx.pmap, and delegates limit validation to runtime. The PyTorch backend stores a closure for post-processing, while Flax applies post-decode transformations through separate JIT-compiled functions.

What is the correct per_core_batch_size for JAX compilation?

The per_core_batch_size parameter in Flax compilation determines the batch size per device before parallelization. Set this value based on your hardware memory constraints; the total batch size equals per_core_batch_size multiplied by the device count. For single-device inference, use per_core_batch_size=1 as shown in the Flax example, then scale up for multi-GPU or TPU pods.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →