Zip and Skip Tries
Loading...
Searching...
No Matches
ParallelSkipTrie.cuh
Go to the documentation of this file.
1
12#pragma once
13
14#include <cmath> // for log2
15#include <cstddef> // for size_t
16#include <memory> // for smart pointers
17#include <random> // for random height generation
18#include <vector> // for dynamic arrays
19
20#include <unordered_map>
21
22#include <fstream> // for file operations
23
24#include "BitString.cuh" // for string representation
25#include "SkipTrie.hpp" // for Direction
26
27#include "cuda_utils.cuh"
28#include "msw.cuh"
29
30
45template<typename CHAR_T, unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
46class ParallelSkipTrie : public SkipTrie<CHAR_T, CHAR_SIZE_BITS>
47{
48public:
50
52
61
68
70
81 bool insert(const KEY_T* key) noexcept;
82
94 bool insert(const KEY_T* key, size_t height) noexcept;
95
96protected:
98 size_t m_max_size;
99
102
105
107 mutable size_t m_comparison_size;
108
110 mutable size_t m_max_copied;
111
114
126 EqualOrSuccessor find_equal_or_successor(const KEY_T* key, const bool require_level0) const noexcept;
127
130
146 ResultLCP compare(const KEY_T* key1, const KEY_T* key2, size_t lcp) const noexcept;
147};
148
149template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
151 : ST(), m_max_size(max_size)
152{
153 // Calculate number of words needed to store max_size characters
154 // Use ceiling division (max_size / ALPHA + potential remainder)
156
157 // Allocate device memory for string comparison operations
159
160 // Allocate larger block for more complex parallel operations
162}
163
164template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
166{
167 // Free GPU memory allocated for string comparison
168 device_free(d_a);
169
170 // Free GPU memory allocated for large block operations
171 device_free(d_largeblock);
172}
173
174template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
175auto ParallelSkipTrie<CHAR_T, CHAR_SIZE_BITS>::compare(const KEY_T* key1, const KEY_T* key2, size_t lcp) const noexcept -> ResultLCP
176{
177 // Initialize result with equality and starting LCP value
178 ResultLCP result = { std::strong_ordering::equal, lcp };
179
180 while (true)
181 {
182 // Perform parallel comparison on GPU using the current comparison size
183 // This is the core GPU-accelerated operation that makes ParallelSkipTrie faster
184 auto [comparison, next_lcp] = key1->par_k_compare(*key2, lcp, m_comparison_size, d_a, d_largeblock, m_max_copied);
185
186 // Update the result with comparison outcome and new LCP length
187 result.result = comparison;
188 result.lcp = next_lcp;
189
190 if (comparison == std::strong_ordering::equal)
191 {
192 // If both keys match completely, we're done
193 if (result.lcp == key1->size() && result.lcp == key2->size())
194 {
195 return result;
196 }
197
198 // Keys match so far but are longer - double comparison size for next iteration
199 // This adaptive sizing improves performance by processing more characters at once
200 m_comparison_size *= 2;
201 lcp = result.lcp;
202 }
203 else
204 {
205 // Found a difference between keys, exit the loop
206 break;
207 }
208 }
209
210 // Halve comparison size for future operations, but don't go below minimum
211 // This adapts the comparison granularity for optimal performance
212 m_comparison_size = std::max(KEY_T::MIN_PAR_COMPARE_CHAR_SIZE, m_comparison_size / 2);
213
214 return result;
215}
216
217template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
219{
220 // Call the height-specific insert with a random height
221 // This follows skip list standard practice of randomized height assignment
222 return insert(key, get_random_height());
223}
224
225template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
226bool ParallelSkipTrie<CHAR_T, CHAR_SIZE_BITS>::insert(const KEY_T* key, size_t height) noexcept
227{
228 // Reset the GPU comparison parameters to their initial values
229 // This ensures optimal starting point for parallel comparison operations
230 m_comparison_size = KEY_T::MIN_PAR_COMPARE_CHAR_SIZE;
231 m_max_copied = 0;
232
233 // Delegate to the parent class implementation after initializing GPU parameters
234 return ST::insert(key, height);
235}
236
237template<typename CHAR_T, unsigned CHAR_SIZE_BITS>
239{
240 // Reset GPU comparison parameters to their initial values
241 // This ensures consistent behavior across multiple search operations
242 m_comparison_size = KEY_T::MIN_PAR_COMPARE_CHAR_SIZE;
243 m_max_copied = 0;
244
245 // Delegate to parent class implementation after initializing GPU parameters
246 // The actual comparisons will use the overridden compare() method which uses GPU acceleration
247 return ST::find_equal_or_successor(key, require_level0);
248}
Defines the BitString class for compact character string storage and comparison.
Defines the SkipTrie class, a skip list based data structure optimized for string storage and retriev...
A class to store strings compactly into integers, packing multiple characters into a single word.
Definition BitString.cuh:58
static constexpr unsigned ALPHA
Number of characters that can be packed into a single storage word.
Definition BitString.cuh:63
Implements a GPU-accelerated skip list data structure optimized for efficient string operations.
size_t m_comparison_size
Current size (in characters) used for parallel comparisons, adjusted dynamically.
ResultLCP compare(const KEY_T *key1, const KEY_T *key2, size_t lcp) const noexcept
Compares two keys using GPU-accelerated parallel comparison.
uintmax_t * d_largeblock
Large block of device (GPU) memory for more complex parallel operations.
EqualOrSuccessor find_equal_or_successor(const KEY_T *key, const bool require_level0) const noexcept
Finds the node containing the exact key or its immediate successor, using parallel comparison.
uintmax_t * d_a
Device (GPU) memory for parallel string comparison operations.
size_t m_max_size
Maximum total size of keys that can be stored, used for GPU memory allocation.
ParallelSkipTrie(size_t max_size)
Constructs a new ParallelSkipTrie with allocated GPU memory for parallel operations.
size_t m_max_copied
Tracks the maximum number of characters copied to the GPU during comparison operations.
~ParallelSkipTrie()
Destructor for the ParallelSkipTrie class.
bool insert(const KEY_T *key) noexcept
Inserts a new key into the skip list with a randomly generated height.
Implements a skip list data structure optimized for storing and retrieving BitString keys.
Definition SkipTrie.hpp:54
size_t lcp(const KEY_T *key) const noexcept
Calculates the Longest Common Prefix (LCP) between a given key and its position in the skip list sear...
Definition SkipTrie.hpp:878
size_t height() const noexcept
Returns the current maximum height of the skip list.
Definition SkipTrie.hpp:150
static size_t get_random_height()
Generates a random height for a new node based on a geometric distribution.
Definition SkipTrie.hpp:577
Provides utility functions and classes for CUDA operations.
void device_free(T *d_arr)
Frees memory on the CUDA device.
T * alloc_to_device(size_t size)
Allocates memory on the CUDA device.
uintmax_t * alloc_large_block_to_device(size_t n)
Allocates a large block of device memory for parallel mismatch operations.
Definition msw.cu:256
CUDA-accelerated Most Significant Word finding algorithms.
Helper struct to return a Node pointer, a flag indicating equality, and an LCP value.
Definition SkipTrie.hpp:337
Helper struct to return a comparison result (ordering) and an LCP value.
Definition SkipTrie.hpp:365
std::strong_ordering result
The result of the comparison (std::strong_ordering::less, equal, or greater).
Definition SkipTrie.hpp:367
size_t lcp
The Longest Common Prefix length calculated during the comparison.
Definition SkipTrie.hpp:369