cuDDL
Loading...
Searching...
No Matches
batch.cuh
Go to the documentation of this file.
1#pragma once
2
3#include <cuda_runtime.h>
4#include <cuda/stream>
5
6#include <algorithm>
7#include <cstddef>
8#include <cstdint>
9
11#include <cuddl/device_span.cuh>
12#include <cuddl/error.hpp>
14
25namespace cuddl {
26
34template <size_t BucketCount>
39 cuda::stream_ref stream
40) {
41 static_assert(BucketCount >= (size_t{1} << 11) && BucketCount <= (size_t{1} << 13));
42 static_assert((BucketCount & (BucketCount - 1U)) == 0U);
43
44 if (left_rows.size() != right_rows.size()) {
45 return Err(Error::invalid_argument("batch register spans must have equal sizes"));
46 }
47 if (left_rows.size() % BucketCount != 0U) {
48 return Err(Error::invalid_argument("batch register spans must contain whole rows"));
49 }
50 auto const pair_count = left_rows.size() / BucketCount;
51 if (outputs.size() < pair_count) {
52 return Err(Error::invalid_argument("batch output span is too small"));
53 }
54 if (pair_count != 0U && (left_rows.data() == nullptr || right_rows.data() == nullptr ||
55 outputs.data() == nullptr)) {
56 return Err(Error::invalid_argument("nonempty batch buffers must not be null"));
57 }
58 if (pair_count == 0U) {
59 return Ok();
60 }
61
62 constexpr size_t warps_per_block = detail::block_size / 32U;
63 constexpr size_t maximum_blocks = 65535U;
64 auto const blocks =
65 std::min((pair_count + warps_per_block - 1U) / warps_per_block, maximum_blocks);
66 detail::batch_summary_kernel<BucketCount>
67 <<<static_cast<uint32_t>(blocks), detail::block_size, 0, stream.get()>>>(
68 left_rows.data(), right_rows.data(), pair_count, outputs.data()
69 );
70 return cuda_try(cudaGetLastError());
71}
72
79template <size_t BucketCount, typename Layout = default_register_layout>
82 device_span<uint64_t> empty_out,
83 device_span<double> estimates_out,
84 cuda::stream_ref stream
85) {
86 static_assert(BucketCount >= (size_t{1} << 11) && BucketCount <= (size_t{1} << 13));
87 static_assert((BucketCount & (BucketCount - 1U)) == 0U);
88
89 if (sketches.size() % BucketCount != 0U) {
90 return Err(Error::invalid_argument("sketch store must contain whole sketches"));
91 }
92 auto const row_count = sketches.size() / BucketCount;
93 if (empty_out.size() < row_count || estimates_out.size() < row_count) {
94 return Err(Error::invalid_argument("sketch store outputs are too small"));
95 }
96 if (row_count == 0U) {
97 return Ok();
98 }
99 if (sketches.data() == nullptr || empty_out.data() == nullptr ||
100 estimates_out.data() == nullptr) {
101 return Err(Error::invalid_argument("nonempty sketch store buffers must not be null"));
102 }
103 if (row_count > detail::maximum_batch_rows) {
104 return Err(Error::invalid_argument("sketch store has too many rows for one launch"));
105 }
106
107 detail::batch_cardinality_kernel<BucketCount, Layout>
108 <<<static_cast<uint32_t>(row_count), detail::block_size, 0, stream.get()>>>(
109 sketches.data(),
110 static_cast<uint32_t>(row_count),
111 empty_out.data(),
112 estimates_out.data()
113 );
114 return cuda_try(cudaGetLastError());
115}
116
122template <size_t BucketCount>
125 device_span<uint16_t> scores_out,
126 cuda::stream_ref stream
127) {
128 static_assert(BucketCount >= (size_t{1} << 11) && BucketCount <= (size_t{1} << 13));
129 static_assert((BucketCount & (BucketCount - 1U)) == 0U);
130
131 if (sketches.size() % BucketCount != 0U) {
132 return Err(Error::invalid_argument("sketch store must contain whole sketches"));
133 }
134 auto const row_count = sketches.size() / BucketCount;
135 if (scores_out.size() < row_count * BucketCount) {
136 return Err(Error::invalid_argument("sketch store outputs are too small"));
137 }
138 if (row_count == 0U) {
139 return Ok();
140 }
141 if (sketches.data() == nullptr || scores_out.data() == nullptr) {
142 return Err(Error::invalid_argument("nonempty sketch store buffers must not be null"));
143 }
144 if (row_count > detail::maximum_batch_rows) {
145 return Err(Error::invalid_argument("sketch store has too many rows for one launch"));
146 }
147
148 detail::batch_scores_kernel<BucketCount>
149 <<<static_cast<uint32_t>(row_count), detail::block_size, 0, stream.get()>>>(
150 sketches.data(), static_cast<uint32_t>(row_count), scores_out.data()
151 );
152 return cuda_try(cudaGetLastError());
153}
154
155} // namespace cuddl
constexpr uint32_t block_size
Threads per CTA for the single-pair and cardinality reduction kernels.
Definition kernels.cuh:28
constexpr size_t maximum_batch_rows
Stored sketches one batch launch may index, bounded by the CUDA grid dimension.
Definition kernels.cuh:31
Batch operations over contiguous device rows.
Definition a48.hpp:14
Result< void > Ok() noexcept
Success return for Result<void>; same as return {}.
Definition error.hpp:181
Result< void > compare_batch_async(device_span< uint32_t const > left_rows, device_span< uint32_t const > right_rows, device_span< pairwise_summary > outputs, cuda::stream_ref stream)
Compares corresponding rows from two contiguous register batches.
Definition batch.cuh:35
Result< void > extract_scores_batch_async(device_span< uint32_t const > sketches, device_span< uint16_t > scores_out, cuda::stream_ref stream)
Copies the winning score of every register into compact row-major scores.
Definition batch.cuh:123
Result< void > cardinality_batch_async(device_span< uint32_t const > sketches, device_span< uint64_t > empty_out, device_span< double > estimates_out, cuda::stream_ref stream)
Computes the cardinality of every stored sketch.
Definition batch.cuh:80
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:176
Result< void > cuda_try(cudaError_t error, std::source_location location=std::source_location::current())
Checks a CUDA runtime call and returns an error on failure.
Definition error.hpp:187
static Error invalid_argument(std::string message)
Definition error.hpp:99
Fallible API result: cuda::std::expected<T, Error> with cuDDL factories.
Definition error.hpp:118
A span that is assumed to point to device-accessible memory.