UnaryLogicalFunctions improve performance using dynamic dispatch

This commit is contained in:
Maksim Kita 2022-06-14 17:30:11 +02:00
parent 7f6d328760
commit dc2e117cce
2 changed files with 59 additions and 41 deletions

View File

@ -13,6 +13,7 @@
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/FunctionUnaryArithmetic.h>
#include <Common/FieldVisitors.h>
#include <algorithm>
@ -50,17 +51,15 @@ MutableColumnPtr buildColumnFromTernaryData(const UInt8Container & ternary_data,
const size_t rows_count = ternary_data.size();
auto new_column = ColumnUInt8::create(rows_count);
std::transform(
ternary_data.cbegin(), ternary_data.cend(), new_column->getData().begin(),
[](const auto x) { return x == Ternary::True; });
for (size_t i = 0; i < rows_count; ++i)
new_column->getData()[i] = (ternary_data[i] == Ternary::True);
if (!make_nullable)
return new_column;
auto null_column = ColumnUInt8::create(rows_count);
std::transform(
ternary_data.cbegin(), ternary_data.cend(), null_column->getData().begin(),
[](const auto x) { return x == Ternary::Null; });
for (size_t i = 0; i < rows_count; ++i)
null_column->getData()[i] = (ternary_data[i] == Ternary::Null);
return ColumnNullable::create(std::move(new_column), std::move(null_column));
}
@ -68,13 +67,14 @@ MutableColumnPtr buildColumnFromTernaryData(const UInt8Container & ternary_data,
template <typename T>
bool tryConvertColumnToBool(const IColumn * column, UInt8Container & res)
{
const auto col = checkAndGetColumn<ColumnVector<T>>(column);
if (!col)
const auto column_typed = checkAndGetColumn<ColumnVector<T>>(column);
if (!column_typed)
return false;
std::transform(
col->getData().cbegin(), col->getData().cend(), res.begin(),
[](const auto x) { return !!x; });
auto & data = column_typed->getData();
size_t data_size = data.size();
for (size_t i = 0; i < data_size; ++i)
res[i] = static_cast<bool>(data[i]);
return true;
}
@ -99,7 +99,7 @@ bool extractConstColumns(ColumnRawPtrs & in, UInt8 & res, Func && func)
{
bool has_res = false;
for (int i = static_cast<int>(in.size()) - 1; i >= 0; --i)
for (Int64 i = static_cast<Int64>(in.size()) - 1; i >= 0; --i)
{
UInt8 x;
@ -458,7 +458,9 @@ ColumnPtr basicExecuteImpl(ColumnRawPtrs arguments, size_t input_rows_count)
for (const IColumn * column : arguments)
{
if (const auto * uint8_column = checkAndGetColumn<ColumnUInt8>(column))
{
uint8_args.push_back(uint8_column);
}
else
{
auto converted_column = ColumnUInt8::create(input_rows_count);
@ -596,14 +598,14 @@ ColumnPtr FunctionAnyArityLogical<Impl, Name>::executeShortCircuit(ColumnsWithTy
if (nulls)
applyTernaryLogic<Name>(mask, *nulls);
MutableColumnPtr res = ColumnUInt8::create();
typeid_cast<ColumnUInt8 *>(res.get())->getData() = std::move(mask);
auto res = ColumnUInt8::create();
res->getData() = std::move(mask);
if (!nulls)
return res;
MutableColumnPtr bytemap = ColumnUInt8::create();
typeid_cast<ColumnUInt8 *>(bytemap.get())->getData() = std::move(*nulls);
auto bytemap = ColumnUInt8::create();
bytemap->getData() = std::move(*nulls);
return ColumnNullable::create(std::move(res), std::move(bytemap));
}
@ -692,29 +694,14 @@ ColumnPtr FunctionAnyArityLogical<Impl, Name>::getConstantResultForNonConstArgum
return result_column;
}
template <typename A, typename Op>
struct UnaryOperationImpl
{
using ResultType = typename Op::ResultType;
using ArrayA = typename ColumnVector<A>::Container;
using ArrayC = typename ColumnVector<ResultType>::Container;
static void NO_INLINE vector(const ArrayA & a, ArrayC & c)
{
std::transform(
a.cbegin(), a.cend(), c.begin(),
[](const auto x) { return Op::apply(x); });
}
};
template <template <typename> class Impl, typename Name>
DataTypePtr FunctionUnaryLogical<Impl, Name>::getReturnTypeImpl(const DataTypes & arguments) const
{
if (!isNativeNumber(arguments[0]))
throw Exception("Illegal type ("
+ arguments[0]->getName()
+ ") of argument of function " + getName(),
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Illegal type ({}) of argument of function {}",
arguments[0]->getName(),
getName());
return isBool(arguments[0]) ? DataTypeFactory::instance().get("Bool") : std::make_shared<DataTypeUInt8>();
}
@ -724,10 +711,9 @@ ColumnPtr functionUnaryExecuteType(const ColumnsWithTypeAndName & arguments)
{
if (auto col = checkAndGetColumn<ColumnVector<T>>(arguments[0].column.get()))
{
auto col_res = ColumnUInt8::create();
auto col_res = ColumnUInt8::create(col->getData().size());
auto & vec_res = col_res->getData();
typename ColumnUInt8::Container & vec_res = col_res->getData();
vec_res.resize(col->getData().size());
UnaryOperationImpl<T, Impl<T>>::vector(col->getData(), vec_res);
return col_res;
@ -750,9 +736,10 @@ ColumnPtr FunctionUnaryLogical<Impl, Name>::executeImpl(const ColumnsWithTypeAnd
|| (res = functionUnaryExecuteType<Impl, Int64>(arguments))
|| (res = functionUnaryExecuteType<Impl, Float32>(arguments))
|| (res = functionUnaryExecuteType<Impl, Float64>(arguments))))
throw Exception("Illegal column " + arguments[0].column->getName()
+ " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN);
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of argument of function {}",
arguments[0].column->getName(),
getName());
return res;
}

View File

@ -0,0 +1,31 @@
<test>
<substitutions>
<substitution>
<name>func</name>
<values>
<value>not</value>
</values>
</substitution>
<substitution>
<name>expr</name>
<values>
<value>number</value>
<value>toUInt32(number)</value>
<value>toUInt16(number)</value>
<value>toUInt8(number)</value>
<value>toInt64(number)</value>
<value>toInt32(number)</value>
<value>toInt16(number)</value>
<value>toInt8(number)</value>
<value>toFloat64(number)</value>
<value>toFloat32(number)</value>
</values>
</substitution>
</substitutions>
<query>SELECT {func}({expr}) FROM numbers(1000000000) FORMAT Null</query>
</test>