Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1cb92fc
Refactor hybrid scan multifile API to enhance bloom filter functionality
qbacpey Jun 11, 2026
815ca02
Enhance hybrid scan multifile API with improved bloom filter handling
qbacpey Jun 14, 2026
51e4c0e
Update comments in hybrid scan multifile filters test for clarity
qbacpey Jun 14, 2026
18e492d
Merge branch 'main' into hybrid/api-split-t1
mhaseeb123 Jun 15, 2026
dbb6284
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Jun 15, 2026
b8baad7
Refactor bloom filter functions in hybrid scan implementation
qbacpey Jun 15, 2026
a750d47
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Jun 22, 2026
2077626
Merge branch 'main' into hybrid/api-split-t1
qbacpey Jun 24, 2026
28177c9
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Jun 25, 2026
aff5c7f
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Jul 24, 2026
25c6be0
Format
qbacpey Jul 24, 2026
3dcdeb5
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Jul 27, 2026
2484b20
Enhance bloom filter validation in hybrid scan implementation
qbacpey Jul 27, 2026
4d4bbc9
Refactor bloom filter parameter types to use std::span
qbacpey Jul 27, 2026
df86dc8
Add tests for parquet bloom filter behavior with absent and mixed pre…
qbacpey Jul 28, 2026
d9c3bed
Style
qbacpey Jul 28, 2026
9f497b9
Merge branch 'main' into hybrid/api-split-t1
qbacpey Jul 28, 2026
99eebce
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Aug 3, 2026
03c9df3
Update bloom filter parameter description and fix comment in hybrid s…
qbacpey Aug 3, 2026
a2ff9e3
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Aug 4, 2026
95388b0
Add dictionary page filtering and update bloom filter documentation
qbacpey Aug 5, 2026
b0567a4
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 5, 2026
969cbac
Enhance Parquet testing with bloom filter alignment and pruning
qbacpey Aug 6, 2026
59219e1
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 6, 2026
c31aa10
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 7, 2026
eae0894
Let `test_parquet` use `read_parquet` only
qbacpey Aug 11, 2026
3ea856c
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Aug 11, 2026
12bd65b
Merge remote-tracking branch 'upstream/main' into hybrid/api-split-t1
qbacpey Aug 17, 2026
cf1fe4e
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 18, 2026
e8ecae7
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 18, 2026
6dc0260
Merge branch 'main' into hybrid/api-split-t1
qbacpey Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions cpp/include/cudf/io/experimental/hybrid_scan_multifile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <rmm/resource_ref.hpp>

#include <memory>
#include <utility>
#include <vector>

namespace cudf::io::parquet::experimental::detail {
Expand Down Expand Up @@ -152,20 +153,37 @@ class hybrid_scan_multifile {
rmm::cuda_stream_view stream) const;

/**
* @brief Get byte ranges of bloom filters and dictionary pages (secondary filters) for row group
* pruning
* @brief Get byte ranges of bloom filters for row group pruning
*
Comment thread
qbacpey marked this conversation as resolved.
Resolved
* @note Device buffers for bloom filter byte ranges must be allocated using a 32 byte
* aligned memory resource
*
* @param row_group_indices Input row group indices, one per source
* @param options Parquet reader options
* @return Pair of vectors of byte ranges of column chunk with bloom filters and dictionary
* pages subject to filter predicate
* @return A pair of (1) a flat vector of byte ranges of column chunk bloom filters subject to the
* filter predicate and (2) a parallel source-index map identifying the source each byte
* range must be fetched from
Comment thread
qbacpey marked this conversation as resolved.
Resolved
*/
[[nodiscard]] std::pair<std::vector<byte_range_info>, std::vector<byte_range_info>>
secondary_filters_byte_ranges(cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options) const;
[[nodiscard]] std::pair<std::vector<byte_range_info>, std::vector<size_type>>
bloom_filters_byte_ranges(cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options) const;

/**
* @brief Filter the row groups using column chunk bloom filters
*
* @note The `bloom_filter_data` device spans must point to 32-byte aligned addresses
*
* @param bloom_filter_data Device spans of bloom filters, one inner vector per source
* @param row_group_indices Input row group indices
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @return Filtered per-source row group indices (one inner vector per source)
Comment thread
qbacpey marked this conversation as resolved.
Resolved
*/
[[nodiscard]] std::vector<std::vector<size_type>> filter_row_groups_with_bloom_filters(
cudf::host_span<std::vector<cudf::device_span<uint8_t const>> const> bloom_filter_data,
cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options,
rmm::cuda_stream_view stream) const;
Comment thread
qbacpey marked this conversation as resolved.
Resolved

private:
std::unique_ptr<detail::hybrid_scan_reader_impl> _impl;
Expand Down
10 changes: 8 additions & 2 deletions cpp/src/io/parquet/experimental/hybrid_scan_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ std::vector<std::vector<cudf::size_type>> aggregate_reader_metadata::filter_row_
return stats_filtered_row_group_indices.value_or(all_row_group_indices(row_group_indices));
}

