Zip and Skip Tries
Loading...
Searching...
No Matches
msw.cu
Go to the documentation of this file.
1
23#include <bit> // bit_width
24#include <cstddef> // size_t
25#include <cstdint> // uintmax_t
26#include <iostream>
27
28#include <stdio.h>
29
30#include "cuda_utils.cuh"
31
42 // Calculate number of chunks, each of size sqrt(n)
43 size_t num_sqrt = std::sqrt(n - 1) + 1;
44
45 // Each thread processes elements at positions (threadIdx + k*blockDim*gridDim)
46 for (auto i = get_tid(); i < n; i += get_num_threads())
47 {
48 // Store XOR result in p2 - non-zero values indicate mismatches
49 p2[i] = p1[i] != p2[i];
50
51 // If there's a mismatch, mark its chunk in the signature array
52 if (p2[i] != 0)
53 {
54 sig_out[i / num_sqrt] = 1;
55 }
56 }
57}
58
69{
70 // Calculate total number of pairwise comparisons needed
71 size_t n_choose_2 = n * (n - 1) / 2;
72
73 // Distribute comparisons evenly across threads
74 size_t num_computations = (n_choose_2 - 1) / get_num_threads() + 1;
75
76 // Calculate starting comparison index for this thread
77 auto i = get_tid() * num_computations;
78
79 // Convert linear index i to pair (a,b) using inverse of triangular number formula
80 // This maps from a 1D index to a 2D comparison between elements at positions a and b
81 size_t b = (1 + std::sqrt(1 + 8 * i)) / 2; // Row index calculation
82 size_t a = i - b * (b - 1) / 2; // Column index calculation
83
84 // Process this thread's allocated comparisons
85 while (num_computations-- && b < n)
86 {
87 // If the left element is non-zero, eliminate the right element
88 if (p[a]) p[b] = 0;
89
90 // Move to next comparison pair
91 ++a;
92
93 // If we reach the end of a row, move to the next row
94 if (a == b)
95 {
96 a = 0; // Start at the leftmost element
97 ++b; // Move to the next row
98 }
99 }
100}
101
114{
115 // Each thread checks a subset of elements
116 for (auto i = get_tid(); i < n; i += get_num_threads())
117 {
118 // If we find a non-zero element, it must be the leftmost one after elimination
119 if (tree[i] != 0)
120 {
121 *section = i; // Record its index as the result
122 }
123 }
124}
125
141size_t seq_find_mismatch(const uintmax_t * const arr1, const uintmax_t * const arr2, size_t size)
142{
143 for (size_t i = 0; i < size; ++i)
144 {
145 if (arr1[i] != arr2[i])
146 {
147 return i;
148 }
149 }
150
151 return size;
152}
153
178size_t par_find_mismatch(const uintmax_t * const d_a, const uintmax_t * const b, uintmax_t *d_large_block, size_t n)
179{
180 // Copy the second array to device memory using pre-allocated buffer
182
183 // Set up memory pointers within the large block:
184 // - d_section: single value to store result
185 // - d_sqrt: array of size sqrt(n) to track which chunks have mismatches
188 size_t num_sqrt = std::sqrt(n - 1) + 1; // Calculate number of sqrt-sized chunks
189
190 // Initialize the section result to max value (no match found yet)
192
193 // Initialize the sqrt array to zeros (no mismatches found yet)
195
196 // PHASE 1: Find which sqrt(n)-sized chunk has the first mismatch
197 // For each element, compute XOR of the two arrays and mark its chunk in d_sqrt if mismatch
199
200 // Find the first non-zero chunk (chunk with a mismatch) in parallel
202
203 // Extract the index of the first chunk with a mismatch
205
206 // Copy the result back to host memory
208 size_t section = *h_section;
209
210 // If no mismatch found, return n (indicating arrays are identical)
211 if (section == std::numeric_limits<uintmax_t>::max())
212 {
213 delete[] h_section;
214 return n;
215 }
216
217 // Reset the section result for the second phase
219
220 // PHASE 2: Find the exact mismatch position within the identified chunk
221 // Calculate the offset and size of the identified chunk
223 size_t section_end = std::min(n, section_offset + num_sqrt);
226
227 // Find the first non-zero word within the chunk (containing XOR results)
229
230 // Extract the index of the first mismatching word within the chunk
232
233 // Copy the result back to host memory
235 size_t result = *h_section;
236
237 delete[] h_section;
238
239 // Return the global index of the first mismatch (chunk offset + position within chunk)
240 return section_offset + result;
241}
242
257{
258 size_t large_block_size = n + std::sqrt(n - 1) + 2;
259
261}
262
280size_t par_find_mismatch(const uintmax_t * const a, const uintmax_t * const b, size_t n)
281{
282 uintmax_t *d_a = copy_to_device(a, n);
284
285 size_t result = par_find_mismatch(d_a, b, d_large_block, n);
286
287 device_free(d_a);
289
290 return result;
291}
Provides utility functions and classes for CUDA operations.
constexpr size_t get_num_threads()
Gets the total number of threads in the kernel launch (compile-time).
T * memset_within_device(T *d_arr, size_t size, int value)
Sets a region of device memory to a specific byte value.
T * copy_from_device(const T *d_arr, size_t size)
Allocates host memory and copies data from device memory to it.
void device_free(T *d_arr)
Frees memory on the CUDA device.
T * copy_to_device(T *d_arr, const T *arr, size_t size)
Copies data from host memory to existing device memory.
__device__ __forceinline__ size_t get_tid()
Gets the global thread ID within a CUDA kernel launch.
T * alloc_to_device(size_t size)
Allocates memory on the CUDA device.
size_t seq_find_mismatch(const uintmax_t *const arr1, const uintmax_t *const arr2, size_t size)
Sequential implementation of finding the first mismatching word between two arrays.
Definition msw.cu:141
__global__ void par_get_section_diff(uintmax_t *tree, uintmax_t *section, size_t n)
Parallel kernel to identify and record the index of the first non-zero element.
Definition msw.cu:113
__global__ void naive_leftmost_prisoner(uintmax_t *p, size_t n)
Parallel kernel to find the leftmost non-zero element in an array.
Definition msw.cu:68
size_t par_find_mismatch(const uintmax_t *const d_a, const uintmax_t *const b, uintmax_t *d_large_block, size_t n)
GPU-accelerated implementation of finding the first mismatching word with pre-allocated memory.
Definition msw.cu:178
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
__global__ void par_sig_sqrt(const uintmax_t *const p1, uintmax_t *p2, uintmax_t *sig_out, size_t n)
CUDA kernel that implements the first phase of the square root decomposition.
Definition msw.cu:41