This is an automated email from the ASF dual-hosted git repository.
agrove pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-comet.git
The following commit(s) were added to refs/heads/main by this push:
new d8ab910e fix: Optimize decimal creation macros (#764)
d8ab910e is described below
commit d8ab910e6933be1136a5242d3d08d1103743b04e
Author: KAZUYUKI TANIMURA <[email protected]>
AuthorDate: Tue Aug 6 06:18:11 2024 -0700
fix: Optimize decimal creation macros (#764)
---
native/core/benches/parquet_decode.rs | 10 ++-
native/core/src/parquet/read/values.rs | 149 ++++++---------------------------
2 files changed, 34 insertions(+), 125 deletions(-)
diff --git a/native/core/benches/parquet_decode.rs
b/native/core/benches/parquet_decode.rs
index 7176bf9c..75eefd5d 100644
--- a/native/core/benches/parquet_decode.rs
+++ b/native/core/benches/parquet_decode.rs
@@ -16,12 +16,12 @@
// under the License.
use arrow_buffer::ToByteSlice;
-use comet::parquet::read::values::{copy_i32_to_i16, copy_i32_to_u16};
+use comet::parquet::read::values::{copy_i32_to_i16, copy_i32_to_u16,
copy_i64_to_i64};
use criterion::{criterion_group, criterion_main, Criterion};
fn criterion_benchmark(c: &mut Criterion) {
let num = 1000;
- let source = vec![78_i8; num * 4];
+ let source = vec![78_i8; num * 8];
let mut group = c.benchmark_group("parquet_decode");
group.bench_function("decode_i32_to_i16", |b| {
let mut dest: Vec<u8> = vec![b' '; num * 2];
@@ -35,6 +35,12 @@ fn criterion_benchmark(c: &mut Criterion) {
copy_i32_to_u16(source.to_byte_slice(), dest.as_mut_slice(), num);
});
});
+ group.bench_function("decode_i64_to_i64", |b| {
+ let mut dest: Vec<u8> = vec![b' '; num * 8];
+ b.iter(|| {
+ copy_i64_to_i64(source.to_byte_slice(), dest.as_mut_slice(), num);
+ });
+ });
}
// Create UTF8 batch with strings representing ints, floats, nulls
diff --git a/native/core/src/parquet/read/values.rs
b/native/core/src/parquet/read/values.rs
index b89face0..324f6106 100644
--- a/native/core/src/parquet/read/values.rs
+++ b/native/core/src/parquet/read/values.rs
@@ -27,7 +27,7 @@ use crate::write_null;
use crate::write_val_or_null;
use crate::{
common::bit::{self, BitReader},
- parquet::{data_type::*, read::DECIMAL_BYTE_WIDTH, ParquetMutableVector},
+ parquet::{data_type::*, ParquetMutableVector},
unlikely,
};
use arrow::datatypes::DataType as ArrowDataType;
@@ -214,6 +214,9 @@ make_int_variant_dict_impl!(Int32ToDecimal64Type, i32, i64);
make_int_variant_dict_impl!(Int32ToDoubleType, i32, f64);
make_int_variant_dict_impl!(Int32TimestampMicrosType, i32, i64);
make_int_variant_dict_impl!(FloatToDoubleType, f32, f64);
+make_int_variant_dict_impl!(Int32DecimalType, i128, i128);
+make_int_variant_dict_impl!(Int64DecimalType, i128, i128);
+make_int_variant_dict_impl!(UInt64Type, u128, u128);
impl PlainDecoding for Int32DateType {
fn decode(src: &mut PlainDecoderInner, dst: &mut ParquetMutableVector,
num: usize) {
@@ -483,7 +486,7 @@ macro_rules! make_int_decimal_variant_impl {
impl PlainDecoding for $ty {
fn decode(src: &mut PlainDecoderInner, dst: &mut
ParquetMutableVector, num: usize) {
let dst_slice = dst.value_buffer.as_slice_mut();
- let dst_offset = dst.num_values * 8;
+ let dst_offset = dst.num_values *
std::mem::size_of::<$dst_type>();
$copy_fn(&src.data[src.offset..], &mut
dst_slice[dst_offset..], num);
let src_precision = src.desc.type_precision() as u32;
@@ -532,7 +535,10 @@ macro_rules! make_int_decimal_variant_impl {
};
}
make_int_decimal_variant_impl!(Int32ToDecimal64Type, copy_i32_to_i64, 4, i64);
+make_int_decimal_variant_impl!(Int32DecimalType, copy_i32_to_i128, 4, i128);
make_int_decimal_variant_impl!(Int64ToDecimal64Type, copy_i64_to_i64, 8, i64);
+make_int_decimal_variant_impl!(Int64DecimalType, copy_i64_to_i128, 8, i128);
+make_int_decimal_variant_impl!(UInt64Type, copy_u64_to_u128, 8, u128);
#[macro_export]
macro_rules! write_val_or_null {
@@ -612,22 +618,13 @@ macro_rules! generate_cast_to_signed {
generate_cast_to_signed!(copy_i32_to_i8, i32, i8);
generate_cast_to_signed!(copy_i32_to_i16, i32, i16);
generate_cast_to_signed!(copy_i32_to_i64, i32, i64);
+generate_cast_to_signed!(copy_i32_to_i128, i32, i128);
generate_cast_to_signed!(copy_i32_to_f64, i32, f64);
+generate_cast_to_signed!(copy_i64_to_i64, i64, i64);
+generate_cast_to_signed!(copy_i64_to_i128, i64, i128);
+generate_cast_to_signed!(copy_u64_to_u128, u64, u128);
generate_cast_to_signed!(copy_f32_to_f64, f32, f64);
-fn copy_i64_to_i64(src: &[u8], dst: &mut [u8], num: usize) {
- debug_assert!(
- src.len() >= num * std::mem::size_of::<i64>(),
- "Source slice is too small"
- );
- debug_assert!(
- dst.len() >= num * std::mem::size_of::<i64>(),
- "Destination slice is too small"
- );
-
- bit::memcpy_value(src, std::mem::size_of::<i64>() * num, dst);
-}
-
// Shared implementation for variants of Binary type
macro_rules! make_plain_binary_impl {
($($ty: ident), *) => {
@@ -758,112 +755,17 @@ macro_rules! make_plain_dict_binary_impl {
make_plain_dict_binary_impl! { ByteArrayType, StringType }
-macro_rules! make_plain_decimal_impl {
- ($is_signed: expr, $($ty: ident; $need_convert: expr), *) => {
- $(
- impl PlainDecoding for $ty {
- fn decode(src: &mut PlainDecoderInner, dst: &mut
ParquetMutableVector, num: usize) {
- let byte_width = src.desc.type_length() as usize;
-
- let src_data = &src.data[src.offset..];
- let dst_data = &mut dst.value_buffer[dst.num_values *
DECIMAL_BYTE_WIDTH..];
-
- let mut src_offset = 0;
- let mut dst_offset = 0;
-
- debug_assert!(byte_width <= DECIMAL_BYTE_WIDTH);
-
- let src_precision = src.desc.type_precision() as u32;
- let src_scale = ::std::cmp::max(src.desc.type_scale(), 0)
as u32;
- let (dst_precision, dst_scale) = match dst.arrow_type {
- ArrowDataType::Decimal128(p, s) if s >= 0 => (p as
u32, s as u32),
- _ => unreachable!(),
- };
- let upper = 10_i128.pow(dst_precision);
- let mul_div = 10_i128.pow(dst_scale.abs_diff(src_scale));
-
- for i in 0..num {
- let s = &mut dst_data[dst_offset..];
-
- bit::memcpy(
- &src_data[src_offset..src_offset + byte_width],
- s,
- );
-
- // Swap the order of bytes to make it little-endian.
- if $need_convert {
- for i in 0..byte_width / 2 {
- s.swap(i, byte_width - i - 1);
- }
- }
-
- if $is_signed {
- // Check if the most significant bit is 1
(negative in 2's complement).
- // If so, also fill pad the remaining bytes with
0xff.
- if s[byte_width - 1] & 0x80 == 0x80 {
- s[byte_width..DECIMAL_BYTE_WIDTH].fill(0xff);
- }
- }
-
- if dst_scale > src_scale {
- let v = s.as_mut_ptr() as *mut i128;
- unsafe {
- // SAFETY the caller must ensure `i`th pointer
is in bounds
- write_val_or_null!(v, v.read_unaligned() *
mul_div, upper, dst, i);
- }
- } else if dst_scale < src_scale {
- let v = s.as_mut_ptr() as *mut i128;
- unsafe {
- // SAFETY the caller must ensure `i`th pointer
is in bounds
- write_val_or_null!(v, v.read_unaligned() /
mul_div, upper, dst, i);
- }
- } else if src_precision > dst_precision {
- let v = s.as_mut_ptr() as *mut i128;
- write_null!(unsafe { v.read_unaligned() }, upper,
dst, i);
- }
-
- src_offset += byte_width;
- dst_offset += DECIMAL_BYTE_WIDTH;
- }
-
- src.offset += num * byte_width;
- }
-
- #[inline]
- fn skip(src: &mut PlainDecoderInner, num: usize) {
- let num_bytes_to_skip = num * src.desc.type_length() as
usize;
- src.offset += num_bytes_to_skip;
- }
- }
-
- impl PlainDictDecoding for $ty {
- fn decode_dict_one(_: usize, val_idx: usize, src:
&ParquetMutableVector, dst: &mut ParquetMutableVector, _: usize) {
- let src_offset = val_idx * DECIMAL_BYTE_WIDTH;
- let dst_offset = dst.num_values * DECIMAL_BYTE_WIDTH;
-
- bit::memcpy(
- &src.value_buffer[src_offset..src_offset +
DECIMAL_BYTE_WIDTH],
- &mut dst.value_buffer[dst_offset..dst_offset +
DECIMAL_BYTE_WIDTH],
- );
- }
- }
- )*
- }
-}
-
-make_plain_decimal_impl!(true, Int32DecimalType; false, Int64DecimalType;
false, FLBADecimalType; true);
-make_plain_decimal_impl!(false, UInt64Type; false);
-
macro_rules! make_plain_decimal_int_impl {
- ($($ty: ident; $num_bytes: expr), *) => {
+ ($($ty: ident; $dst_type:ty), *) => {
$(
impl PlainDecoding for $ty {
fn decode(src: &mut PlainDecoderInner, dst: &mut
ParquetMutableVector, num: usize) {
+ let num_bytes = std::mem::size_of::<$dst_type>();
let byte_width = src.desc.type_length() as usize;
- let num_bits = 64.min(8 * byte_width);
+ let num_bits = num_bytes.saturating_sub(byte_width) * 8;
let src_data = &src.data[src.offset..];
- let dst_data = &mut dst.value_buffer[dst.num_values *
$num_bytes..];
+ let dst_data = &mut dst.value_buffer[dst.num_values *
num_bytes..];
let mut src_offset = 0;
@@ -873,22 +775,22 @@ macro_rules! make_plain_decimal_int_impl {
ArrowDataType::Decimal128(p, s) if s >= 0 => (p as
u32, s as u32),
_ => (src_precision, src_scale),
};
- let upper = 10_i64.pow(dst_precision);
- let mul_div = 10_i64.pow(dst_scale.abs_diff(src_scale));
+ let upper = (10 as $dst_type).pow(dst_precision);
+ let mul_div = (10 as
$dst_type).pow(dst_scale.abs_diff(src_scale));
for i in 0..num {
- let mut unscaled: i64 = 0;
+ let mut unscaled: $dst_type = 0;
for _ in 0..byte_width {
- unscaled = unscaled << 8 | src_data[src_offset] as
i64;
+ unscaled = unscaled << 8 | src_data[src_offset] as
$dst_type;
src_offset += 1;
}
- unscaled = (unscaled << (64 - num_bits)) >> (64 -
num_bits);
+ unscaled = (unscaled << num_bits) >> num_bits;
if dst_scale > src_scale {
unscaled *= mul_div;
} else if dst_scale < src_scale {
unscaled /= mul_div;
}
- bit::memcpy_value(&unscaled, $num_bytes, &mut
dst_data[i * $num_bytes..]);
+ bit::memcpy_value(&unscaled, num_bytes, &mut
dst_data[i * num_bytes..]);
if src_precision > dst_precision {
write_null!(unscaled, upper, dst, i);
}
@@ -906,9 +808,10 @@ macro_rules! make_plain_decimal_int_impl {
impl PlainDictDecoding for $ty {
#[inline]
fn decode_dict_one(_: usize, val_idx: usize, src:
&ParquetMutableVector, dst: &mut ParquetMutableVector, _: usize) {
+ let num_bytes = std::mem::size_of::<$dst_type>();
bit::memcpy(
- &src.value_buffer[val_idx * $num_bytes..(val_idx + 1)
* $num_bytes],
- &mut dst.value_buffer[dst.num_values * $num_bytes..],
+ &src.value_buffer[val_idx * num_bytes..(val_idx + 1) *
num_bytes],
+ &mut dst.value_buffer[dst.num_values * num_bytes..],
);
}
}
@@ -916,7 +819,7 @@ macro_rules! make_plain_decimal_int_impl {
};
}
-make_plain_decimal_int_impl!(FLBADecimal32Type; 4, FLBADecimal64Type; 8);
+make_plain_decimal_int_impl!(FLBADecimal32Type; i32, FLBADecimal64Type; i64,
FLBADecimalType; i128);
// Int96 contains 12 bytes
const INT96_SRC_BYTE_WIDTH: usize = 12;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]