Implementation:Deepspeedai DeepSpeed Sparse Attention Utils
| Knowledge Sources | |
|---|---|
| Domains | Sparse_Attention, Optimization, Block_Sparse, Algorithms |
| Last Updated | 2026-02-09 00:00 GMT |
Overview
Block-sparse attention pattern segmentation algorithm that groups sparse attention blocks into efficient compute kernels with configurable block sizes.
Description
This utility implements an intelligent segmentation algorithm for structured sparse attention patterns, specifically designed to optimize block-sparse matmul operations. The algorithm takes a sparse attention layout (represented as a 3D tensor indicating which blocks are active) and partitions it into groups of square blocks that can be computed efficiently with specialized kernels. Starting from a configurable maximum block width, it iteratively identifies rectangular regions of active blocks, groups them into square tiles, and tracks their original indices for result gathering. The implementation uses dynamic programming-style analysis to find maximal square subregions while respecting sparsity patterns, enabling coalesced memory access and efficient use of tensor cores. The segmentation is performed independently per attention head, supporting heterogeneous sparsity patterns across heads and layers.
Usage
Use this utility when implementing block-sparse attention mechanisms where the sparsity pattern is known ahead of time (e.g., fixed patterns, local attention, strided patterns). The segmentation output can drive kernel dispatch in sparse attention libraries, enabling significant speedups over dense attention for long sequences while maintaining exactness unlike approximation methods.
Code Reference
Source Location
- Repository: DeepSpeed
- File: csrc/sparse_attention/utils.cpp
Signature
// Main segmentation function
ret_t sdd_segment(torch::Tensor layout, int start_width);
// Internal: segment blocks of specific width
void segment_blocks(torch::Tensor layout, torch::Tensor idx,
torch::Tensor scratch, int max_width, ret_t& ret);
// Return type: vector of (block_width, block_indices)
typedef std::vector<std::tuple<int, torch::Tensor>> ret_t;
Import
import deepspeed.ops.sparse_attention.utils as sparse_utils
I/O Contract
| Input | Type | Description |
|---|---|---|
| layout | torch.Tensor | Sparse pattern [heads×blocks_m×blocks_n] (int) |
| start_width | int | Maximum block size to consider (power of 2) |
| Output | Type | Description |
|---|---|---|
| segments | list of tuples | [(block_size, indices_tensor), ...] |
| block_size | int | Square block dimension (e.g., 16, 32, 64) |
| indices_tensor | torch.Tensor | Indices [num_blocks×4] = [head, m, n, orig_idx] |
Usage Examples
Basic Sparse Pattern Segmentation:
import torch
import deepspeed.ops.sparse_attention.utils as sparse_utils
# Define sparse attention pattern
# 1 = compute this block, 0 = skip
num_heads = 8
seq_blocks = 64 # 64×64 blocks = 4096×4096 tokens (with block_size=64)
layout = torch.zeros(num_heads, seq_blocks, seq_blocks, dtype=torch.int32)
# Example: local attention pattern (diagonal band)
bandwidth = 4
for h in range(num_heads):
for i in range(seq_blocks):
for j in range(max(0, i-bandwidth), min(seq_blocks, i+bandwidth+1)):
layout[h, i, j] = 1
print(f"Sparsity: {(layout == 0).float().mean():.2%}")
# Segment into efficient blocks
segments = sparse_utils.sdd_segment(layout, start_width=64)
print(f"Segmentation result:")
for block_size, indices in segments:
print(f" Block size {block_size}: {indices.size(0)} blocks")
Strided Sparse Attention:
# Strided pattern: attend to every k-th position
def create_strided_pattern(num_heads, seq_blocks, stride=8):
layout = torch.zeros(num_heads, seq_blocks, seq_blocks,
dtype=torch.int32)
for h in range(num_heads):
for i in range(seq_blocks):
# Attend to positions at multiples of stride
for j in range(0, seq_blocks, stride):
layout[h, i, j] = 1
# Also attend to local neighbors
for j in range(max(0, i-2), min(seq_blocks, i+3)):
layout[h, i, j] = 1
return layout
layout = create_strided_pattern(8, 64, stride=8)
segments = sparse_utils.sdd_segment(layout, start_width=64)
# Use segments to dispatch sparse kernels
for block_size, indices in segments:
# Each index: [head_id, row_block, col_block, original_index]
h = indices[:, 0]
m = indices[:, 1]
n = indices[:, 2]
orig_idx = indices[:, 3]
# Dispatch block-sparse matmul of size (block_size × block_size)
# sparse_matmul(Q_blocks[h,m], K_blocks[h,n], block_size)
pass
Fixed Attention Pattern (e.g., BigBird):
def bigbird_pattern(num_heads, seq_blocks, window_size=3,
num_global=2, num_random=3):
"""
BigBird sparse attention pattern:
- Local window around each position
- Global tokens that attend to everything
- Random connections
"""
layout = torch.zeros(num_heads, seq_blocks, seq_blocks,
dtype=torch.int32)
for h in range(num_heads):
# Local window
for i in range(seq_blocks):
for j in range(max(0, i-window_size),
min(seq_blocks, i+window_size+1)):
layout[h, i, j] = 1
# Global tokens (first few blocks)
for i in range(seq_blocks):
for j in range(num_global):
layout[h, i, j] = 1 # Everyone attends to global
layout[h, j, i] = 1 # Global attends to everyone
# Random connections
for i in range(seq_blocks):
rand_indices = torch.randint(0, seq_blocks, (num_random,))
for j in rand_indices:
layout[h, i, j] = 1
return layout
layout = bigbird_pattern(8, 64)
segments = sparse_utils.sdd_segment(layout, start_width=64)
# Sparsity analysis
total_blocks = layout.numel()
active_blocks = (layout == 1).sum().item()
print(f"BigBird sparsity: {100 * (1 - active_blocks/total_blocks):.1f}%")
print(f"Active blocks: {active_blocks}/{total_blocks}")
Multi-Scale Segmentation:
# Try multiple block sizes for better coverage
def multi_scale_segment(layout):
"""
Segment with multiple block sizes: 64, 32, 16
Larger blocks are more efficient but less flexible
"""
all_segments = []
for start_width in [64, 32, 16]:
# Make a copy to avoid modifying original
layout_copy = layout.clone()
segments = sparse_utils.sdd_segment(layout_copy, start_width)
for block_size, indices in segments:
all_segments.append({
'block_size': block_size,
'num_blocks': indices.size(0),
'indices': indices,
'flops': block_size * block_size * indices.size(0)
})
# Remove segmented blocks from layout
for block_size, indices in segments:
for idx in indices:
h, m, n = idx[0].item(), idx[1].item(), idx[2].item()
# Mark surrounding area as covered
layout_copy[h, m, n] = 0
return all_segments
layout = create_strided_pattern(4, 64, stride=8)
multi_segs = multi_scale_segment(layout)
print("Multi-scale segmentation:")
for seg in multi_segs:
print(f" {seg['block_size']}×{seg['block_size']}: "
f"{seg['num_blocks']} blocks, {seg['flops']:,} ops")
Attention Pattern Visualization:
import matplotlib.pyplot as plt
def visualize_segmentation(layout, segments):
"""
Visualize sparse pattern and its segmentation
"""
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# Original pattern
axes[0].imshow(layout[0].cpu(), cmap='binary', interpolation='nearest')
axes[0].set_title('Original Sparse Pattern')
axes[0].set_xlabel('Key Blocks')
axes[0].set_ylabel('Query Blocks')
# Segmented pattern with colors per block size
segmented = torch.zeros_like(layout[0], dtype=torch.float32)
colors = {64: 1.0, 32: 0.7, 16: 0.4, 8: 0.2}
for block_size, indices in segments:
for idx in indices:
if idx[0] == 0: # First head
m, n = idx[1].item(), idx[2].item()
segmented[m, n] = colors.get(block_size, 0.5)
axes[1].imshow(segmented.cpu(), cmap='viridis', interpolation='nearest')
axes[1].set_title('Segmented Blocks (color = block size)')
axes[1].set_xlabel('Key Blocks')
axes[1].set_ylabel('Query Blocks')
plt.tight_layout()
plt.savefig('sparse_attention_segmentation.png')
# Example usage
layout = bigbird_pattern(1, 64)
segments = sparse_utils.sdd_segment(layout, start_width=64)
visualize_segmentation(layout, segments)
Performance Analysis:
def analyze_segmentation_efficiency(layout, start_width=64):
"""
Analyze how well segmentation captures sparsity
"""
segments = sparse_utils.sdd_segment(layout, start_width)
total_active = (layout == 1).sum().item()
covered = 0
compute_cost = 0
print("Segmentation Analysis:")
print(f" Total active blocks: {total_active}")
for block_size, indices in segments:
num_blocks = indices.size(0)
blocks_covered = num_blocks * block_size * block_size
covered += blocks_covered
compute_cost += num_blocks * (block_size ** 3) # Matmul cost
print(f" {block_size}×{block_size} blocks: {num_blocks}")
print(f" Covers: {blocks_covered} unit blocks")
print(f" Compute: {compute_cost:,} FLOPs")
efficiency = covered / total_active if total_active > 0 else 0
print(f"\nCoverage efficiency: {efficiency:.2%}")
print(f"Total compute cost: {compute_cost:,} FLOPs")
return efficiency, compute_cost
layout = create_strided_pattern(8, 64, stride=4)
eff, cost = analyze_segmentation_efficiency(layout)
Integration with Sparse Attention:
class SparseAttention(torch.nn.Module):
def __init__(self, num_heads, seq_length, block_size=64):
super().__init__()
self.num_heads = num_heads
self.seq_length = seq_length
self.block_size = block_size
self.seq_blocks = seq_length // block_size
# Define sparsity pattern
self.register_buffer('layout',
self.create_pattern(num_heads, self.seq_blocks))
# Pre-compute segmentation
self.segments = sparse_utils.sdd_segment(
self.layout, start_width=block_size)
def create_pattern(self, heads, blocks):
# Override to define custom pattern
layout = torch.zeros(heads, blocks, blocks, dtype=torch.int32)
# Local + strided pattern
for h in range(heads):
for i in range(blocks):
for j in range(max(0, i-2), min(blocks, i+3)):
layout[h, i, j] = 1
for j in range(0, blocks, 4):
layout[h, i, j] = 1
return layout
def forward(self, Q, K, V):
# Q, K, V: [batch, heads, seq, head_dim]
# Reshape into blocks
# ... block reshaping ...
attention_output = torch.zeros_like(Q)
# Dispatch sparse matmuls using segmentation
for block_size, indices in self.segments:
# Efficient block-sparse computation
# attention_output += sparse_block_attn(Q, K, V,
# indices, block_size)
pass
return attention_output
Related Pages
- Random LTD Binding - Token dropping for sequence reduction
- Inference PT Binding - Attention softmax operations
- Custom CUDA Layers - Attention kernel implementations