You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Next up: Implement and benchmark your first scalar bitmap scan
86
+
## Next up: implement and benchmark your first scalar bitmap scan
87
87
88
88
With your bit vector infrastructure in place, you're now ready to scan it for set bits—the core operation that underpins all bitmap-based filters in database systems.
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/bitmap_scan_sve2/03-scalar-implementations.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -76,7 +76,7 @@ size_t result_count = 0;
76
76
```
77
77
Instead of iterating through each bit individually, this implementation processes one byte (8 bits) at a time. The main optimization over the previous scalar implementation is checking if an entire byte is zero and skipping it entirely. For sparse bitmaps, this can dramatically reduce the number of bit checks.
78
78
79
-
## Next up: Accelerate bitmap scanning with NEON and SVE
79
+
## Next up: accelerate bitmap scanning with NEON and SVE
80
80
81
81
You’ve now implemented two scalar scanning routines:
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/bitmap_scan_sve2/04-vector-implementations.md
+10-5Lines changed: 10 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,9 +10,12 @@ layout: "learningpathall"
10
10
---
11
11
Modern Arm CPUs like Neoverse V2 support SIMD (Single Instruction, Multiple Data) extensions that allow processing multiple bytes in parallel. In this section, you'll explore how NEON and SVE vector instructions can dramatically accelerate bitmap scanning by skipping over large regions of unset data and reducing per-bit processing overhead.
12
12
13
-
## NEON Implementation
13
+
## NEON implementation
14
+
15
+
This implementation uses NEON SIMD (Single Instruction, Multiple Data) instructions to process 16 bytes (128 bits) at a time, significantly accelerating the scanning process.
16
+
17
+
Copy the NEON implementation shown below into the same file:
14
18
15
-
This implementation uses NEON SIMD (Single Instruction, Multiple Data) instructions to process 16 bytes (128 bits) at a time, significantly accelerating the scanning process. Copy the NEON implementation shown below into the same file:
This NEON implementation processes 16 bytes at a time with vector instructions. For sparse bitmaps, entire 16-byte chunks can be skipped at once, providing a significant speedup over byte-level skipping. After vector processing, it falls back to scalar code for any remaining bytes that don't fill a complete 16-byte chunk.
85
88
86
-
## SVE Implementation
89
+
## SVE implementation
90
+
91
+
This implementation uses SVE instructions which are available in the Arm Neoverse V2 based AWS Graviton 4 processor.
87
92
88
-
This implementation uses SVE instructions which are available in the Arm Neoverse V2 based AWS Graviton 4 processor. Copy this SVE implementation into the same file:
93
+
Copy this SVE implementation into the same file:
89
94
90
95
```c
91
96
// SVE implementation using svcmp_u8, PNEXT, and LASTB
The SVE implementation efficiently scans bitmaps by using `svcmpne_u8` to identify non-zero bytes and `svpnext_b8` to iterate through them sequentially. It extracts byte indices and values with `svlastb_u8`, then processes individual bits using scalar code. This hybrid vector-scalar approach maintains great performance across various bitmap densities. On Graviton4, SVE vectors are 128 bits (16 bytes), allowing processing of 16 bytes at once.
154
159
155
-
## Next up: Apply vectorized scanning to database workloads
160
+
## Next up: apply vectorized scanning to database workloads
156
161
157
162
With both NEON and SVE implementations in place, you’ve now unlocked the full power of Arm’s vector processing capabilities for bitmap scanning. These SIMD techniques allow you to process large bitvectors more efficiently—especially when filtering sparse datasets or skipping over large blocks of empty rows.
The main function of your program is responsible for setting up the test environment, running the benchmarking code for the four different implementations across various bit densities, and reporting the results. In the context of bitmap scanning, bit density refers to the percentage or proportion of bits that are set (have a value of 1) in the bitmap. Copy the main function code below into `bitvector_scan_benchmark.c`:
43
+
The main function of your program is responsible for setting up the test environment, running the benchmarking code for the four different implementations across various bit densities, and reporting the results. In the context of bitmap scanning, bit density refers to the percentage or proportion of bits that are set (have a value of 1) in the bitmap.
44
+
45
+
Copy the main function code below into `bitvector_scan_benchmark.c`:
44
46
45
47
```C
46
48
int main() {
@@ -148,7 +150,7 @@ When running on a Graviton4 c8g.large instance with Ubuntu 24.04, the results sh
@@ -160,23 +162,25 @@ When running on a Graviton4 c8g.large instance with Ubuntu 24.04, the results sh
160
162
161
163
## Understanding the results
162
164
163
-
## Generic Scalar vs Optimized Scalar
165
+
The benchmarking results reveal how different bitmap scanning implementations perform across a range of bit densities—from completely empty vectors to those with millions of set bits. Understanding these trends is key to selecting the most effective approach for your specific use case.
166
+
167
+
### Generic scalar vs optimized scalar
164
168
165
169
The optimized scalar implementation shows significant improvements over the generic scalar implementation due to:
***Reduced Function Calls**: Accessing bits directly rather than through function calls
169
173
***Better Cache Utilization**: More sequential memory access patterns
170
174
171
-
## Optimized Scalar vs NEON
175
+
###Optimized scalar vs NEON
172
176
173
177
The NEON implementation shows further improvements over the optimized scalar implementation for sparse bit vectors due to:
174
178
175
179
***Chunk-level Skipping**: Quickly skipping 16 empty bytes at once
176
180
***Vectorized Comparison**: Checking multiple bytes in parallel
177
181
***Early Termination**: Quickly determining if a chunk contains any set bits
178
182
179
-
## NEON vs SVE
183
+
###NEON vs SVE
180
184
181
185
The performance comparison between NEON and SVE depends on the bit density:
182
186
@@ -190,7 +194,7 @@ The performance comparison between NEON and SVE depends on the bit density:
190
194
- SVE consistently outperforms NEON
191
195
- SVE achieves up to 1.66x speedup over NEON at 0.01% density
192
196
193
-
## Key Optimizations in SVE Implementation
197
+
###Key optimizations in SVE implementation
194
198
195
199
The SVE implementation includes several key optimizations:
196
200
@@ -204,7 +208,7 @@ The SVE implementation includes several key optimizations:
204
208
205
209
***Prefetching**: Using `__builtin_prefetch` to reduce memory latency by prefetching the next chunk of data.
206
210
207
-
## Next up: Apply what you’ve learned to real-world workloads
211
+
## Next up: apply what you’ve learned to real-world workloads
208
212
209
213
Now that you’ve benchmarked all four bitmap scanning implementations—scalar (generic and optimized), NEON, and SVE—you have a data-driven understanding of how vectorization impacts performance across different bitmap densities.
0 commit comments