Enable hybrid scan page pruning for page level IO - #23374
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughParquet preprocessing now decodes headers from offset indexes or explicit page spans, tracks optional value metadata, skips decoding pruned pages, and reconstructs string/list offsets through a dedicated GPU path. ChangesParquet preprocessing updates
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Preserve page locations and variable-width offset state needed to safely reconstruct columns from a sparse subset of Parquet data pages.
Refine page topology preprocessing and add pruned-page decoding with hybrid scan coverage.
9df47c8 to
cebbcd5
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
cpp/src/io/parquet/page_hdr.cu (1)
523-561: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
decode_page_header'spageparameter is unused/dead.The function only ever writes to
bs->page, never dereferencespage. Both call sites (decode_using_page_index_fn,decode_from_page_data_fn) rely on a manualpages[page_idx] = bs.page;copy afterward. This is easy to misread as "decodes directly into*page", and a future refactor that drops the manual copy (assuming the function already did it) would silently regress page decoding.♻️ Either write directly to `*page` or drop the unused parameter
-__device__ void decode_page_header(byte_stream_s* bs, - cudf::size_type chunk_idx, - PageInfo* page, - kernel_error::pointer error_code) +__device__ void decode_page_header(byte_stream_s* bs, + cudf::size_type chunk_idx, + kernel_error::pointer error_code) { bs->page.chunk_idx = chunk_idx;(and update both call sites to drop the
&pages[page_idx]argument, keeping their existing manual copy-back.)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cpp/src/io/parquet/page_hdr.cu` around lines 523 - 561, Remove the unused page parameter from decode_page_header and update both decode_using_page_index_fn and decode_from_page_data_fn call sites to stop passing &pages[page_idx]. Preserve the existing manual bs.page-to-pages[page_idx] copy-back behavior.cpp/src/io/parquet/parquet_gpu.hpp (1)
1040-1056: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDoc tag:
pagesis mutated, should be[in,out].
fill_pruned_offsetswrites output offsets intopages(perfill_pruned_offsets_kernel), but is tagged@param[in] pages. Other mutatingPageInfospan params in this file use[in,out](e.g.decode_page_data,compute_page_string_sizes_pass1).📝 Doc tag fix
- * `@param`[in] pages All pages to be processed + * `@param`[in,out] pages All pages to be processed🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cpp/src/io/parquet/parquet_gpu.hpp` around lines 1040 - 1056, Update the Doxygen annotation for the pages parameter of fill_pruned_offsets from [in] to [in,out], reflecting that the function writes output offsets into the PageInfo span. Leave the other parameter documentation unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@cpp/src/io/parquet/page_hdr.cu`:
- Around line 523-561: Remove the unused page parameter from decode_page_header
and update both decode_using_page_index_fn and decode_from_page_data_fn call
sites to stop passing &pages[page_idx]. Preserve the existing manual
bs.page-to-pages[page_idx] copy-back behavior.
In `@cpp/src/io/parquet/parquet_gpu.hpp`:
- Around line 1040-1056: Update the Doxygen annotation for the pages parameter
of fill_pruned_offsets from [in] to [in,out], reflecting that the function
writes output offsets into the PageInfo span. Leave the other parameter
documentation unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 1c8aaf44-8571-4402-bb5d-88977a7a14f7
📒 Files selected for processing (12)
cpp/CMakeLists.txtcpp/src/io/parquet/decode_pruned_pages.cucpp/src/io/parquet/experimental/hybrid_scan_preprocess.cucpp/src/io/parquet/page_hdr.cucpp/src/io/parquet/parquet_gpu.hppcpp/src/io/parquet/reader_impl.cppcpp/src/io/parquet/reader_impl.hppcpp/src/io/parquet/reader_impl_helpers.cppcpp/src/io/parquet/reader_impl_preprocess.cucpp/src/io/parquet/reader_impl_preprocess_utils.cucpp/src/io/parquet/reader_impl_preprocess_utils.cuhcpp/tests/io/experimental/hybrid_scan_test.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
- cpp/src/io/parquet/reader_impl.cpp
- cpp/src/io/parquet/reader_impl.hpp
- cpp/src/io/parquet/reader_impl_helpers.cpp
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
cpp/tests/io/experimental/hybrid_scan_test.cpp (1)
444-546: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider adding a fully-pruned (empty result) scenario.
All three pruning scenarios in this test leave multiple pages of rows surviving; none exercises the case where all pages/rows are pruned (empty filter/payload result). Per coding guidelines, tests should cover empty-input/empty-result edge cases in addition to boundary and multi-page scenarios — worth adding a
validatecall with an unsatisfiable filter to ensurehybrid_scanand the offset-reconstruction path handle a fully-empty result correctly.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cpp/tests/io/experimental/hybrid_scan_test.cpp` around lines 444 - 546, Extend the validate-based scenarios in ConsecutivePrunedPageOffsets with an unsatisfiable filter that prunes every page and produces empty filter and payload tables. Reuse the existing col_ref and validate helper, and provide empty expected_slices to exercise hybrid_scan and nested offset reconstruction for a fully empty result.Source: Coding guidelines
cpp/src/io/parquet/reader_impl_preprocess_utils.cu (1)
443-465: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAvoid computing
d_chunk_page_infofor the accelerated decode paths.
chunk_page_offsets/d_chunk_page_infoare computed unconditionally, butd_chunk_page_infois only consumed by the slowCOLUMN_CHUNKSfallback branch (line ~544-548); theOFFSET_INDEXandPAGE_SPANSpaths never read it. Since this function is the accelerated path this PR is optimizing for hybrid-scan sparse I/O, the extrarmm::device_uvectorallocation andthrust::for_eachare wasted work on every call for those paths.♻️ Proposed fix
- rmm::device_uvector<chunk_page_info> d_chunk_page_info(pass.chunks.size(), stream); - thrust::for_each(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), - iter, - iter + pass.chunks.size(), - [cpi = d_chunk_page_info.begin(), - chunk_page_offsets = chunk_page_offsets.begin(), - unsorted_pages = unsorted_pages.begin()] __device__(size_t i) { - cpi[i].pages = &unsorted_pages[chunk_page_offsets[i]]; - }); + rmm::device_uvector<chunk_page_info> d_chunk_page_info(0, stream); + if constexpr (data_source_type == page_data_source_type::COLUMN_CHUNKS) { + d_chunk_page_info = rmm::device_uvector<chunk_page_info>(pass.chunks.size(), stream); + thrust::for_each(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), + iter, + iter + pass.chunks.size(), + [cpi = d_chunk_page_info.begin(), + chunk_page_offsets = chunk_page_offsets.begin(), + unsorted_pages = unsorted_pages.begin()] __device__(size_t i) { + cpi[i].pages = &unsorted_pages[chunk_page_offsets[i]]; + }); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cpp/src/io/parquet/reader_impl_preprocess_utils.cu` around lines 443 - 465, Move the `chunk_page_offsets` and `d_chunk_page_info` allocation and initialization into the slow `COLUMN_CHUNKS` fallback branch, immediately before its consumption. Keep the `OFFSET_INDEX` and `PAGE_SPANS` paths free of these allocations and the associated `thrust::for_each`, while preserving the existing page-offset setup for `COLUMN_CHUNKS`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@cpp/src/io/parquet/reader_impl_preprocess_utils.cu`:
- Around line 443-465: Move the `chunk_page_offsets` and `d_chunk_page_info`
allocation and initialization into the slow `COLUMN_CHUNKS` fallback branch,
immediately before its consumption. Keep the `OFFSET_INDEX` and `PAGE_SPANS`
paths free of these allocations and the associated `thrust::for_each`, while
preserving the existing page-offset setup for `COLUMN_CHUNKS`.
In `@cpp/tests/io/experimental/hybrid_scan_test.cpp`:
- Around line 444-546: Extend the validate-based scenarios in
ConsecutivePrunedPageOffsets with an unsatisfiable filter that prunes every page
and produces empty filter and payload tables. Reuse the existing col_ref and
validate helper, and provide empty expected_slices to exercise hybrid_scan and
nested offset reconstruction for a fully empty result.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 44db8c07-3531-44f7-b288-d576ae5f6a06
📒 Files selected for processing (12)
cpp/CMakeLists.txtcpp/src/io/parquet/decode_pruned_pages.cucpp/src/io/parquet/experimental/hybrid_scan_preprocess.cucpp/src/io/parquet/page_hdr.cucpp/src/io/parquet/parquet_gpu.hppcpp/src/io/parquet/reader_impl.cppcpp/src/io/parquet/reader_impl.hppcpp/src/io/parquet/reader_impl_helpers.cppcpp/src/io/parquet/reader_impl_preprocess.cucpp/src/io/parquet/reader_impl_preprocess_utils.cucpp/src/io/parquet/reader_impl_preprocess_utils.cuhcpp/tests/io/experimental/hybrid_scan_test.cpp
vuule
left a comment
There was a problem hiding this comment.
Finally done, but not much to show for :D
Co-authored-by: Vukasin Milovanovic <vmilovanovic@nvidia.com>
|
/merge |
Related to #23374 Several advanced parquet features in Hybrid scan reader require only offset index portion of the page index (column index is only used in page stats based pruned and that too only if offset index is also available). This PR relaxes the `has_page_index` computations and checks to specific page index portions we need and want to operate on as well as offering fallbacks instead of throwing in certain APIs. TLDR; this is mostly a refactor and nothing new really is being added or any bugs being fixed. Authors: - Muhammad Haseeb (https://github.com/mhaseeb123) Approvers: - Tom Augspurger (https://github.com/TomAugspurger) - Lawrence Mitchell (https://github.com/wence-) - Tianyu Liu (https://github.com/kingcrimsontianyu) - Vukasin Milovanovic (https://github.com/vuule) - https://github.com/paul-aiyedun URL: #23386
Description
Contributes to #23519
This PR includes bug fixes and supporting features needed to enable page pruning with page-level (sparse) I/O (for payload columns) in hybrid scan, that is upcoming in #23375 and includes end to end tests.
Checklist