[FEA] Improve Parquet decoding throughput in libcudf
- Dominant language
- C++
- Stars
- 9.8k
- Forks
- 1.1k
- Avg merge
- 3d 6m
- Merged PRs (30d)
- 278
Description
**Is your feature request related to a problem? Please describe.**
We use specialized kernels to process uncompressed, encoded parquet data pages into arrow-formatted cuDF columns. The throughput achieved by the decoding kernels is a function of data type, and many data types show <50 GB/s of throughput on H100.
* generic decode kernel containing decode device functions, includes struct, list, string, fixed width, dictionary device functions
* delta byte array kernel for strings
* delta length byte array kernel for strings

You can generate this data using this command:
```
./PARQUET_READER_NVBENCH -b 0 -a cardinality=0 -a run_length=1 --timeout 0.2
```
# Nsight Systems Profiles
Let's look at nsys profiles for each data type.
## INTEGER

Shows three kernels (total 4 ms) of `gpuDecodePageDataGeneric`. Peak warp occupancy is ~50%, with drops at the end.
## FLOAT

Shows one 1.7 ms kernel of `gpuDecodePageDataGeneric`. Peak warp occupancy is ~50%, with drops at the end.
## BOOL8

Shows one 8 ms kernel of `gpuDecodePageDataGeneric`. Peak warp occupancy is ~50%, with drops at the end.
## DECIMAL

Shows 8.3 ms of unsnap (we should remove this, see #18349). Shows 1.3 ms of `gpuDecodePageDataGeneric`
## TIMESTAMP

Shows 8.3 ms of unsnap (we should remove this, see #18349). Shows 1.7 ms over two calls of `gpuDecodePageDataGeneric`
## DURATION

Shows 1.6 ms of unsnap (we should remove this, see #18349). Shows 1.7 ms over two calls of `gpuDecodePageDataGeneric`
## STRING

Shows 10 ms of unsnap (we should remove this, see #18349). Shows 0.7 ms in `gpuComputeStringPageBounds` and 9.6 ms in `gpuDecodePageDataGeneric`.
## LIST

Shows 3.1 ms of unsnap, 6.2 ms of `gpuComputePageSizes` and 8.4 ms of `gpuDecodePageDataGeneric`. Plus 9.5 ms of `cub::reduce`, something like 120 calls. Is this a per-page reduction? (Needs attribution)
## STRUCT

Shows 9.3 ms in unsnap, 6 ms in `gpuDecodePageDataGeneric` over two calls, and 29 ms in recursive calls to `superimpose_nulls_no_sanitize`.
**Describe the solution you'd like**
I believe we should target at least 100 GB/s throughput in the decode stage. We may need new approaches such as state machines based on the libcudf FST, intra-warp coordination, better usage of shared memory and L2 cache, and more ideas.
Opportunities:
* For strings, can we precompute more pieces similar to `gpuComputeStringPageBounds` so that the decode can run faster than 9.6 ms?
* For lists, can we fuse any of the `cub::DeviceReduce::Reduce` calls?
* For structs, can we find a more efficient approach to ensure nulls sanitization? 29 ms is a very long time
Contributor guide
Assessment
This issue has not been assessed yet.