---
title: 'Index-Batching: Optimizing Bulk Operations'
url: https://www.emergentmind.com/topics/index-batching
type: topic
---

# Index-Batching: Optimizing Bulk Operations

Searching arXiv for the specified papers and closely related work on batching/indexing.
Index-batching, as used across several recent arXiv papers, denotes a family of techniques in which multiple index-related operations are collected and processed together so that fixed costs are amortized, memory access becomes more regular, or linear sweeps over compressed structures become feasible. In the cited literature, this idea appears in at least four technically distinct settings: batched reporting from the positional Burrows–Wheeler Transform (PBWT) for haplotype matching, append-only batched updates for GPU-native hybrid approximate nearest-neighbor indices, batched insertions into B-trees under fragmentation analysis, and batched organization of many small sparse systems in accelerator-resident solvers [2605.15819] [2604.16402] [2603.12211] [2209.03228]. Across these settings, batching is not a single algorithm but a design pattern that couples workload aggregation with data-layout and update-policy choices.

## 1. Core abstraction and recurring motivation

A common abstraction is that a large number of individually modest operations are expensive when executed one at a time because each operation incurs auxiliary overheads: random-access structures in compressed text or genomic indices, per-kernel launch overheads on GPUs, irreversible split policies in dynamic trees, or low-occupancy execution of many small linear systems. Batching changes the granularity of execution so that the implementation can operate on a group of objects with a single sweep, a single launch, or a single analytical state transition [2605.15819] [2604.16402] [2209.03228].

In the PBWT setting, the two phases of set-maximal exact match (SMEM) finding separate discovery from reporting. Phase 1 finds maximal substrings of a query haplotype that occur in the same column-range positions in one or more rows of a haplotype panel, and Phase 2 reports the identities of all haplotypes in which each substring occurs. The cited batching result targets the second phase, which becomes the bottleneck when many haplotypes match each substring or when per-interval access requires extra overhead [2605.15819].

In GRAB-ANNS, batching is motivated by GPU architecture. The paper argues that directly porting CPU-centric hybrid search algorithms to GPUs leads to severe performance degradation because of irregular memory access, branch divergence, and excessive CPU–GPU synchronization. The index is therefore redesigned around bucketed memory layout, fixed-degree adjacency, and append-only batched insertion [2604.16402].

In B-trees, batching has a different role. A batch is a run of consecutive keys inserted at a single position, and the analysis asks how such workloads affect internal fragmentation and long-run space utilization. Here batching is not merely an implementation optimization; it changes the stochastic process analyzed by the generalized Yao framework [2603.12211].

In the implicit Landau operator, batching gathers all small sparse systems of the same size into a single device-resident kernel launch. The independent systems arise from solving one collision problem per spatial point and species, with roughly uniform dimensions per velocity grid [2209.03228].

## 2. PBWT prefix-array access via batching

Haplotype panels are modeled as large binary matrices \(M[0..h-1][0..\ell-1]\) of height \(h\) and length \(\ell\), with total size \(n = h\ell\). The PBWT is commonly used to store such panels compactly so that, given a query haplotype \(Q\), one can find all SMEMs between \(Q\) and the rows of \(M\). For each SMEM \(Q[i..j]\), Phase 2 reports the interval \(a_{j+1}[L..R]\) in the \((j+1)\)-th prefix array, whose length is \(k = R-L+1\) [2605.15819].

Bonizzoni, Gagie, and Gao (2026), as summarized in the batching report, gave two Phase 2 tradeoffs. Scheme A uses \(O\bigl((r+h)\log n\bigr)\) bits and reports an interval of length \(k\) in \(O\bigl(\log\log\min(h,\ell) + k\bigr)\) time. Scheme B uses \(O\bigl(r\log h + h\log n\bigr)\) bits and reports in \(O\bigl(k\log\log h\bigr)\) time. Here \(r\) is the total number of runs in the run-length encoding of all PBWT columns. The batching result observes that, if reporting can be delayed, the second step can instead use \(O\bigl(r\log h\bigr)\) bits and constant time per reported haplotype under explicit workload assumptions [2605.15819].

The key batch size is
\[
T = \frac{r\lg h}{\lg r}.
\]
The method waits until \(T\) SMEM-substrings have been discovered across potentially many queries. If \(K\) denotes the total number of haplotypes to report over those \(T\) substrings, and if the average satisfies
\[
\frac{K}{T} \ge \frac{\lg r}{\lg h},
\]
then \(K \ge r\). Under these conditions, all \(K\) hits can be reported in \(O(K)\) time while using only \(O(r\log h)\) bits of additional space [2605.15819].

The batched reporting algorithm stores one 4-tuple per SMEM, \((\text{query ID}, j, L, R)\), and sorts the records by increasing end-column \(j\). It initializes a doubly-linked list with nodes \(0,1,\dots,h-1\) in order \(a_0\), together with an array mapping each value to its node. As the prefix arrays are built column by column using linear-time linked-list updates, run boundaries are processed by cutting the list, the pieces are stably reordered by bit value, and the pieces are re-spliced to form \(a_{j+1}\). Whenever the current column matches a stored record’s end-column, the algorithm traverses the linked list from the node holding \(L_\alpha\) forward \(R_\alpha-L_\alpha+1\) steps, outputting row IDs [2605.15819].

The complexity statement is explicit. Building prefix arrays via linked-list updates over \(\ell\) columns costs \(O(r)\) total time because the per-column work sums over the number of runs. Traversing all requested intervals costs \(O(K)\). Hence the overall time is \(O(r+K)\), which becomes \(O(K)\) when \(K \ge r\), yielding \(O(1)\) amortized time per reported haplotype. The total space remains \(O(r\log h)\) bits, including the run-length–compressed PBWT, per-run last-entry annotations, and the batch records [2605.15819].

The stated assumptions are equally important. The report assumes \(K=\Omega(r)\); if \(K=o(r)\), it recommends falling back to Scheme B or Scheme A. No randomness is used. A common misconception is that batching in compressed indexing only improves constants; this example shows an asymptotic removal of per-output logarithmic factors, but only after introducing delay and a density assumption on the batched workload. The paper also states that the idea may generalize to RLBWT-based FM-indices, compressed suffix arrays with run-block partitions, and wavelet-tree–based structures when many queries are issued together. This suggests that the decisive property is not PBWT-specific semantics but the availability of a linear sweep that can emit blocks of consecutive identifiers [2605.15819].

## 3. GPU-native index-batching in hybrid search

GRAB-ANNS presents index-batching as a GPU-native update pipeline for dynamic hybrid search. Its global data structures are explicitly pre-allocated in large device arrays: a Global Feature Matrix \(X\) of size \(N_{\mathrm{cap}}\times d\), a Global Adjacency Matrix \(A\) of size \(N_{\mathrm{cap}}\times K_{\max}\), an Index-to-Bucket Map \(M_{I2B}\), and Bucket-to-Index Lists \(M_{B2I}[i]\). Because these structures are pre-allocated, inserting new nodes never requires shifting or re-sorting existing data, and pointers embedded in \(A\) remain valid for the duration of the process [2604.16402].

When a batch \(Q_{\mathrm{new}}\) of \(b\) new objects arrives, insertion proceeds in two lock-free, SIMT-friendly operations entirely on the GPU. First, a single 32-bit atomic counter reserves a contiguous block of physical indices \([L,L+b)\). In a single kernel, threads write each vector into \(X[L+i]\), initialize \(A[L+i]\) to empty, and set \(M_{I2B}[L+i]\leftarrow \text{bucket\_id}(Q_{\mathrm{new}}[i].s)\). Second, each thread appends its new physical index to the corresponding \(M_{B2I}\) list using atomic push operations. The paper states that this two-step append takes \(O(1)\) time per new vector and preserves all existing graph connectivity [2604.16402].

Graph-topology updates are then batched across all \(b\) insertions in three fused stages rather than processed sequentially. Stage 1 performs parallel candidate search: local search within the bucket via \(M_{B2I}[bucket]\), global search for remote linking using the graph \(A\), and candidate merging with pruning. Stage 2 performs forward edge selection by heuristic pruning with freshness bias \(\alpha < 1\), overwriting adjacency slots in \(A[idx]\) and emitting reverse-link requests. Stage 3 applies reverse rewiring in parallel by attempting to insert the new node into the adjacency list of each affected existing node via small-world pruning [2604.16402].

The paper ties batching directly to hardware behavior. Processing all \(b\) insertions in a single launch per stage means the launch overhead is paid only once, while every streaming multiprocessor can stay busy on thousands of threads. The fixed-degree hybrid design is also part of the batching argument: disjoint buckets reduce contention for local updates, the regular \(N_{\mathrm{cap}}\times K_{\max}\) layout yields coalesced 32- or 64-byte loads and stores, and equal row lengths eliminate intra-warp divergence and dynamic pointer chasing [2604.16402].

The complexity description is separated by stage. Physical append is \(O(1)\) per new vector. In Stage 1, each new node performs \(O(\log |B|)\) hops within its bucket, where \(|B|\approx 10^4\), plus \(O(\log N)\) hops on the global graph, and these operations are executed in parallel across \(b\) threads. Forward selection and reverse rewiring are \(O(K_{\max})\) per node, again in parallel. The space overhead is \(O(N\cdot d)\) floats for \(X\), \(O(N\cdot K_{\max})\) integers for \(A\), and \(O(N)\) indices for each of the two maps [2604.16402].

The empirical claims are specific. On four 1 M-vector benchmarks—DEEP-96, SIFT-128, GIST-960, and WIT-2048—bulk ingest of 1 M vectors via the static two-pass build takes 30.2 s to 262.8 s depending on \(d\). Using the batch-insertion pipeline, starting from a base index on 0 vectors and dynamically inserting 1 M vectors, completion takes 32.7 s–226.2 s, described as only an 8.2% overhead in the best case and a 13.9% speedup in the worst. Compared against CPU baselines, this corresponds to 2.8–23.8× faster ingestion. The abstract additionally states up to 240.1 times higher query throughput and 12.6 times faster index construction than state-of-the-art CPU-based systems, and up to 10 times higher throughput compared to optimized GPU-native reimplementations, while maintaining high recall [2604.16402].

A frequent misconception is that batching on accelerators is mainly a matter of grouping work items. GRAB-ANNS presents a stronger claim: batching becomes effective only when memory layout, update policy, and graph topology are co-designed for SIMT execution. In that sense, index-batching here is inseparable from bucketization and fixed-degree regularity.

## 4. Batched insertions and fragmentation in B-trees

In the B-tree setting, batching is formalized as a workload model rather than an implementation pattern. A block has capacity \(B\), with \(B\) assumed odd, and when a block reaches size \(B+1\) it must split irrevocably. Under the even-split rule, \(B+1\) keys are split into \(\lfloor(B+1)/2\rfloor\) and \(\lceil(B+1)/2\rceil\), with tie-breaking to the right sibling. A batched insertion step chooses a leaf at random proportional to its current size \(n\), then inserts \(r\) consecutive new keys at that point. An equivalent view is to choose an interval uniformly among the \(n+1\) gaps and insert \(r\) new keys into that gap in sorted order [2603.12211].

The space-utilization metric is
\[
U = \frac{(N/B)}{X},
\]
where \(N\) is the number of keys and \(X\) is the total number of blocks. Yao’s classical model with \(r=1\) gives \(\lim U = \ln 2 \approx 0.693\) under even splitting. The batched analysis generalizes Yao’s recurrence by replacing the \(r=1\) birth–death matrix with a matrix \(A(B,r)\) that “wraps around” in steps of \(r\). The main convergence theorem states that \(A(B,r)\) is irreducible-Metzler on the subspace of attainable sizes, has a unique positive simple eigenvalue \(\lambda=r\), and all other eigenvalues satisfy \(\Re \lambda' < r\). Consequently, \(v_n/n \to u\), where \(u\) is the unique positive eigenvector satisfying \(A\cdot u = r\cdot u\) [2603.12211].

The resulting fill bound for even splitting is stated as
\[
U \ge 1 - \frac{f(r)}{B},
\]
with \(f(r)=O(\log(r/B))\), more precisely \(f(r)=H_{\lceil B/r\rceil}-H_{\lfloor B/(2r)\rfloor}\) up to constant factors. The proof sketch describes a step-\(r\) recurrence
\[
u_k = \frac{k-r}{k+r}u_{k-r}, \qquad k \ge d+r,
\]
where \(d=\lfloor(B+1)/2\rfloor\), together with residue-class telescoping products [2603.12211].

Batching is not uniformly beneficial in this model. The paper explicitly states that even splitting can degrade to \(U\to 0.5\) at \(r\approx B/2\). It therefore develops two remedies. For medium \(r\), an uneven split with a factor \(\delta\in(0,1)\) can confine blocks to at most three sizes and yields proven fill \(U \ge (3/2)(r/B)\) for \(r/B\in(7/18,0.5)\) and \(U \ge (10/9)(r/B)\) for \(r/B\in(0.5,2/3)\). For large \(r\), deferred even-split rebalances an overflow into \(\lceil(\ell+r)/B\rceil\) nearly equal blocks and yields fill at least \(\max\{(r/B+1/2)/\lceil r/B+1\rceil,\,2/3\}-O(1/B)\). For \(r\in(B/(2i),B/(2i-1)]\), the rescaled chain becomes exactly Yao’s \(2i\)-capacity model, giving the exact formula
\[
U = (2i\,r/B)\,[H_{2i}-H_i].
\]
Practical guidance in the exposition includes thresholds such as using standard even split when \(r < 0.2\cdot B\), switching to \(\delta\)-uneven splitting for \(r\in(0.39B,0.5B)\), and using deferred even splitting when \(r<0.67B\) to guarantee \(U\ge 2/3\) [2603.12211].

This setting clarifies a central limitation of index-batching: aggregating updates can worsen structural quality if the split rule is not adapted to batch size. The paper therefore treats batching as a workload class that must be matched by a compatible rebalancing policy, not as a universally harmless throughput optimization.

## 5. Batched problem indexing in implicit Landau solvers

The Landau collision-operator paper uses batching for many small sparse systems that are indexed by spatial point and species. After finite-element discretization and fully implicit time stepping, each velocity grid produces independent systems of the form
\[
(M + \Delta t\,A_h[u])\,\delta = r,
\]
and in a multi-species problem with \(S\) species and \(N_{\mathrm{space}}\) spatial points, there are \(S\times N_{\mathrm{space}}\) independent systems of roughly the same size, about \(100\)–\(1000\) unknowns [2209.03228].

All small sparse systems of the same size are gathered into a single kernel launch. For each distinct velocity-space grid, the paper builds batched arrays
\[
\texttt{rowPtr[batchSize][nRows+1]},\quad
\texttt{colInd[batchSize][nnzPerSys]},\quad
\texttt{val[batchSize][nnzPerSys]},
\]
together with right-hand sides \(B[\texttt{batchSize}][\texttt{nRows}]\) and solutions \(X[\texttt{batchSize}][\texttt{nRows}]\). The first dimension is the batch, and local row \(i\) of problem \(p\) corresponds to global index \(p\cdot nRows + i\). Padding rounds \(nnzMax\) to a multiple of a warp or wavefront and also pads \(\texttt{rowPtr}\) for efficient team-parallel loops [2209.03228].

The TFQMR implementation uses one Kokkos team per system, with vector lanes traversing rows and inner loops. The entire iterative solve for one small system is contained in a single device kernel, and each system retains its own convergence check so that some systems may exit early while others continue. Different grids are not mixed in a single batch; instead, the code launches one kernel per grid, because all systems on one grid share the same matrix size and sparsity pattern [2209.03228].

The reported performance is architecture-specific. On one A100 node with 4 GPUs, the 2V case with batch size about \(256\) yields Jacobian \(1.57\) s, mass \(0.22\) s, and batched-solve \(0.58\) s per time advance, total \(2.44\) s. The 3V case with batch size about \(32\) yields Jacobian \(29.7\) s, mass \(3.0\) s, and batched-solve \(2.33\) s, total \(35.1\) s. On one MI250X node with 8 GCDs, the 2V case with batch size about \(128\) yields Jacobian \(4.28\) s, mass \(0.29\) s, and solve \(0.49\) s, total \(5.08\) s, while the 3V case with batch size about \(64\) yields Jacobian \(168.2\) s, mass \(18.1\) s, and solve \(11.3\) s, total \(196.8\) s. The paper also states that batched TFQMR is \(2\)–\(20\times\) faster than an aggregated solver that uses one big block diagonal matrix and standard sparse-BLAS launches [2209.03228].

Although this is not an indexing data structure in the database sense, it illustrates an important extension of index-batching: the batch index \(p\) becomes the organizing axis for memory layout, scheduling, and hardware occupancy. A plausible implication is that the same principle underlies several ostensibly different systems papers: the useful “index” is often the batch coordinate itself.

## 6. Cross-cutting trade-offs and scope conditions

Several common trade-offs recur. In PBWT, batching trades delay—waiting for \(T = r\lg h/\lg r\) SMEMs—for \(O(1)\) amortized time per reported haplotype at \(O(r\log h)\) bits. In GRAB-ANNS, batching trades fine-grained per-node insertion for append-only out-of-order insertion and three bulk graph-update stages, thereby reducing kernel-launch overhead and CPU–GPU synchronization. In B-trees, batching changes the insertion workload and can either preserve or damage utilization depending on the split rule. In the Landau solver, batching requires grouping systems by grid so that matrix sizes and sparsity patterns are homogeneous [2605.15819] [2604.16402] [2603.12211] [2209.03228].

Several scope conditions are explicit. PBWT batching assumes \(K=\Omega(r)\) and falls back when \(K=o(r)\). GRAB-ANNS relies on pre-allocated dense arrays, fixed-length neighbor lists, and bucket contiguity. The Landau solver emphasizes batching same-size systems and avoiding mixed sizes in one launch. B-tree analysis depends on the ratio \(r/B\) and shows that even splitting alone is inadequate for some batch regimes [2605.15819] [2604.16402] [2603.12211] [2209.03228].

Two misconceptions are directly countered by the cited results. First, batching does not automatically improve all quality metrics: B-tree even splitting can approach the pathological \(50\%\) bound for \(r\approx B/2\) unless the split strategy is changed [2603.12211]. Second, batching is not merely an implementation detail: in PBWT it removes per-output logarithmic factors under stated assumptions, and in GRAB-ANNS it is inseparable from the index topology and memory layout [2605.15819] [2604.16402].

Taken together, these works suggest that index-batching is most effective when three conditions hold simultaneously: there are many independent or weakly coupled operations, the batched objects admit a regular shared representation, and the system can exploit a sweep- or launch-level amortization that is unavailable to isolated operations. That interpretation aligns with the cited domains without collapsing their differences: compressed genomic reporting, GPU graph indexing, B-tree occupancy, and batched sparse solves each instantiate the same systems principle under very different mathematical and architectural constraints.

Source: https://www.emergentmind.com/topics/index-batching