Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
121bf9d
Add hybrid scan multifile reader basics
mhaseeb123 May 21, 2026
b763cdb
Minor
mhaseeb123 May 21, 2026
c9bf419
Clean up claude's comments
mhaseeb123 May 21, 2026
795f058
Add gtests
mhaseeb123 May 21, 2026
ec0b59e
Merge branch 'main' into fea/hybrid-scan-multifile-base
mhaseeb123 May 21, 2026
f8b90ea
Apply suggestions from code review
mhaseeb123 May 21, 2026
90aef61
Update cpp/src/io/parquet/experimental/hybrid_scan_multifile.cpp
mhaseeb123 May 21, 2026
8876f57
Apply suggestions from @PointKernel (thanks!)
mhaseeb123 May 21, 2026
a575276
Minor
mhaseeb123 May 21, 2026
c7d7cb6
Minor changes
mhaseeb123 May 21, 2026
467a628
Allow more than 2B rows
mhaseeb123 May 21, 2026
1909146
Minor bug fix
mhaseeb123 May 21, 2026
17fd247
Minor
mhaseeb123 May 21, 2026
0493395
Merge branch 'main' into fea/hybrid-scan-multifile-base
mhaseeb123 May 21, 2026
e0319ab
Merge branch 'main' into fea/hybrid-scan-multifile-base
mhaseeb123 May 28, 2026
bf25506
Merge branch 'main' into fea/hybrid-scan-multifile-base
mhaseeb123 May 29, 2026
e013fda
Add multifile row group filtering with stats and byte ranges
mhaseeb123 May 29, 2026
209a9e2
Merge branch 'main' into fea/hybrid-scan-multifile-row-group-filter-p…
mhaseeb123 Jun 2, 2026
c164897
Revert unneeded changes
mhaseeb123 Jun 2, 2026
7a35f6e
Style fix
mhaseeb123 Jun 2, 2026
8c7b183
Address comments
mhaseeb123 Jun 2, 2026
140e90d
Address review comments
mhaseeb123 Jun 2, 2026
9fcbb0a
Apply suggestions
mhaseeb123 Jun 3, 2026
a35f429
Style
mhaseeb123 Jun 3, 2026
269212c
Merge branch 'main' of https://github.com/rapidsai/cudf into fea/hybr…
mhaseeb123 Jun 4, 2026
0d404b1
Multifile hybrid scan APIs for row mask construction
mhaseeb123 Jun 4, 2026
db305f0
Simplify test
mhaseeb123 Jun 5, 2026
6b9d7af
Merge branch 'main' into fea/hybrid-scan-multifile-row-mask
mhaseeb123 Jun 5, 2026
48319ba
Multifile all column materializers for multifile hybrid scan
mhaseeb123 Jun 5, 2026
f9151ce
Doc updates
mhaseeb123 Jun 5, 2026
350047d
Merge branch 'main' into fea/column-chunk-byte-ranges
mhaseeb123 Jun 8, 2026
6cbf7ea
Merge branch 'main' into fea/column-chunk-byte-ranges
Matt711 Jun 9, 2026
db034d1
Add multifile hybrid scan two-step column materializers
mhaseeb123 Jun 10, 2026
1949b00
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 13, 2026
f5875a1
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 16, 2026
48c2eca
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 22, 2026
13f0da6
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 23, 2026
c641fa4
Style fix
mhaseeb123 Jun 24, 2026
f60af20
Minor
mhaseeb123 Jun 24, 2026
95c073d
Style
mhaseeb123 Jun 24, 2026
4544e87
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 24, 2026
f62f443
Merge branch 'main' into fea/two-step-materialize
mhaseeb123 Jun 26, 2026
27ee85b
Add hybrid scan multifile chunked materializers
mhaseeb123 Jun 26, 2026
4f2d5a6
Merge branch 'main' of https://github.com/rapidsai/cudf into fea/chun…
mhaseeb123 Jun 29, 2026
9735cb3
Consolidate hybrid scan common
mhaseeb123 Jun 29, 2026
9e00142
Minor
mhaseeb123 Jun 29, 2026
9714eb4
Minor refactoring
mhaseeb123 Jun 29, 2026
988c2de
rearrange helper functions
mhaseeb123 Jun 29, 2026
8eb4a06
style fix
mhaseeb123 Jun 29, 2026
838b465
Address comments from coderabbitai
mhaseeb123 Jun 30, 2026
cbe5b6a
Revert some junk changes
mhaseeb123 Jun 30, 2026
d62b3eb
Fix empty row mask behavior
mhaseeb123 Jun 30, 2026
9ffec61
Minor
mhaseeb123 Jun 30, 2026
d6c4ba1
Minor
mhaseeb123 Jun 30, 2026
1d74c51
Minor
mhaseeb123 Jun 30, 2026
1b815f4
Minor
mhaseeb123 Jun 30, 2026
00cf4c3
style
mhaseeb123 Jun 30, 2026
c1d2e19
Merge branch 'main' into fea/chunked-materialization
mhaseeb123 Jun 30, 2026
52aae7f
Doc updates
mhaseeb123 Jun 30, 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
10 changes: 5 additions & 5 deletions cpp/include/cudf/io/experimental/hybrid_scan.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only doc changes

* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -513,7 +513,7 @@ class hybrid_scan_reader {
*
* @param row_group_indices Input row groups indices
* @param column_chunk_data Device spans of column chunk data of payload columns
* @param row_mask Boolean column indicating which rows need to be read. All rows read if empty
* @param row_mask Boolean column indicating which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
Expand Down Expand Up @@ -564,7 +564,7 @@ class hybrid_scan_reader {
* @param pass_read_limit Limit on the memory used for reading and decompressing data. `0` if
* there is no limit
* @param row_group_indices Input row groups indices
* @param row_mask Boolean column indicating which rows need to be read. All rows read if empty
* @param row_mask Boolean column indicating which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param column_chunk_data Device spans of column chunk data of filter columns
* @param options Parquet reader options
Expand Down Expand Up @@ -601,7 +601,7 @@ class hybrid_scan_reader {
* @param pass_read_limit Limit on the memory used for reading and decompressing data. `0` if
* there is no limit
* @param row_group_indices Input row groups indices
* @param row_mask Boolean column indicating which rows need to be read. All rows read if empty
* @param row_mask Boolean column indicating which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param column_chunk_data Device spans of column chunk data of payload columns
* @param options Parquet reader options
Expand All @@ -623,7 +623,7 @@ class hybrid_scan_reader {
* @brief Materializes a chunk of payload columns and applies the corresponding range of input row
* mask to the output table chunk
*
* @param row_mask Boolean column indicating which rows need to be read. All rows read if empty
* @param row_mask Boolean column indicating which rows need to be read
*
* @return Table chunk of materialized filter columns and metadata
*/
Expand Down
154 changes: 137 additions & 17 deletions cpp/include/cudf/io/experimental/hybrid_scan_multifile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ class hybrid_scan_multifile {
* @brief Get all available per-source row group indices from the parquet files
*
* @param options Parquet reader options
* @return Vector of row group indices, one inner vector per source
* @return Vector of vectors of row group indices, one per source
*/
[[nodiscard]] std::vector<std::vector<size_type>> all_row_groups(
parquet_reader_options const& options) const;

/**
* @brief Get the total number of top-level rows in the per-source row groups
*
* @param row_group_indices Input per-source row group indices (one inner vector per source)
* @param row_group_indices Span of vectors of input row group indices, one per source
* @return Total number of top-level rows across all sources
*/
[[nodiscard]] size_type total_rows_in_row_groups(
Expand All @@ -130,9 +130,9 @@ class hybrid_scan_multifile {
* Filters the row groups such that only the row groups that start within the byte range are
* selected. Note that the last selected row group may end beyond the byte range.
*
* @param row_group_indices Input row group indices, one per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @return Filtered per-source row group indices (one inner vector per source)
* @return Vector of vectors of filtered row group indices, one per source
*/
[[nodiscard]] std::vector<std::vector<size_type>> filter_row_groups_with_byte_range(
cudf::host_span<std::vector<size_type> const> row_group_indices,
Expand All @@ -141,10 +141,10 @@ class hybrid_scan_multifile {
/**
* @brief Filter the input row groups using column chunk statistics
*
* @param row_group_indices Input row group indices, one per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @return Filtered row group indices, one per source
* @return Vector of vectors of filtered row group indices, one per source
*/
[[nodiscard]] std::vector<std::vector<size_type>> filter_row_groups_with_stats(
cudf::host_span<std::vector<size_type> const> row_group_indices,
Expand All @@ -158,7 +158,7 @@ class hybrid_scan_multifile {
* @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 row_group_indices Span of vectors of 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
Expand All @@ -171,7 +171,7 @@ class hybrid_scan_multifile {
* @brief Builds a boolean survival column of size equal to the total number of rows in the row
* groups containing all `true` values
*
* @param row_group_indices Input per-source row group indices (one inner vector per source)
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned column's device memory
* @return An all-true boolean (survival) column spanning all selected rows across all sources
Expand All @@ -185,7 +185,7 @@ class hybrid_scan_multifile {
* @brief Builds a boolean column indicating surviving rows using page-level statistics in the
* page index
*
* @param row_group_indices Input per-source row group indices (one inner vector per source)
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned column's device memory
Expand All @@ -206,7 +206,7 @@ class hybrid_scan_multifile {
* map has one source index per byte range and can be used to regroup byte ranges by datasource
* before fetching.
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @return Pair of flattened byte ranges to column chunks of filter columns and their
* corresponding source indices
Expand All @@ -219,7 +219,7 @@ class hybrid_scan_multifile {
* @brief Materializes filter columns and updates the input row mask to only the rows that exist
* in the output table
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param column_chunk_data Flattened device spans of filter column chunk data returned in the
* same order as `filter_column_chunks_byte_ranges`
* @param[in,out] row_mask Mutable boolean column spanning all selected rows across all sources
Expand Down Expand Up @@ -247,7 +247,7 @@ class hybrid_scan_multifile {
* map has one source index per byte range and can be used to regroup byte ranges by datasource
* before fetching.
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @return Pair of flattened byte ranges to column chunks of payload columns and their
* corresponding source indices
Expand All @@ -259,11 +259,11 @@ class hybrid_scan_multifile {
/**
* @brief Materialize payload columns and applies the row mask to the output table
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param column_chunk_data Flattened device spans of payload column chunk data returned in the
* same order as `payload_column_chunks_byte_ranges`
* @param row_mask Boolean column spanning all selected rows across all sources and indicating
* which rows need to be read. All rows read if empty
* which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
Expand All @@ -282,7 +282,7 @@ class hybrid_scan_multifile {
/**
* @brief Get byte ranges of column chunks of all (or selected) columns
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param options Parquet reader options
* @return Pair of flattened byte ranges to column chunks of all (or selected) columns and their
* corresponding source indices
Expand All @@ -294,7 +294,7 @@ class hybrid_scan_multifile {
/**
* @brief Materializes all (or selected) columns and returns the final output table
*
* @param row_group_indices Input row group indices, one inner vector per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param column_chunk_data Flattened device spans of column chunk data returned in the same order
* as `all_column_chunks_byte_ranges`
* @param options Parquet reader options
Expand All @@ -309,6 +309,119 @@ class hybrid_scan_multifile {
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr) const;

/**
* @brief Setup chunking information for filter columns and preprocess the input data pages
*
* @param chunk_read_limit Limit on total number of bytes to be returned per table chunk. `0` if
* there is no limit
* @param pass_read_limit Limit on the memory used for reading and decompressing data. `0` if
* there is no limit
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param row_mask Boolean column spanning all selected rows across all sources and indicating
* which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param column_chunk_data Flattened device spans of filter column chunk data returned in the
* same order as `filter_column_chunks_byte_ranges`
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the device memory for the output table chunks
*/
void setup_chunking_for_filter_columns(
std::size_t chunk_read_limit,
std::size_t pass_read_limit,
cudf::host_span<std::vector<size_type> const> row_group_indices,
cudf::column_view const& row_mask,
use_data_page_mask mask_data_pages,
cudf::host_span<cudf::device_span<uint8_t const> const> column_chunk_data,
parquet_reader_options const& options,
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr) const;

/**
* @brief Materializes a chunk of filter columns and updates the corresponding range of input row
* mask to only the rows that exist in the output table
*
* @param[in,out] row_mask Mutable boolean column spanning all selected rows across all sources
* and indicating surviving rows from page pruning. The row mask size must equal the total
* number of rows in the input row groups, and is empty only when there are no such rows
* (yielding an empty output table)
*
* @return Table chunk of materialized filter columns and metadata
*/
[[nodiscard]] table_with_metadata materialize_filter_columns_chunk(
cudf::mutable_column_view& row_mask) const;

/**
* @brief Setup chunking information for payload columns and preprocess the input data pages
*
* @param chunk_read_limit Limit on total number of bytes to be returned per table chunk. `0` if
* there is no limit
* @param pass_read_limit Limit on the memory used for reading and decompressing data. `0` if
* there is no limit
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param row_mask Boolean column spanning all selected rows across all sources and indicating
* which rows need to be read
* @param mask_data_pages Whether to build and use a data page mask using the row mask
* @param column_chunk_data Flattened device spans of payload column chunk data returned in the
* same order as `payload_column_chunks_byte_ranges`
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the device memory for the output table chunks
*/
void setup_chunking_for_payload_columns(
std::size_t chunk_read_limit,
std::size_t pass_read_limit,
cudf::host_span<std::vector<size_type> const> row_group_indices,
cudf::column_view const& row_mask,
use_data_page_mask mask_data_pages,
cudf::host_span<cudf::device_span<uint8_t const> const> column_chunk_data,
parquet_reader_options const& options,
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr) const;

/**
* @brief Materializes a chunk of payload columns and applies the corresponding range of input row
* mask to the output table chunk
*
* @param row_mask Boolean column spanning all selected rows across all sources and indicating
* which rows need to be read
*
* @return Table chunk of materialized payload columns and metadata
*/
[[nodiscard]] table_with_metadata materialize_payload_columns_chunk(
cudf::column_view const& row_mask) const;

/**
* @brief Setup chunking information for all (or selected) columns and preprocess the input data
* pages
*
* @param chunk_read_limit Limit on total number of bytes to be returned per table chunk. `0` if
* there is no limit
* @param pass_read_limit Limit on the memory used for reading and decompressing data. `0` if
* there is no limit
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param column_chunk_data Flattened device spans of column chunk data returned in the same order
* as `all_column_chunks_byte_ranges`
* @param options Parquet reader options
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the device memory for the output table chunks
*/
void setup_chunking_for_all_columns(
std::size_t chunk_read_limit,
std::size_t pass_read_limit,
cudf::host_span<std::vector<size_type> const> row_group_indices,
cudf::host_span<cudf::device_span<uint8_t const> const> column_chunk_data,
parquet_reader_options const& options,
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr) const;

/**
* @brief Materializes a chunk of all (or selected) columns and returns the output table chunk
*
* @return Table chunk of materialized all (or selected) columns and metadata
*/
[[nodiscard]] table_with_metadata materialize_all_columns_chunk() const;

/**
* @brief Partition row groups into passes such that the amount of GPU memory required to read,
* decompress and decode a pass is bounded by the specified limit
Expand All @@ -320,7 +433,7 @@ class hybrid_scan_multifile {
*
* @throws std::invalid_argument if no row group indices in the input
*
* @param row_group_indices Input row group indices, one per source
* @param row_group_indices Span of vectors of input row group indices, one per source
* @param pass_read_limit Memory limit to read and decompress row group data, `0` if there is
* no limit (single pass)
*
Expand All @@ -330,6 +443,13 @@ class hybrid_scan_multifile {
cudf::host_span<std::vector<size_type> const> row_group_indices,
std::size_t pass_read_limit) const;

/**
* @brief Check if there is any parquet data left to read for the current chunked setup
*
* @return Boolean indicating if there is any data left to read
*/
[[nodiscard]] bool has_next_table_chunk() const;

private:
std::unique_ptr<detail::hybrid_scan_reader_impl> _impl;
};
Expand Down
Loading
Loading