How to Configure Tile-Based Threading in librav1e
This article explains how to configure tile-based threading in
librav1e, the Rust-based AV1 video encoder. It covers the
underlying concepts of AV1 tiling, provides step-by-step instructions
for configuring tiles via both the command-line interface (CLI) and the
developer API, and outlines best practices for balancing encoding speed
with visual quality.
Understanding AV1 Tiles and Threading
In the AV1 video coding format, a frame can be partitioned into a grid of independently decodable rectangles known as “tiles.” Because these tiles do not rely on spatial prediction from neighboring tiles, they can be encoded and decoded in parallel.
librav1e leverages this architecture to distribute the
encoding workload across multiple CPU threads. To achieve optimal
multi-threaded performance, you must configure both the tile grid
structure and the encoder’s thread limit.
Method 1: Configuring Tiles via the CLI
If you are using the rav1e command-line tool, tile-based
threading is controlled using three primary arguments:
--tile-cols, --tile-rows, and
--threads.
In AV1, tile counts are specified as exponents of 2 (\(\log_2\) values):
--tile-cols <val>: The number of tile columns, expressed as \(2^{\text{val}}\). For example,--tile-cols 1creates \(2^1 = 2\) columns.--tile-rows <val>: The number of tile rows, expressed as \(2^{\text{val}}\). For example,--tile-rows 1creates \(2^1 = 2\) rows.--threads <val>: The maximum number of threads the encoder is allowed to spawn.
Example Command
To encode a video using a 2x2 tile grid (4 tiles total) utilizing 4 threads, use the following command:
rav1e input.y4m -o output.ivf --tile-cols 1 --tile-rows 1 --threads 4Method 2: Configuring Tiles via the Rust API
If you are integrating librav1e directly into a Rust
application, you must configure these parameters inside the
Config and EncoderConfig structures.
- Initialize your
EncoderConfig. - Set the
tile_colsandtile_rowsfields (using \(\log_2\) values). - Set the
threadsoption in the outerConfigstruct to allocate worker threads to the thread pool.
use rav1e::prelude::*;
fn main() {
// 1. Create the base encoder configuration
let mut enc_cfg = EncoderConfig::default();
// Configure a 2x2 tile layout (2^1 columns x 2^1 rows = 4 tiles)
enc_cfg.tile_cols = 1;
enc_cfg.tile_rows = 1;
// 2. Wrap it in the master Config struct and set thread limits
let cfg = Config::new()
.with_encoder_config(enc_cfg)
.with_threads(4); // Allocate 4 threads for parallel tile processing
}Best Practices for Tile Configuration
While increasing the tile count improves encoding speed by enabling higher CPU utilization, it can negatively impact compression efficiency. Because prediction cannot cross tile boundaries, a high density of tiles results in a higher bitrate for the same visual quality.
To achieve the best balance: * 1080p Video: Use 2
columns and 1 row (2 tiles) or 2 columns and 2 rows (4 tiles). *
4K Video: Use 4 columns and 2 rows (8 tiles). *
Thread Allocation: Always ensure your
--threads count is at least equal to the total number of
tiles (columns \(\times\) rows) to
prevent thread starvation during parallel execution.