Skip to content

[POC] Add BINARY type to cuDF supporting 32-bit and 64-bit offsets - #23658

Draft
GregoryKimball wants to merge 12 commits into
NVIDIA:mainfrom
GregoryKimball:cudf-binary-type
Draft

[POC] Add BINARY type to cuDF supporting 32-bit and 64-bit offsets#23658
GregoryKimball wants to merge 12 commits into
NVIDIA:mainfrom
GregoryKimball:cudf-binary-type

Conversation

@GregoryKimball

@GregoryKimball GregoryKimball commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Description

Many data processing workloads carry binary data as payloads. cuDF has represented this data using a physical type of LIST<UNIT8>, but this representation often hits the limit of 2.1 GB per column due to the size_type limit on list children. If cuDF had a BINARY type, we could naturally represent these kind of payloads, and with the offsetalator pattern from STRINGS we could also support LARGE_BINARY arrow data using 64-bit offsets.

Adding a BINARY type to cuDF brings several benefits:

  • enable workloads to carry significant amounts of inline image data without having to carefully partition the table to avoid list overflow
  • enable variant data to be represented in columns without list overflow. Status quo is that JSON strings can reach dozens of GB per table, but then the table has to be partitioned before conversion to variant. Variant data uses a physical type of STRUCT<LIST<UNIT8>,LIST<UINT8>> and this could change to STRUCT<BINARY,BINARY>.
  • Parquet supports binary data, and currently the cuDF readers and writers have to convert binary to either STRING or LIST<UINT8>. A native binary type would be a more natural target type.
  • BINARY type could also let users convert and carry lists of fixed width type, like LIST<FLOAT32> embeddings beyond the 32-bit child limit.

Why haven't we added BINARY yet?

  • Adding a new type to cuDF adds another branch to the type dispatcher. Adding a branch to the type dispatcher increases compile time, binary size, and can reduce kernel occupancy.
  • LIST<UINT8> has been an adequate workaround
  • We were paranoid about adding types because of an occupancy cliff in mixed join and AST. But now we have deprecated the mixed join kernels (for join, chunked probe, post filter instead), and have more mature JIT tools to avoid AST occupancy issues.

What is this POC for?

  • measuring the libcudf.so binary size impact of adding a type
    • measurement is promising. Baseline: 188.734 MiB, BINARY branch: 191.350 MiB
  • measuring the compilation time impact of adding a type
  • measuring the microbenchmark differences from adding a type
    • seems not too bad
image
  • clarifying the blast radius of such a change

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Define the byte-oriented row view, variable-width column view, and factories with INT32 or INT64 offsets. Register the new sources and permit BINARY parent payload storage.
Map BINARY to binary_view, enable device element access, and add explicit support boundaries for APIs that still depend on deferred scalar or variable-width implementations.
Cover dispatcher and trait mappings, both offset widths, canonical empty layout, unsigned-byte ordering, factory validation, and device row access.
Copy sliced BINARY columns with normalized offsets, preserved offset width, payload bytes, and validity so generic column copy construction handles the new type.
Add a device-view factory and use it to move variable-width binary rows through generic gather and concatenate paths, including sliced and out-of-bounds inputs.
Materialize target binary views, scatter source rows into them, and rebuild the variable-width output while preserving empty and null values.
Hash binary payload bytes across MurmurHash and xxHash implementations, and verify unsigned-byte ordering and equality through sort and distinct operations.
Exercise dictionary encode and decode with duplicate and empty binary payloads to establish support through generic hash, sort, gather, and comparison paths.
Add a per-column byte-array output policy, default unannotated BYTE_ARRAY and fixed-length data to BINARY, preserve annotated text as STRING, and retain the legacy LIST<UINT8> compatibility path.
Encode native BINARY payloads through Parquet byte-array paths, including dictionary encoding and statistics, so BINARY columns round-trip without conversion.
Emit Arrow BinaryView metadata for native BINARY columns so Arrow-schema-enabled Parquet round trips retain byte semantics.
Honor type-length metadata for native BINARY columns and encode their payloads as FIXED_LEN_BYTE_ARRAY values with round-trip coverage.
@copy-pr-bot

copy-pr-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

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.

@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. CMake CMake build issue labels Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CMake CMake build issue libcudf Affects libcudf (C++/CUDA) code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant