Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize gcd for array and scalar case by avoiding make_scalar_function where has unnecessary conversion between scalar and array #14834

Merged
merged 6 commits into from
Feb 25, 2025

Conversation

jayzhan211
Copy link
Contributor

Which issue does this PR close?

  • Closes #.

Rationale for this change

make_scalar_function convert scalar to array and call function kernel. However, we don't need to convert to array and can directly compute on it. This improve the gcd performance in array vs scalar case

What changes are included in this PR?

Are these changes tested?

Are there any user-facing changes?

@github-actions github-actions bot added sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Feb 23, 2025
@jayzhan211
Copy link
Contributor Author

Gnuplot not found, using plotters backend
Benchmarking gcd both array: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.5s, enable flat sampling, or reduce sample count to 50.
gcd both array          time:   [1.4799 ms 1.4826 ms 1.4853 ms]
                        change: [+1.1198% +1.3952% +1.6734%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Benchmarking gcd array and scalar: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 8.9s, enable flat sampling, or reduce sample count to 50.
gcd array and scalar    time:   [1.7456 ms 1.7486 ms 1.7519 ms]
                        change: [-4.8528% -4.6518% -4.4540%] (p = 0.00 < 0.05)
                        Performance has improved.

gcd both scalar         time:   [23.373 ns 23.431 ns 23.487 ns]
                        change: [-93.342% -93.306% -93.272%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 18 outliers among 100 measurements (18.00%)
  5 (5.00%) low severe
  5 (5.00%) low mild
  5 (5.00%) high mild
  3 (3.00%) high severe

@jayzhan211 jayzhan211 marked this pull request as draft February 23, 2025 06:24
@jayzhan211 jayzhan211 marked this pull request as ready for review February 23, 2025 07:14
Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jayzhan211 -- look like a nice improvement to me

Comment on lines 115 to 127
fn compute_gcd_for_arrays(a: &ArrayRef, b: &ArrayRef) -> Result<ColumnarValue> {
let result: Result<Int64Array> = a
.as_primitive::<Int64Type>()
.iter()
.zip(b.as_primitive::<Int64Type>().iter())
.map(|(a, b)| match (a, b) {
(Some(a), Some(b)) => Ok(Some(compute_gcd(a, b)?)),
_ => Ok(None),
})
.collect();

result.map(|arr| ColumnarValue::Array(Arc::new(arr) as ArrayRef))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use try_binary and make it even faster:

Suggested change
fn compute_gcd_for_arrays(a: &ArrayRef, b: &ArrayRef) -> Result<ColumnarValue> {
let result: Result<Int64Array> = a
.as_primitive::<Int64Type>()
.iter()
.zip(b.as_primitive::<Int64Type>().iter())
.map(|(a, b)| match (a, b) {
(Some(a), Some(b)) => Ok(Some(compute_gcd(a, b)?)),
_ => Ok(None),
})
.collect();
result.map(|arr| ColumnarValue::Array(Arc::new(arr) as ArrayRef))
}
fn compute_gcd_for_arrays(a: &ArrayRef, b: &ArrayRef) -> Result<ColumnarValue> {
let result: Result<Int64Array> = a
.as_primitive::<Int64Type>()
.iter()
.zip(b.as_primitive::<Int64Type>().iter())
.map(|(a, b)| match (a, b) {
(Some(a), Some(b)) => Ok(Some(compute_gcd(a, b)?)),
_ => Ok(None),
})
.collect();
result.map(|arr| ColumnarValue::Array(Arc::new(arr) as ArrayRef))
}

I'll run some quick numbers with your new benchmark.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With my proposal the two array version seems to go 25% faster than this PR. Here is a PR with that improvement:

Gnuplot not found, using plotters backend
Benchmarking gcd both array: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.9s, enable flat sampling, or reduce sample count to 60.
gcd both array          time:   [1.1940 ms 1.2007 ms 1.2081 ms]
                        change: [-27.574% -27.080% -26.470%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
  6 (6.00%) high mild
  3 (3.00%) high severe

gcd array and scalar    time:   [1.9644 ms 1.9705 ms 1.9781 ms]
                        change: [-1.3293% -0.9077% -0.4670%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) high mild
  3 (3.00%) high severe

gcd both scalar         time:   [26.094 ns 26.253 ns 26.467 ns]
                        change: [-1.1099% -0.6987% -0.2362%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

Use try_binary to make gcd even faster
b.len()
);
}
try_binary(a, b, compute_gcd)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try_binary actually did the length check

@jayzhan211 jayzhan211 merged commit f1f6e5e into apache:main Feb 25, 2025
26 checks passed
@jayzhan211 jayzhan211 deleted the opt-gcd branch February 25, 2025 14:39
@jayzhan211
Copy link
Contributor Author

Thanks @alamb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
functions Changes to functions implementation sqllogictest SQL Logic Tests (.slt)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants