You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "prtkgaur (via GitHub)" <gi...@apache.org> on 2026/09/10 19:53:36 UTC

[PR] GH-51268: [C++][Parquet] Scan DELTA_BINARY_PACKED deltas a vector at a time [arrow]

prtkgaur opened a new pull request, #51295:
URL: https://github.com/apache/arrow/pull/51295

   DESCRIPTION:
   
   
   > Builds on #51250 and contains its commit, since the gain here depends on it. Only the
   > last two commits belong to this PR, and the benchmark below is measured against its
   > parent as well as against main.
   
   ### Rationale for this change
   
   Once equal-width miniblocks are unpacked in one call, what is left per value is the prefix
   sum: a chain of dependent additions, one value at a time, with the running total carried
   from each to the next. That chain is now the cost of decoding a narrow DELTA_BINARY_PACKED
   page.
   
   The sum can be computed several values at a time instead. A log-step inclusive scan turns
   a register of deltas into a register of running totals in log2(lanes) shifted additions,
   and the frame is added *before* the scan, which makes its running multiple fall out of the
   scan itself rather than needing a separate multiply per lane.
   
   ### What changes are included in this PR?
   
   The value-at-a-time loop becomes a helper that scans whole registers and finishes the
   remainder one value at a time, carrying the running total across registers. Every term
   stays in the unsigned type, so the wrapping the format specifies is unchanged and decoded
   values are identical.
   
   Two details are worth a reviewer's attention:
   
   - **How the running total crosses registers.** The obvious way -- read the last lane into a
     general-purpose register, re-broadcast it -- puts a vector-to-scalar round trip on the
     critical dependency chain and is *slower than the scalar loop it replaces*: measured in
     isolation, 0.480 ns per value scalar, 1.528 ns that way, 0.361 ns keeping the carry in a
     vector register and broadcasting the last lane with a shuffle. The helper does the last
     of those.
   - **The threshold is a lane count, not a type.** A scan pays off only once a register holds
     enough values to beat the additions it replaces; at two lanes it loses, because one
     doubling step plus the carry costs more than the two additions saved. So the vector loop
     is compiled only where a register holds four or more values, and otherwise the remainder
     loop does all the work. At Arrow's default 128-bit baseline that means 32-bit values are
     scanned and 64-bit values fall through to the same loop as today; with a wider baseline
     both are scanned. The 64-bit vector loop therefore is not built by a default
     configuration and is not exercised by CI as it stands.
   
   This overlaps #51249: the helper takes the frame and the running total by value and returns
   the new total, which is what that PR does by hand, so whichever lands second needs a
   trivial rebase. It is also why the 64-bit arms improve here without being vectorized.
   
   ### Are these changes tested?
   
   A new typed test walks every residual bit width for both integer widths, and at each width
   enough lengths to leave every remainder a register-sized group can leave, so each width is
   decoded through the vector loop, through the remainder, and across the hand-off between
   them. Deltas alternate between the frame and the widest value the width can hold, which
   pins the stored width, keeps a non-zero frame in play -- its running multiple grows with
   the index, so folding it in per register has to get that multiple right -- and wraps the
   running total repeatedly, which is where a grouped total and a value-at-a-time one part
   company if any term is signed. Three mutations each turn it red: dropping the frame's
   running multiple and losing the carry between registers fail the 32-bit instantiation,
   which is the one that builds a vector loop here, and stopping the remainder loop one value
   early fails both.
   
   Outside the tree, the helper was also checked element-wise against the loop it replaces
   over 2760 cases per width, across value counts 0 to 1024, forty seeds, and full-range
   wrapping / small / near-maximum value ranges.
   
   ### Benchmark
   
   Same setup as #51250: AWS Graviton4, GCC 11.5, `Release`, one core, 9 repetitions, medians,
   65,536 values. Every point built twice with the builds interleaved, so no ratio crosses two
   builds; both ratios are given. `NarrowSorted` is the arm added by the first of the two
   commits and holds non-decreasing values, the shape DELTA_BINARY_PACKED is usually chosen
   for. The `Fixed` arms are the zero bit width path, which has no prefix sum to scan.
   
   | benchmark | #51250 | this PR | | vs. main |
   |---|--:|--:|--:|--:|
   | `Decode_Int32_NarrowSorted` | 73.7 us | 45.7 us | **1.61x** / 1.61x | **2.18x** |
   | `Decode_Int32_Narrow` | 74.8 us | 46.4 us | **1.61x** / 1.61x | **2.15x** |
   | `Decode_Int32_Wide` | 83.7 us | 53.6 us | **1.56x** / 1.56x | **1.90x** |
   | `Decode_Int64_NarrowSorted` | 71.4 us | 55.0 us | **1.30x** / 1.30x | **1.47x** |
   | `Decode_Int64_Narrow` | 70.9 us | 55.2 us | **1.28x** / 1.29x | **1.49x** |
   | `Decode_Int64_Wide` | 318.6 us | 301.3 us | 1.06x / 1.06x | 1.07x |
   | `Decode_Int32_Fixed` | 20.4 us | 20.5 us | 1.00x / 1.00x | 0.97x |
   | `Decode_Int64_Fixed` | 31.3 us | 31.3 us | 1.00x / 1.00x | 0.98x |
   
   The gain needs #51250 underneath it. On top of #51249 alone, without coalescing, the same
   kernel measures 0.98x to 1.03x across the 32-bit arms -- a wash. Per-register setup only
   amortizes over the longer runs coalescing produces; at one unpack call per 32 values there
   is not enough work between calls for it to pay.
   
   ### Are there any user-facing changes?
   
   No. No API change, no format change, and decoded values are identical.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [WIP][POC] GH-51268: [C++][Parquet] Scan DELTA_BINARY_PACKED deltas a vector at a time [arrow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #51295:
URL: https://github.com/apache/arrow/pull/51295#issuecomment-5982210571

   <!--
     Licensed to the Apache Software Foundation (ASF) under one
     or more contributor license agreements.  See the NOTICE file
     distributed with this work for additional information
     regarding copyright ownership.  The ASF licenses this file
     to you under the Apache License, Version 2.0 (the
     "License"); you may not use this file except in compliance
     with the License.  You may obtain a copy of the License at
   
       http://www.apache.org/licenses/LICENSE-2.0
   
     Unless required by applicable law or agreed to in writing,
     software distributed under the License is distributed on an
     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     KIND, either express or implied.  See the License for the
     specific language governing permissions and limitations
     under the License.
   -->
   
   Thanks for opening a pull request!
   
   **This pull request has been automatically converted to a draft because its title doesn't match Arrow's required format.**
   
   If this is not a [minor PR](https://github.com/apache/arrow/blob/main/CONTRIBUTING.md#Minor-Fixes), could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose
   
   Opening GitHub issues ahead of time contributes to the [Openness](http://theapacheway.com/open/#:~:text=Openness%20allows%20new%20users%20the,must%20happen%20in%20the%20open.) of the Apache Arrow project.
   
   Then could you also rename the pull request title in the following format?
   
       GH-${GITHUB_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}
   
   or
   
       MINOR: [${COMPONENT}] ${SUMMARY}
   
   **After updating the title, you can mark the pull request as ready for review.**
   
   See also:
   
     * [Other pull requests](https://github.com/apache/arrow/pulls/)
     * [Contribution Guidelines - Contributing Overview](https://arrow.apache.org/docs/developers/overview.html)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org