Skip to content

Add Arrow fixed-size-list ingress - #23583

Open
0guban0v wants to merge 5 commits into
NVIDIA:mainfrom
0guban0v:fixed-size-list-arrow-ingress
Open

Add Arrow fixed-size-list ingress#23583
0guban0v wants to merge 5 commits into
NVIDIA:mainfrom
0guban0v:fixed-size-list-arrow-ingress

Conversation

@0guban0v

@0guban0v 0guban0v commented Aug 7, 2026

Copy link
Copy Markdown

Closes #23545

Validation on RTX A6000, CUDA 13.3:

  • 10/10 focused fixed-size-list tests passed
  • complete INTEROP_TEST passed

@0guban0v
0guban0v requested review from a team as code owners August 7, 2026 15:34
@copy-pr-bot

copy-pr-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. Python Affects Python cuDF API. pylibcudf Issues specific to the pylibcudf package labels Aug 7, 2026
@GPUtester GPUtester moved this to In Progress in cuDF Python Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added Arrow interoperability for fixed-size list arrays across host, device, stream, and Python table conversions.
    • Fixed-size lists are converted to regular list columns while preserving values, nesting, nulls, slicing, empty inputs, and zero-width lists.
  • Bug Fixes

    • Added validation for invalid widths, offsets, child ranges, and overflow conditions.
    • Unsupported fixed-size-list schemas in device-array ownership construction now return a clear data type error.

Walkthrough

The Arrow interop layer detects fixed-size-list schemas, converts them to cuDF LIST columns by synthesizing offsets, validates bounds, preserves slices, and rejects unsupported owning device wrappers. C++, stream, and Python tests cover these paths.

Changes

Fixed-size-list Arrow interoperability

Layer / File(s) Summary
Schema and layout validation
cpp/src/interop/arrow_data_structures.cpp, cpp/src/interop/arrow_utilities.*, cpp/tests/interop/arrow_data_structures_test.cpp
Adds recursive schema detection, width and layout validation, LIST mapping, and rejection of fixed-size lists in owning device wrappers.
Host and device conversion
cpp/src/interop/from_arrow_host.*, cpp/src/interop/from_arrow_device.cu, cpp/tests/interop/from_arrow_host_test.cpp, cpp/tests/interop/from_arrow_device_test.cpp
Synthesizes normalized int32 offsets, validates child ranges, preserves slices, and covers null, empty, zero-width, large, and invalid inputs.
Stream and Python integration
cpp/tests/interop/from_arrow_stream_test.cpp, python/pylibcudf/tests/test_table.py
Tests stream concatenation, nulls, slices, boundary-sized chunks, and normalization in column and mixed-type table imports.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: ⚪ Minimal · up to b2fe7

The PR adds fixed-size-list Arrow ingress with focused and interoperability validation; remaining items are limited to optional test coverage, allocator consistency, and test-helper cleanup, with no actionable merge-blocking risk at the current head.

Possibly related PRs

  • NVIDIA/cudf#23607: Establishes offset-type separation used by synthesized fixed-size-list offsets.

Suggested reviewers: mythrocks, qbacpey, galipremsagar

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: Arrow fixed-size-list ingress support.
Description check ✅ Passed The description directly relates to fixed-size-list ingress and reports validation results for the linked issue.
Linked Issues check ✅ Passed The changes implement ingress mapping from Arrow FixedSizeList to cudf LIST, with validation and comprehensive tests, satisfying issue #23545.
Out of Scope Changes check ✅ Passed The implementation and tests remain focused on Arrow fixed-size-list ingress; no unrelated or egress changes are evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cpp/src/interop/from_arrow_host.cu (1)

608-717: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Add boundary and multi-block fixed-size-list cases.

The tests cover empty, null, and sliced input. They do not cover boundary or multi-block row counts. Add fixed-size-list cases that cross the relevant execution-size boundary.

As per coding guidelines, “Tests must cover empty inputs, nulls, sliced columns, boundary and multi-block sizes.”

🤖 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/interop/from_arrow_host.cu` around lines 608 - 717, Add
fixed-size-list test cases covering row counts at the relevant execution-size
boundary and counts large enough to span multiple blocks. Extend the existing
tests for empty, null, and sliced inputs, using the from_arrow_column conversion
path and validating both conversion success and resulting values.

Source: Coding guidelines

🤖 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.

Inline comments:
In `@cpp/src/interop/from_arrow_host.cu`:
- Around line 297-317: Update get_fixed_size_list_offsets to validate
input->offset and input->length are non-negative before arithmetic, handle width
== 0 explicitly, and verify input->length + 1 fits cudf::size_type. Check each
multiplication for int64_t overflow before computing offset and length, then
retain the existing child-element limit validation and only cast after all
bounds checks pass.

In `@cpp/tests/interop/from_arrow_device_test.cpp`:
- Around line 310-388: Expand the fixed-size-list coverage in
FixedSizeListColumn and FixedSizeListColumnSliced in
cpp/tests/interop/from_arrow_device_test.cpp:310-388 to include empty inputs,
nullable list rows, boundary sizes, and multi-block sizes while preserving
existing full and sliced cases. Extend the corresponding fixed-size-list tests
in cpp/tests/interop/from_arrow_host_test.cpp:608-717 with boundary-size and
multi-block-size cases; no empty or nullable cases are requested there.

In `@cpp/tests/interop/from_arrow_host_test.cpp`:
- Around line 608-717: Extend the fixed-size-list tests around
FixedSizeListColumn with a case at the relevant conversion boundary and another
whose row count exceeds one execution block. Cover both valid and nullable
inputs as appropriate, and assert the resulting offsets, child values, and null
masks (including nonempty null rows where applicable) rather than only table
equivalence.

In `@cpp/tests/interop/from_arrow_stream_test.cpp`:
- Around line 174-209: Expand the fixed-size-list coverage in
cpp/tests/interop/from_arrow_stream_test.cpp at lines 174-209 by adding
null-row, nonzero-offset sliced, boundary-size, and multi-block-size stream
cases alongside FixedSizeListEmptyTest and FixedSizeListChunkedTest. Expand the
related coverage in python/pylibcudf/tests/test_table.py at lines 110-120 with
empty, all-null, and single-row arrays, plus a mixed-type table containing a
fixed-size-list column; no other sites require changes.

---

Outside diff comments:
In `@cpp/src/interop/from_arrow_host.cu`:
- Around line 608-717: Add fixed-size-list test cases covering row counts at the
relevant execution-size boundary and counts large enough to span multiple
blocks. Extend the existing tests for empty, null, and sliced inputs, using the
from_arrow_column conversion path and validating both conversion success and
resulting values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a1a9d9ea-0721-4ce2-b20b-09819fa50260

📥 Commits

Reviewing files that changed from the base of the PR and between bbeea4b and 43289ef.

📒 Files selected for processing (11)
  • cpp/src/interop/arrow_data_structures.cpp
  • cpp/src/interop/arrow_utilities.cpp
  • cpp/src/interop/arrow_utilities.hpp
  • cpp/src/interop/from_arrow_device.cu
  • cpp/src/interop/from_arrow_host.cu
  • cpp/src/interop/from_arrow_host.hpp
  • cpp/tests/interop/arrow_data_structures_test.cpp
  • cpp/tests/interop/from_arrow_device_test.cpp
  • cpp/tests/interop/from_arrow_host_test.cpp
  • cpp/tests/interop/from_arrow_stream_test.cpp
  • python/pylibcudf/tests/test_table.py

Comment thread cpp/src/interop/from_arrow_host.cu Outdated
Comment thread cpp/tests/interop/from_arrow_device_test.cpp
Comment thread cpp/tests/interop/from_arrow_host_test.cpp
Comment thread cpp/tests/interop/from_arrow_stream_test.cpp
@0guban0v
0guban0v marked this pull request as draft August 7, 2026 15:45
@0guban0v

0guban0v commented Aug 7, 2026

Copy link
Copy Markdown
Author

Addressed in fdf87a7: added overflow-safe bounds validation, including negative metadata, zero width, multiplication overflow, and short-child checks

@0guban0v
0guban0v marked this pull request as ready for review August 7, 2026 17:33
@0guban0v

0guban0v commented Aug 7, 2026

Copy link
Copy Markdown
Author

Ready for maintainer vetting. Could someone add feature request and non-breaking labels and approve NVIDIA runner workflows?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@cpp/src/interop/arrow_utilities.cpp`:
- Around line 111-121: In the fixed-size-list bounds validation before
constructing the returned range, add a check that row_end is at most max_size /
width after the existing int64_t overflow check. Ensure this rejects absolute
child ranges exceeding cudf::size_type before the child_length validation and
return in the surrounding conversion function.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ae361867-000a-429d-8c1b-9343c94183eb

📥 Commits

Reviewing files that changed from the base of the PR and between 43289ef and fdf87a7.

📒 Files selected for processing (8)
  • cpp/src/interop/arrow_utilities.cpp
  • cpp/src/interop/arrow_utilities.hpp
  • cpp/src/interop/from_arrow_device.cu
  • cpp/src/interop/from_arrow_host.cu
  • cpp/tests/interop/from_arrow_device_test.cpp
  • cpp/tests/interop/from_arrow_host_test.cpp
  • cpp/tests/interop/from_arrow_stream_test.cpp
  • python/pylibcudf/tests/test_table.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • python/pylibcudf/tests/test_table.py
  • cpp/src/interop/from_arrow_device.cu
  • cpp/src/interop/from_arrow_host.cu

Comment thread cpp/src/interop/arrow_utilities.cpp
@0guban0v
0guban0v force-pushed the fixed-size-list-arrow-ingress branch from fdf87a7 to 625a3af Compare August 7, 2026 17:46
@GregoryKimball GregoryKimball added feature request New feature or request non-breaking Non-breaking change labels Aug 7, 2026
@0guban0v
0guban0v force-pushed the fixed-size-list-arrow-ingress branch from 625a3af to 8599f6f Compare August 10, 2026 13:46
@0guban0v
0guban0v marked this pull request as draft August 11, 2026 19:04
@0guban0v

0guban0v commented Aug 11, 2026

Copy link
Copy Markdown
Author

I have pending fix to promote, but PR push is blocked likely due to RAPIDS → NVIDIA CUDA-X transition.
@GregoryKimball , please confirm when my fork will be unblocked.

Edit: fork has been unblocked. Thank you.

@0guban0v
0guban0v force-pushed the fixed-size-list-arrow-ingress branch 2 times, most recently from ddf9508 to 5d8fc7b Compare August 12, 2026 15:39
@0guban0v
0guban0v marked this pull request as ready for review August 12, 2026 15:50
@0guban0v
0guban0v requested review from a team as code owners August 12, 2026 15:50
Comment on lines +89 to +91
"Owning Arrow device wrappers do not support fixed-size-list input until "
"fixed-size-list egress is implemented",
cudf::data_type_error);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please remove the "TODO" from the error message.

Comment on lines +363 to +365
owned.emplace_back(make_fixed_size_list_offsets(
static_cast<size_type>(layout.row_end) + 1, layout.width, stream, mr));
offsets_view = owned.back()->view();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: is it worth introducing this helper function that is only used here and could be inlined, I think.

{
constexpr int32_t width = 2;

for (auto const num_rows : {cudf::size_type{1024}, cudf::size_type{1025}}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we need to test two different numbers of rows here?

* @return INT32 offsets column
*/
std::unique_ptr<column> make_fixed_size_list_offsets(size_type size,
int32_t width,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: Should the width value also be size_type?

Comment thread cpp/src/interop/from_arrow_host.hpp Outdated
* @param width Number of child elements per list row
* @param stream CUDA stream used for device memory operations
* @param mr Device memory resource to use for all device memory allocations
* @return INT32 offsets column

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: This is correct today, but becomes out of date if we move to 64bit offsets.

Comment thread cpp/src/interop/from_arrow_host.hpp Outdated
* Arrow fixed-size-list arrays carry no offsets buffer; the offsets are implicit.
* This generates `size` offsets of the form `{0, width, 2*width, ...}`.
*
* @param size Number of offsets to generate (normally num_rows + 1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When would it not be num_rows + 1?

* @brief Validated physical bounds for an Arrow fixed-size-list array
*/
struct fixed_size_list_layout {
int32_t width; ///< Child elements per row and LIST offset increment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: size_type? Or does the arrow spec mandate int32?

@wence-

wence- commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

/ok to test 5d8fc7b

@0guban0v
0guban0v force-pushed the fixed-size-list-arrow-ingress branch from 5d8fc7b to b2fe766 Compare August 12, 2026 21:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
cpp/src/interop/from_arrow_host.cu (1)

443-444: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the current device resource for the Thrust execution policy.

The policy passed to thrust::sequence supplies the allocator for temporary allocations. The output resource mr should own only the returned offsets column. Pass cudf::get_current_device_resource_ref() to rmm::exec_policy_nosync instead. thrust::sequence rarely allocates, so the practical impact is small.

As per coding guidelines, "Temporary memory not using cudf::get_current_device_resource_ref()" is a review concern for cpp/**/*.{cpp,cu,hpp,cuh}.

♻️ Proposed change
-  thrust::sequence(
-    rmm::exec_policy_nosync(stream, mr), d_offsets, d_offsets + num_offsets, int32_t{0}, width);
+  thrust::sequence(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()),
+                   d_offsets,
+                   d_offsets + num_offsets,
+                   int32_t{0},
+                   width);
🤖 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/interop/from_arrow_host.cu` around lines 443 - 444, Update the
execution policy used by thrust::sequence to pass
cudf::get_current_device_resource_ref() instead of the output resource mr,
keeping mr responsible only for the returned offsets column.

Source: Coding guidelines

cpp/tests/interop/from_arrow_stream_test.cpp (1)

128-189: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share the fixed-size-list Arrow test helpers. The fixed-size-list schema builder and array builder are duplicated almost verbatim across the interop test files. cudf_test/nanoarrow_utils.hpp is already included by these tests and is the natural home for them.

  • cpp/tests/interop/from_arrow_stream_test.cpp#L128-L189: Move make_fixed_size_list_stream_schema and make_fixed_size_list_chunk into cudf_test/nanoarrow_utils.hpp under one shared name, then call the shared helpers here.
  • cpp/tests/interop/from_arrow_host_test.cpp#L535-L610: Replace make_fixed_size_list_schema and make_fixed_size_list_array with the shared helpers, and keep as_host_device_array local if it stays host-specific.
🤖 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/interop/from_arrow_stream_test.cpp` around lines 128 - 189, Move
the duplicated fixed-size-list schema and array builders into the shared
nanoarrow utility header under common helper names, preserving their current
behavior and signatures as needed. In
cpp/tests/interop/from_arrow_stream_test.cpp lines 128-189, remove the local
make_fixed_size_list_stream_schema and make_fixed_size_list_chunk definitions
and update callers to use the shared helpers. In
cpp/tests/interop/from_arrow_host_test.cpp lines 535-610, replace
make_fixed_size_list_schema and make_fixed_size_list_array with the shared
helpers; leave as_host_device_array local if it remains host-specific.
🤖 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.

Inline comments:
In `@cpp/tests/interop/arrow_data_structures_test.cpp`:
- Around line 324-333: Extend Arrow interop tests near
NestedFixedSizeListDeviceInputRejected with a schema whose dictionary value type
is a fixed-size list, then construct the corresponding arrow_column or
arrow_table and assert it throws cudf::data_type_error. Reuse the existing
fixed-size-list and device-input helpers where applicable, while preserving the
current direct-schema and struct-child coverage.

---

Nitpick comments:
In `@cpp/src/interop/from_arrow_host.cu`:
- Around line 443-444: Update the execution policy used by thrust::sequence to
pass cudf::get_current_device_resource_ref() instead of the output resource mr,
keeping mr responsible only for the returned offsets column.

In `@cpp/tests/interop/from_arrow_stream_test.cpp`:
- Around line 128-189: Move the duplicated fixed-size-list schema and array
builders into the shared nanoarrow utility header under common helper names,
preserving their current behavior and signatures as needed. In
cpp/tests/interop/from_arrow_stream_test.cpp lines 128-189, remove the local
make_fixed_size_list_stream_schema and make_fixed_size_list_chunk definitions
and update callers to use the shared helpers. In
cpp/tests/interop/from_arrow_host_test.cpp lines 535-610, replace
make_fixed_size_list_schema and make_fixed_size_list_array with the shared
helpers; leave as_host_device_array local if it remains host-specific.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 889a9cb2-074c-4dd0-9902-b8508e11dde6

📥 Commits

Reviewing files that changed from the base of the PR and between 40ba83d and b2fe766.

📒 Files selected for processing (11)
  • cpp/src/interop/arrow_data_structures.cpp
  • cpp/src/interop/arrow_utilities.cpp
  • cpp/src/interop/arrow_utilities.hpp
  • cpp/src/interop/from_arrow_device.cu
  • cpp/src/interop/from_arrow_host.cu
  • cpp/src/interop/from_arrow_host.hpp
  • cpp/tests/interop/arrow_data_structures_test.cpp
  • cpp/tests/interop/from_arrow_device_test.cpp
  • cpp/tests/interop/from_arrow_host_test.cpp
  • cpp/tests/interop/from_arrow_stream_test.cpp
  • python/pylibcudf/tests/test_table.py

Comment on lines +324 to +333

TEST_F(ArrowTableTest, NestedFixedSizeListDeviceInputRejected)
{
auto schema = make_fixed_size_list_schema(true);
auto array = make_empty_device_array();

EXPECT_THROW(
{ static_cast<void>(cudf::interop::arrow_table(std::move(*schema.get()), std::move(array))); },
cudf::data_type_error);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add coverage for dictionary-held fixed-size lists.

Line 36 in cpp/src/interop/arrow_data_structures.cpp traverses schema.dictionary. These tests cover a direct schema and a struct child only. Add a dictionary schema whose dictionary value is a fixed-size list. Assert that the owning arrow_column or arrow_table constructor throws cudf::data_type_error.

As per coding guidelines, **/*: “Add unit tests and unit benchmarks.”

🤖 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/interop/arrow_data_structures_test.cpp` around lines 324 - 333,
Extend Arrow interop tests near NestedFixedSizeListDeviceInputRejected with a
schema whose dictionary value type is a fixed-size list, then construct the
corresponding arrow_column or arrow_table and assert it throws
cudf::data_type_error. Reuse the existing fixed-size-list and device-input
helpers where applicable, while preserving the current direct-schema and
struct-child coverage.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request libcudf Affects libcudf (C++/CUDA) code. non-breaking Non-breaking change pylibcudf Issues specific to the pylibcudf package Python Affects Python cuDF API.

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[FEA] Support Arrow FixedSizeList in libcudf interop

5 participants