std::vector<byte_range_info> aggregate_reader_metadata::get_bloom_filter_bytes(
std::pair<std::vector<byte_range_info>, std::vector<cudf::size_type>>
aggregate_reader_metadata::get_bloom_filter_bytes(
Comment thread
qbacpey marked this conversation as resolved.
Resolved
cudf::host_span<std::vector<cudf::size_type> const> row_group_indices,
host_span<data_type const> output_dtypes,
host_span<cudf::size_type const> output_column_schemas,
Expand Down Expand Up @@ -411,6 +412,10 @@ std::vector<byte_range_info> aggregate_reader_metadata::get_bloom_filter_bytes(
std::vector<byte_range_info> bloom_filter_bytes;
bloom_filter_bytes.reserve(num_chunks);

// Parallel map identifying the source each emitted byte range must be fetched from
std::vector<cudf::size_type> chunk_source_map;
chunk_source_map.reserve(num_chunks);
Comment thread
qbacpey marked this conversation as resolved.
Resolved

// Flag to check if we have at least one valid bloom filter offset
auto have_bloom_filters = false;

Expand All @@ -431,6 +436,7 @@ std::vector<byte_range_info> aggregate_reader_metadata::get_bloom_filter_bytes(
// Get bloom filter offsets and sizes
bloom_filter_bytes.emplace_back(col_meta.bloom_filter_offset.value_or(0),
col_meta.bloom_filter_length.value_or(0));
chunk_source_map.emplace_back(static_cast<cudf::size_type>(src_index));

// Set `have_bloom_filters` if `bloom_filter_offset` is valid
if (col_meta.bloom_filter_offset.has_value()) { have_bloom_filters = true; }
Expand All @@ -440,7 +446,7 @@ std::vector<byte_range_info> aggregate_reader_metadata::get_bloom_filter_bytes(

if (not have_bloom_filters) { return {}; }

return bloom_filter_bytes;
return {std::move(bloom_filter_bytes), std::move(chunk_source_map)};
}

std::vector<byte_range_info> aggregate_reader_metadata::get_dictionary_page_bytes(
Expand Down
15 changes: 9 additions & 6 deletions cpp/src/io/parquet/experimental/hybrid_scan_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,16 @@ class aggregate_reader_metadata : public aggregate_reader_metadata_base {
* @param output_column_schemas schema indices of output columns
* @param filter AST expression to filter row groups based on bloom filters
*
* @return Byte ranges of bloom filters, one per column chunk with equality predicate
* @return A pair of (1) byte ranges of bloom filters, one per column chunk with equality
* predicate, and (2) a parallel source-index map identifying the source each byte range
* must be fetched from
Comment thread
qbacpey marked this conversation as resolved.
Resolved
*/
[[nodiscard]] std::vector<cudf::io::text::byte_range_info> get_bloom_filter_bytes(
cudf::host_span<std::vector<size_type> const> row_group_indices,
cudf::host_span<data_type const> output_dtypes,
cudf::host_span<cudf::size_type const> output_column_schemas,
std::reference_wrapper<ast::expression const> filter);
[[nodiscard]] std::pair<std::vector<cudf::io::text::byte_range_info>,
std::vector<cudf::size_type>>
get_bloom_filter_bytes(cudf::host_span<std::vector<size_type> const> row_group_indices,
cudf::host_span<data_type const> output_dtypes,
cudf::host_span<cudf::size_type const> output_column_schemas,
std::reference_wrapper<ast::expression const> filter);

/**
* @brief Get the dictionary page byte ranges, one per column chunk with (in)equality predicate
Expand Down
27 changes: 22 additions & 5 deletions cpp/src/io/parquet/experimental/hybrid_scan_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,14 @@ hybrid_scan_reader_impl::secondary_filters_byte_ranges(
CUDF_EXPECTS(not row_group_indices.empty(), "Empty input row group indices encountered");
auto [expr_conv, output_dtypes] = prepare_filter_and_output_types(options);

auto const bloom_filter_bytes =
_extended_metadata->get_bloom_filter_bytes(row_group_indices,
output_dtypes,
_output_column_schemas,
expr_conv.get_converted_expr().value());
// Single-file combined view: take only the bloom byte ranges (`.first`). The per-range source
// map (`.second`) is unused here because the single-file reader has exactly one source.
Comment thread
qbacpey marked this conversation as resolved.
Resolved
auto const bloom_filter_bytes = _extended_metadata
->get_bloom_filter_bytes(row_group_indices,
output_dtypes,
_output_column_schemas,
expr_conv.get_converted_expr().value())
.first;
auto const dictionary_page_bytes =
_extended_metadata->get_dictionary_page_bytes(row_group_indices,
output_dtypes,
Expand All @@ -297,6 +300,20 @@ hybrid_scan_reader_impl::secondary_filters_byte_ranges(
return {bloom_filter_bytes, dictionary_page_bytes};
}

std::pair<std::vector<byte_range_info>, std::vector<size_type>>
hybrid_scan_reader_impl::bloom_filters_byte_ranges(
cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options)
{
CUDF_EXPECTS(not row_group_indices.empty(), "Empty input row group indices encountered");
auto [expr_conv, output_dtypes] = prepare_filter_and_output_types(options);

return _extended_metadata->get_bloom_filter_bytes(row_group_indices,
output_dtypes,
_output_column_schemas,
expr_conv.get_converted_expr().value());
}

std::vector<std::vector<size_type>>
hybrid_scan_reader_impl::filter_row_groups_with_dictionary_pages(
cudf::host_span<cudf::device_span<uint8_t const> const> dictionary_page_data,
Expand Down
7 changes: 7 additions & 0 deletions cpp/src/io/parquet/experimental/hybrid_scan_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ class hybrid_scan_reader_impl : public parquet::detail::reader_impl {
secondary_filters_byte_ranges(cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options);

/**
* @copydoc cudf::io::experimental::hybrid_scan_multifile::bloom_filters_byte_ranges
*/
[[nodiscard]] std::pair<std::vector<byte_range_info>, std::vector<size_type>>
bloom_filters_byte_ranges(cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options);

/**
* @copydoc cudf::io::experimental::hybrid_scan::filter_row_groups_with_dictionary_pages
*/
Expand Down
35 changes: 32 additions & 3 deletions cpp/src/io/parquet/experimental/hybrid_scan_multifile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <cudf/detail/nvtx/ranges.hpp>
#include <cudf/io/experimental/hybrid_scan_multifile.hpp>

#include <numeric>

namespace cudf::io::parquet::experimental {

hybrid_scan_multifile::hybrid_scan_multifile(
Expand Down Expand Up @@ -74,13 +76,40 @@ std::vector<std::vector<size_type>> hybrid_scan_multifile::filter_row_groups_wit
return _impl->filter_row_groups_with_stats(row_group_indices, options, stream);
}

std::pair<std::vector<text::byte_range_info>, std::vector<text::byte_range_info>>
hybrid_scan_multifile::secondary_filters_byte_ranges(
std::pair<std::vector<text::byte_range_info>, std::vector<size_type>>
hybrid_scan_multifile::bloom_filters_byte_ranges(
cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options) const
{
CUDF_FUNC_RANGE();
return _impl->secondary_filters_byte_ranges(row_group_indices, options);
return _impl->bloom_filters_byte_ranges(row_group_indices, options);
}

std::vector<std::vector<size_type>> hybrid_scan_multifile::filter_row_groups_with_bloom_filters(
cudf::host_span<std::vector<cudf::device_span<uint8_t const>> const> bloom_filter_data,
cudf::host_span<std::vector<size_type> const> row_group_indices,
parquet_reader_options const& options,
rmm::cuda_stream_view stream) const
Comment thread
qbacpey marked this conversation as resolved.
Resolved
{
CUDF_FUNC_RANGE();

// Concatenate the per-source spans in source order
auto const num_chunks =
std::accumulate(bloom_filter_data.begin(),
bloom_filter_data.end(),
std::size_t{0},
[](auto sum, auto const& source_data) { return sum + source_data.size(); });

std::vector<cudf::device_span<uint8_t const>> flattened_bloom_filter_data;
flattened_bloom_filter_data.reserve(num_chunks);
for (auto const& source_bloom_filter_data : bloom_filter_data) {
flattened_bloom_filter_data.insert(flattened_bloom_filter_data.end(),
source_bloom_filter_data.begin(),
source_bloom_filter_data.end());
}

return _impl->filter_row_groups_with_bloom_filters(
flattened_bloom_filter_data, row_group_indices, options, stream);
}

} // namespace cudf::io::parquet::experimental
Loading
Loading