Skip to content

Commit 31fda42

Browse files
authored
perf[gpu]: generate FixedSizeList offsets on device (#8458)
Use the existing CUDA sequence kernel to materialize Arrow List offsets for FixedSizeList export directly on the device. This avoids building the offsets buffer on the CPU and copying it to CUDA memory while preserving existing i32 overflow checks. Signed-off-by: "Alexander Droste" <alexander.droste@protonmail.com>
1 parent 4652f29 commit 31fda42

1 file changed

Lines changed: 24 additions & 12 deletions

File tree

vortex-cuda/src/arrow/canonical.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ async fn export_fixed_size_list(
10111011
} = array.into_data_parts();
10121012

10131013
let (validity_buffer, null_count) = export_arrow_validity_buffer(validity, len, 0, ctx).await?;
1014-
let offsets_buffer = fixed_size_list_offsets(len, list_size, ctx).await?;
1014+
let offsets_buffer = fixed_size_list_offsets(len, list_size, ctx)?;
10151015

10161016
export_list_layout(
10171017
elements,
@@ -1025,7 +1025,7 @@ async fn export_fixed_size_list(
10251025
.await
10261026
}
10271027

1028-
async fn fixed_size_list_offsets(
1028+
fn fixed_size_list_offsets(
10291029
len: usize,
10301030
list_size: u32,
10311031
ctx: &mut CudaExecutionCtx,
@@ -1035,17 +1035,29 @@ async fn fixed_size_list_offsets(
10351035
"cannot export FixedSizeList with list size {list_size}: Arrow List offsets require i32"
10361036
)
10371037
})?;
1038-
let offsets = (0..=i32::try_from(len)?)
1039-
.map(|idx| {
1040-
idx.checked_mul(list_size)
1041-
.ok_or_else(|| vortex_err!("FixedSizeList Arrow List offsets exceed i32 range"))
1042-
})
1043-
.collect::<VortexResult<Vec<_>>>()?;
1038+
let len_i32 = i32::try_from(len)?;
1039+
len_i32
1040+
.checked_mul(list_size)
1041+
.ok_or_else(|| vortex_err!("FixedSizeList Arrow List offsets exceed i32 range"))?;
1042+
1043+
let output_len = len
1044+
.checked_add(1)
1045+
.ok_or_else(|| vortex_err!("FixedSizeList Arrow List offsets length overflows usize"))?;
1046+
let offsets = ctx.device_alloc::<i32>(output_len)?;
1047+
let base = 0i32;
1048+
let output_len_u64 = output_len as u64;
1049+
let kernel = ctx.load_function_with_suffixes("sequence", &["i32"])?;
1050+
1051+
ctx.launch_kernel(&kernel, output_len, |args| {
1052+
args.arg(&offsets)
1053+
.arg(&base)
1054+
.arg(&list_size)
1055+
.arg(&output_len_u64);
1056+
})?;
10441057

1045-
ctx.ensure_on_device(BufferHandle::new_host(
1046-
Buffer::from(offsets).into_byte_buffer(),
1047-
))
1048-
.await
1058+
Ok(BufferHandle::new_device(Arc::new(CudaDeviceBuffer::new(
1059+
offsets,
1060+
))))
10491061
}
10501062

10511063
/// Return Arrow Device `List` offsets as an `i32` device buffer.

0 commit comments

Comments
 (0)