-
Notifications
You must be signed in to change notification settings - Fork 2
Reordering Algorithms
GraphBrew implements 21 different vertex reordering algorithms, each with unique characteristics suited for different graph topologies. This page explains each algorithm in detail.
Graph algorithms spend significant time accessing memory. When vertices are ordered randomly, memory access patterns are unpredictable, causing cache misses. Reordering places frequently co-accessed vertices together in memory, dramatically improving cache utilization.
Before Reordering: After Reordering:
Vertex 1 → 5, 99, 2000 Vertex 1 → 2, 3, 4
Vertex 2 → 8, 1500, 3 Vertex 2 → 1, 3, 5
(scattered neighbors) (nearby neighbors)
| Category | Algorithms | Best For |
|---|---|---|
| Basic | ORIGINAL, RANDOM, SORT | Baseline comparisons |
| Hub-Based | HUBSORT, HUBCLUSTER | Power-law graphs |
| DBG-Based | DBG, HUBSORTDBG, HUBCLUSTERDBG | Cache locality |
| Community | RABBITORDER, GORDER, CORDER | Modular graphs |
| Leiden-Based | LeidenOrder, LeidenHybrid, etc. | Strong community structure |
| Hybrid | GraphBrewOrder, AdaptiveOrder | Adaptive selection |
Keep original vertex ordering
./bench/bin/pr -f graph.el -s -o 0 -n 3- Description: Uses vertices in their original order from the input file
- Complexity: O(1) - no reordering
- Best for: Baseline comparison, already well-ordered graphs
- When to use: Always run this first to establish baseline performance
Random vertex permutation
./bench/bin/pr -f graph.el -s -o 1 -n 3- Description: Randomly shuffles all vertices
- Complexity: O(n) where n = number of vertices
- Best for: Testing, worst-case scenarios
- When to use: Debugging, establishing worst-case baseline
Sort vertices by ID
./bench/bin/pr -f graph.el -s -o 2 -n 3- Description: Sorts vertices in ascending order by original ID
- Complexity: O(n log n)
- Best for: Graphs where IDs have locality meaning
- When to use: When input has meaningful vertex numbering
These algorithms prioritize high-degree vertices (hubs) which are accessed frequently.
Sort by degree (hubs first)
./bench/bin/pr -f graph.el -s -o 3 -n 3- Description: Places high-degree vertices (hubs) at the beginning
- Complexity: O(n log n)
- Rationale: Hubs are accessed most frequently; placing them together improves cache reuse
- Best for: Power-law graphs (social networks, web graphs)
How it works:
Original: v1(deg=5), v2(deg=100), v3(deg=2), v4(deg=50)
After: v2(deg=100), v4(deg=50), v1(deg=5), v3(deg=2)
Cluster hubs with their neighbors
./bench/bin/pr -f graph.el -s -o 4 -n 3- Description: Places each hub followed by its neighbors
- Complexity: O(n + m) where m = number of edges
- Rationale: When accessing a hub, its neighbors are likely accessed next
- Best for: Graphs with hub-and-spoke patterns
How it works:
Hub v2 has neighbors: v1, v5, v8
Ordering: v2, v1, v5, v8, [next hub], ...
Degree-Based Grouping (DBG) creates "frequency zones" based on access patterns.
Degree-Based Grouping
./bench/bin/pr -f graph.el -s -o 5 -n 3- Description: Groups vertices by degree into logarithmic buckets
- Complexity: O(n)
- Rationale: Vertices with similar degrees have similar access frequencies
- Best for: General-purpose, works well on most graphs
Bucket structure:
Bucket 0: degree 1
Bucket 1: degree 2-3
Bucket 2: degree 4-7
Bucket 3: degree 8-15
...
HUBSORT within DBG buckets
./bench/bin/pr -f graph.el -s -o 6 -n 3- Description: First groups by DBG, then sorts each bucket by degree
- Complexity: O(n log n)
- Best for: Combines benefits of both approaches
HUBCLUSTER within DBG buckets
./bench/bin/pr -f graph.el -s -o 7 -n 3- Description: First groups by DBG, then clusters hubs with neighbors in each bucket
- Complexity: O(n + m)
- Best for: Power-law graphs with clear hub structure
These algorithms detect communities (densely connected subgraphs) and reorder to keep community members together.
Rabbit Order (community + incremental aggregation)
RABBIT_ENABLE=1 make pr
./bench/bin/pr -f graph.el -s -o 8 -n 3- Description: Hierarchical community detection with incremental aggregation
- Complexity: O(n log n) average
-
Requires: Build with
RABBIT_ENABLE=1 - Best for: Large graphs with hierarchical community structure
Key insight: Uses a "rabbit" metaphor where vertices "hop" to form communities.
Graph Ordering (dynamic programming + BFS)
./bench/bin/pr -f graph.el -s -o 9 -n 3- Description: Uses dynamic programming with sliding window optimization
- Complexity: O(n × w) where w = window size
- Best for: Graphs where local structure matters
Window optimization:
Window size determines how far ahead to look when placing vertices
Larger window = better quality, slower computation
Cache-aware Ordering
./bench/bin/pr -f graph.el -s -o 10 -n 3- Description: Explicitly optimizes for CPU cache hierarchy
- Complexity: O(n + m)
- Best for: Cache-sensitive applications
Reverse Cuthill-McKee
./bench/bin/pr -f graph.el -s -o 11 -n 3- Description: Classic bandwidth-reduction algorithm (BFS-based)
- Complexity: O(n + m)
- Best for: Sparse matrices, scientific computing graphs
- Note: Originally designed for sparse matrix solvers
How it works:
- Start from a peripheral vertex (far from center)
- BFS traversal, ordering by increasing degree
- Reverse the final ordering
Leiden community detection
./bench/bin/pr -f graph.el -s -o 12 -n 3- Description: State-of-the-art community detection algorithm
- Complexity: O(n log n) average
- Best for: Graphs with strong community structure
Key features:
- Improves on Louvain algorithm
- Guarantees well-connected communities
- Produces high-quality modularity scores
Per-community reordering
# Format: -o 13:<frequency>:<intra_algo>:<resolution>
./bench/bin/pr -f graph.el -s -o 13:10:17 -n 3- Description: Runs Leiden, then applies a different algorithm within each community
-
Parameters:
-
frequency: Hub frequency threshold (default: 10) -
intra_algo: Algorithm to use within communities (e.g., 17 = LeidenDFSHub) -
resolution: Leiden resolution parameter (default: 0.75)
-
- Best for: Fine-grained control over per-community ordering
Load mapping from file
./bench/bin/pr -f graph.el -s -o 14:mapping.lo -n 3- Description: Loads a pre-computed vertex ordering from file
-
File formats:
.lo(list order) or.so(source order) - Best for: Using externally computed orderings
Perceptron-based algorithm selection
./bench/bin/pr -f graph.el -s -o 15 -n 3- Description: Uses ML to select the best algorithm for each community
- Complexity: O(n log n) + perceptron inference
- Best for: Unknown graphs, automated pipelines
How it works:
- Run Leiden to detect communities
- Compute features for each community (size, density, hub concentration)
- Use trained perceptron to select best algorithm per community
- Apply selected algorithm to each community
See: AdaptiveOrder-ML for details on the ML model.
These algorithms use Leiden community detection combined with different dendrogram traversal strategies.
Leiden produces a hierarchical tree of communities:
Root
/ \
Comm1 Comm2
/ \ |
C1a C1b C2a
Different traversal orders produce different vertex orderings.
Depth-First Search traversal
./bench/bin/pr -f graph.el -s -o 16 -n 3- Description: Standard DFS traversal of community hierarchy
- Order: Goes deep into one branch before exploring siblings
- Best for: General hierarchical structure
DFS prioritizing hub communities
./bench/bin/pr -f graph.el -s -o 17 -n 3- Description: DFS that visits high-degree communities first
- Rationale: Hub communities are accessed more frequently
- Best for: Power-law graphs
DFS prioritizing larger communities
./bench/bin/pr -f graph.el -s -o 18 -n 3- Description: DFS that visits larger communities first
- Rationale: Larger communities contain more vertices to process
- Best for: Graphs with uneven community sizes
Breadth-First Search traversal
./bench/bin/pr -f graph.el -s -o 19 -n 3- Description: Level-order traversal of community hierarchy
- Order: Processes all communities at one level before going deeper
- Best for: Wide, shallow community hierarchies
Hybrid hub-aware DFS
./bench/bin/pr -f graph.el -s -o 20 -n 3- Description: Combines hub prioritization with adaptive traversal
- Best for: Most graphs - good default choice
Why it's often best:
- Balances hub frequency with community structure
- Adapts traversal based on community characteristics
- Robust across different graph types
| Graph Type | Recommended | Alternatives |
|---|---|---|
| Social Networks | LeidenHybrid (20) | LeidenDFSHub (17), AdaptiveOrder (15) |
| Web Graphs | LeidenHybrid (20) | HUBCLUSTERDBG (7) |
| Road Networks | ORIGINAL (0), RCM (11) | GORDER (9) |
| Citation Networks | LeidenOrder (12) | RABBITORDER (8) |
| Unknown | AdaptiveOrder (15) | LeidenHybrid (20) |
| Size | Nodes | Recommended |
|---|---|---|
| Small | < 100K | Any (try several) |
| Medium | 100K - 1M | LeidenHybrid (20) |
| Large | 1M - 100M | LeidenHybrid (20), AdaptiveOrder (15) |
| Very Large | > 100M | HUBCLUSTERDBG (7), LeidenOrder (12) |
Is your graph modular (has communities)?
├── Yes → Is it very large (>10M vertices)?
│ ├── Yes → LeidenOrder (12)
│ └── No → LeidenHybrid (20)
└── No/Unknown → Is it a power-law graph?
├── Yes → HUBCLUSTERDBG (7)
└── No → Try AdaptiveOrder (15)
Running PageRank on a social network (1M vertices, 10M edges):
| Algorithm | Time | Speedup |
|---|---|---|
| ORIGINAL (0) | 1.00s | 1.00x |
| RANDOM (1) | 1.45s | 0.69x |
| HUBSORT (3) | 0.85s | 1.18x |
| DBG (5) | 0.80s | 1.25x |
| HUBCLUSTERDBG (7) | 0.72s | 1.39x |
| LeidenOrder (12) | 0.65s | 1.54x |
| LeidenHybrid (20) | 0.58s | 1.72x |
- Running-Benchmarks - How to run experiments
- AdaptiveOrder-ML - Deep dive into ML-based selection
- Adding-New-Algorithms - Implement your own algorithm