From: Joel Jacobson <joel@compiler.org>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Optimize numeric multiplication for one and two base-NBASE digit multiplicands.
Date: Mon, 01 Jul 2024 08:04:06 +0200
Message-ID: <44d2ffca-d560-4919-b85a-4d07060946aa@app.fastmail.com> (raw)
Hello hackers,
Attached patch introduces an optimization of mul_var() in numeric.c, targeting cases where the multiplicands consist of only one or two base-NBASE digits. Such small multiplicands can fit into an int64 and thus be computed directly, resulting in a significant performance improvement, between 26% - 34% benchmarked on Intel Core i9-14900K.
This optimization is similar to commit d1b307eef2, that also targeted one and two base-NBASE digit operands, but optimized div_var().
Regards,
Joel
Attachments:0001-optimize-numeric-mul_var-small-factors.patch (application/octet-stream, 1.8K) download
From 070bca416c0a78f4ce32a25c1225e820c820498a Mon Sep 17 00:00:00 2001
From: Joel Jakobsson <github@compiler.org>
Date: Mon, 1 Jul 2024 07:44:46 +0200
Subject: [PATCH] Optimize numeric multiplication for up to two base-NBASE
digit operands
---
src/backend/utils/adt/numeric.c | 52 +++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.cindex 5510a203b0..d6c9017a35 100644--- a/src/backend/utils/adt/numeric.c+++ b/src/backend/utils/adt/numeric.c@@ -8747,6 +8747,58 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
return;
}
+ /*+ * If var1 and var2 are just one or two digits, their product will fit in+ * an int64 can be computed directly, which is significantly faster.+ */+ if (var2ndigits <= 2)+ {+ int64 product;++ switch (var1ndigits)+ {+ case 1:+ product = var1digits[0];+ break;+ case 2:+ product = var1digits[0] * NBASE + var1digits[1];+ break;+ }++ switch (var2ndigits)+ {+ case 1:+ product *= var2digits[0];+ break;+ case 2:+ product *= var2digits[0] * NBASE + var2digits[1];+ break;+ }++ alloc_var(result, res_ndigits);+ res_digits = result->digits;+ for (i = res_ndigits - 1; i >= 0; i--)+ {+ res_digits[i] = product % NBASE;+ product /= NBASE;+ }+ Assert(product == 0);++ /*+ * Finally, round the result to the requested precision.+ */+ result->weight = res_weight;+ result->sign = res_sign;++ /* Round to target rscale (and set result->dscale) */+ round_var(result, rscale);++ /* Strip leading and trailing zeroes */+ strip_var(result);++ return;+ }+
/*
* We do the arithmetic in an array "dig[]" of signed int's. Since
* INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
--
2.45.1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: joel@compiler.org
Subject: Re: Optimize numeric multiplication for one and two base-NBASE digit multiplicands.
In-Reply-To: <44d2ffca-d560-4919-b85a-4d07060946aa@app.fastmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox