---
title: CSR to AR-CSR Conversion Algorithm
url: https://www.emergentmind.com/topics/conversion-algorithm-from-csr-to-ar-csr
type: topic
---

# CSR to AR-CSR Conversion Algorithm

A conversion algorithm from Compressed Sparse Row (CSR) to Adaptive Row-grouped CSR (AR-CSR) transforms sparse matrix storage to optimize parallelism, memory access, and arithmetic intensity for architectures such as GPUs. AR-CSR is not a single format, but a designation for blocked or grouped CSR variants that leverage thread-level parallelism or computational reuse through common subexpressions. This article surveys and details both major forms of AR-CSR: (1) **Adaptive Row-grouped CSR for GPU execution** [1203.5737], and (2) **Adder-Rod CSR exploiting common subexpression elimination for constant matrices** [2303.16106], contextualizing them within a formal format-conversion paradigm [2001.02609].

## 1. Prerequisites and Standard CSR Format

CSR encodes a sparse $m\times n$ matrix $A$ as three arrays:
- **values** $[0\,..\,\mathrm{nnz}-1]$: nonzero entries, row-major,
- **colIdx** $[0\,..\,\mathrm{nnz}-1]$: column indices for each value,
- **rowPtr** $[0\,..\,m]$: $\mathrm{rowPtr}[i]$ marks the start of row $i$ in values/colIdx.

Given $i$, entries for row $i$ are indexed as $k\in[\mathrm{rowPtr}[i],\,\mathrm{rowPtr}[i+1])$.

AR-CSR formats generalize CSR by focusing on adaptive grouping or arithmetic compression:

- **GPU-Adaptive AR-CSR** [1203.5737]: Rows are grouped into blocks, with each block mapped to a CUDA-thread block. Thread assignments and data layout are chosen to maximize workload balance and enable coalesced memory access.
- **Adder-Rod (CSE-Based) AR-CSR** [2303.16106]: For pruned/quantized constant matrices, common subexpressions (CSEs) among columns are extracted and encoded to minimize redundant computation and storage.

## 2. GPU-Adaptive Row-grouped CSR: Algorithms and Data Structures

The canonical AR-CSR for GPU computation [1203.5737] groups consecutive rows into "row-groups," designed to match CUDA thread blocks. The conversion comprises four phases:

### 2.1. Row-group Partitioning and GroupInfo Construction

Given tunable parameters `blockSize` (threads per group/block) and `desiredChunkSize` (controls regularity vs. padding), rows are assigned into groups subject to:

- Maximum $blockSize$ rows per group,
- Cumulative nonzeros per group $\leq blockSize \times desiredChunkSize$.

Each group $g$ is characterized by:
- $firstRow_g$: index of first row,
- $size_g$: count of rows,
- $chunkSize_g$: maximum workload (nonzeros handled per thread in $g$),
- $offset_g$: start index in packed arrays (computed later).

### 2.2. Adaptive Thread Assignment (Greedy Splitting)

For each group, assign threads to rows:

1. Initialize each row with 1 thread: $t_r=1$ for $r=0..size{-}1$.
2. Allocate remaining threads to the row currently having the largest "chunk" $f_r = \lceil \mathrm{nnz}_r / t_r \rceil$, incrementing $t_r$.
3. The final $chunkSize_g = \max_r \lceil \mathrm{nnz}_r / t_r \rceil$.
4. Record mapping in `threadMap`.

This process balances load across threads within each group:
$$
f_{g, r} = \left\lceil \frac{\mathrm{nnz}_{g, r}}{t_{g,r}}\right\rceil,
\qquad
chunkSize_g = \max_{0\le r < R} f_{g,r}
$$

### 2.3. Offset Calculation

Compute offsets for packed storage:
$$
offset_0 = 0,\quad
offset_g = \sum_{h<g} chunkSize_h \cdot blockSize
$$

### 2.4. Assembly of AR-CSR Arrays

Allocate storage:
- $M = \sum_g(chunkSize_g \cdot blockSize)$.
- Arrays: $\text{AR\_values}[0..M-1]$, $\text{AR\_colIdx}[0..M-1]$.

For each group $g$ and thread $t$, determine which row/chunk to process using exclusive prefix sums and allocate each thread a contiguous, column-major chunk for coalesced memory access.

Padding is inserted as necessary (with $\text{colIdx} = -1$) to maintain block alignment, enabling early kernel exits.

### 2.5. Pseudocode Summary

```python
# Partition rows
groups = []
for i in range(m):
    ... # as in detailed stepwise algorithm in [1203.5737]
# Thread mapping and chunkSize computation per group
for g in groups:
    ... # greedy assignment as above
# Offset computation
...
# Build AR_values/AR_colIdx
...
```

### 2.6. Computational Complexity

- Partitioning:  $O(m)$.
- Thread assignment: $O(m \cdot blockSize)$.
- Packing: touch every nonzero $O(\mathrm{nnz})$; overall $O(m + \mathrm{nnz})$ for practical block sizes.

## 3. Adder-Rod CSR via Common Subexpression Extraction

Adder-Rod (CSE-based) AR-CSR is designed for sparse constant matrices where weight reuse is possible [2303.16106]. The conversion pipeline:

### 3.1 Construction of Per-Column Unique Weights

For each column $j$, collect unique weights $U_j$, store in a flat array $W$, and record segment boundaries in $WP[j]$. Each T$_{r,j}$ is mapped to a "weight pointer" $p \in [WP[j], WP[j+1])$.

### 3.2 Extraction of Two-term CSEs

- Randomly pair columns and, for each pair, identify the most frequent $(p_i,p_j)$ across all rows.
- Apply a random search (randomly swap columns between pairs) to maximize total gain (number of redundant additions eliminated).
- For each extracted pair with $z_c>1$ occurrences, record $(p_i,p_j)$ and the list of row indices in compressed CSE arrays.

### 3.3 Assembly of Final Structures

- The remaining unmapped nonzeros are encoded as "singles" per row, in $S$ and $SP$.
- Storage:
  - $W, WP$: compressed representation of unique weights.
  - $CSE, CP$: CSE blocks with pointers and their row indices.
  - $S, SP$: singles per row.

### 3.4 Complexity

- Weight collection: $O(\mathrm{nnz} + N U)$.
- CSE extraction: $O(\mathrm{It} \cdot (N + \mathrm{At})\cdot M)$ per random search iteration.

### 3.5 Worked Example

Given a $4\times 4$ matrix with all positions nonzero, CSE-based AR-CSR can reduce addition and multiplication count (and array size) versus CSR, as detailed explicitly in [2303.16106, Section 3].

## 4. General Format-Conversion Paradigms and Optimization

Formal frameworks such as Chou et al. [2001.02609] unify a spectrum of blocked and adaptive compressed formats. Conversion routines operate in three structured phases:

- **Coordinate Remapping:** For each nonzero at $(i, j)$, compute its AR-CSR destination indices, e.g., $(b = \lfloor i/B \rfloor, r = i\,\%\,B, j)$.
- **Attribute Analysis:** Compute histogram queries to allocate group/row pointers.
- **Assembly (Scatter):** One or two passes over nonzeros, possibly fusing remapping and positional assignment for efficiency.

This approach supports both hardware-optimized (GPU) and software-oriented (CSE) AR-CSR formats, producing efficient conversion code that avoids explicit temporaries and can be parallelized or vectorized [2001.02609].

## 5. Data Layout, Thread Assignment, and Memory Behavior

For the GPU AR-CSR [1203.5737]:

- Each group maps directly to a CUDA thread block; threads are adaptively subdivided among rows to minimize maximum per-thread workload ($chunkSize$).
- Storage layout is column-major over threads, ensuring that simultaneous thread accesses map to consecutive physical addresses—this yields fully coalesced memory transactions for both loads and stores.
- Padding with artificial zeros (signaled by $\text{colIdx}=-1$) enforces uniform chunk sizes.

For Adder-Rod AR-CSR [2303.16106]:

- The layout exploits weight sharing and avoids storing duplicate weights by mapping matrix entries to their unique per-column weights.
- CSE blocks and singles structure the data for efficient traversal and minimal redundancy.

## 6. Preprocessing Constraints and Parameter Tuning

Key preprocessing requirements and constraints:

- CSR input must have sorted $\mathrm{rowPtr}$ and valid format.
- No reordering/sorting of column indices; per-row structure is preserved.
- **GPU AR-CSR:** $desiredChunkSize \geq 1$, with larger values beneficial for uniform matrices, but increasing padding in irregular cases.
- **CSE-based AR-CSR:** Efficacy depends on nonzero value repetition ($U$ small), and on the structure yielding frequent CSEs across columns.
- General parallelization possible in all phases; e.g., per-thread histograms in analysis phase can avoid atomics when fusing into per-thread buffers ([2001.02609], [1203.5737]).

## 7. Illustrative Example and Practical Considerations

For a $3\times 3$ matrix:

- Standard CSR arrays ($rowPtr, values, colIdx$) are partitioned into three groups due to chunking rules.
- Each group is handled by a thread block, each row is greedily split onto as many threads as possible (subject to group/block constraints), and chunked for column-major packing.
- Data arrays are padded as required, group descriptors maintained, and thread mapping finalized. The result is a memory layout and thread assignment enabling maximal throughput and efficient block-wise reduction, especially in GPU SpMV kernels [1203.5737].

For CSE AR-CSR, given a $4\times 4$ matrix with repetitive values, the construction yields compressed arrays with minimal redundant additions, as detailed stepwise in [2303.16106], demonstrating storage and runtime savings versus CSR in settings where constant (pruned, quantized) matrices are typical.

---

In summary, conversion from CSR to AR-CSR is a structured, multi-phase process that enables adaptive, hardware-aware, and application-driven storage reorganization. The concrete algorithmic steps and data layouts depend on the targeted variant—whether for maximizing SIMD/thread efficiency or for exploiting arithmetic redundancy. The pattern illustrated in the cited works provides a rigorous pipeline for high-performance sparse matrix storage and computation [1203.5737, 2303.16106, 2001.02609].

Source: https://www.emergentmind.com/topics/conversion-algorithm-from-csr-to-ar-csr