mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-04 05:22:17 +00:00
Faster 256-bit multiplication (#15418)
This commit is contained in:
parent
86cfc6f914
commit
4fd1db73a1
@ -436,7 +436,54 @@ private:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr static auto multiply(const integer<Bits, Signed> & lhs, const T & rhs)
|
||||
constexpr static integer<Bits, Signed>
|
||||
multiply(const integer<Bits, Signed> & lhs, const T & rhs)
|
||||
{
|
||||
if constexpr (Bits == 256 && sizeof(base_type) == 8)
|
||||
{
|
||||
/// @sa https://github.com/abseil/abseil-cpp/blob/master/absl/numeric/int128.h
|
||||
using HalfType = unsigned __int128;
|
||||
|
||||
HalfType a01 = (HalfType(lhs.items[little(1)]) << 64) + lhs.items[little(0)];
|
||||
HalfType a23 = (HalfType(lhs.items[little(3)]) << 64) + lhs.items[little(2)];
|
||||
HalfType a0 = lhs.items[little(0)];
|
||||
HalfType a1 = lhs.items[little(1)];
|
||||
|
||||
HalfType b01 = rhs;
|
||||
uint64_t b0 = b01;
|
||||
uint64_t b1 = 0;
|
||||
HalfType b23 = 0;
|
||||
if constexpr (sizeof(T) > 8)
|
||||
b1 = b01 >> 64;
|
||||
if constexpr (sizeof(T) > 16)
|
||||
b23 = (HalfType(rhs.items[little(3)]) << 64) + rhs.items[little(2)];
|
||||
|
||||
HalfType r23 = a23 * b01 + a01 * b23 + a1 * b1;
|
||||
HalfType r01 = a0 * b0;
|
||||
HalfType r12 = (r01 >> 64) + (r23 << 64);
|
||||
HalfType r12_x = a1 * b0;
|
||||
|
||||
integer<Bits, Signed> res;
|
||||
res.items[little(0)] = r01;
|
||||
res.items[little(3)] = r23 >> 64;
|
||||
|
||||
if constexpr (sizeof(T) > 8)
|
||||
{
|
||||
HalfType r12_y = a0 * b1;
|
||||
r12_x += r12_y;
|
||||
if (r12_x < r12_y)
|
||||
++res.items[little(3)];
|
||||
}
|
||||
|
||||
r12 += r12_x;
|
||||
if (r12 < r12_x)
|
||||
++res.items[little(3)];
|
||||
|
||||
res.items[little(1)] = r12;
|
||||
res.items[little(2)] = r12 >> 64;
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
integer<Bits, Signed> res{};
|
||||
#if 1
|
||||
@ -477,6 +524,7 @@ private:
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr static integer<Bits, Signed> operator_unary_tilda(const integer<Bits, Signed> & lhs) noexcept
|
||||
|
15
tests/performance/bigint_arithm.xml
Normal file
15
tests/performance/bigint_arithm.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<test>
|
||||
<settings>
|
||||
<max_memory_usage>10G</max_memory_usage>
|
||||
</settings>
|
||||
|
||||
<query>SELECT toInt128(number) + number FROM numbers_mt(1000000000) FORMAT Null</query>
|
||||
<query>SELECT toInt128(number) - number FROM numbers_mt(1000000000) FORMAT Null</query>
|
||||
<query>SELECT toInt128(number) * number FROM numbers_mt(1000000000) FORMAT Null</query>
|
||||
<query>SELECT toInt128(number) / number FROM numbers_mt(1000000000) FORMAT Null</query>
|
||||
|
||||
<query>SELECT toInt256(number) + number FROM numbers_mt(100000000) FORMAT Null</query>
|
||||
<query>SELECT toInt256(number) - number FROM numbers_mt(100000000) FORMAT Null</query>
|
||||
<query>SELECT toInt256(number) * number FROM numbers_mt(100000000) FORMAT Null</query>
|
||||
<query>SELECT intDiv(toInt256(number + 1), number + 1) FROM numbers_mt(100000000) FORMAT Null</query>
|
||||
</test>
|
@ -0,0 +1 @@
|
||||
0
|
4
tests/queries/0_stateless/01485_256_bit_multiply.sql
Normal file
4
tests/queries/0_stateless/01485_256_bit_multiply.sql
Normal file
@ -0,0 +1,4 @@
|
||||
select count() from
|
||||
(
|
||||
select toInt128(number) * number x, toInt256(number) * number y from numbers_mt(100000000) where x != y
|
||||
);
|
Loading…
Reference in New Issue
Block a user