mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-09 17:14:47 +00:00
UnaryLogicalFunctions improve performance using dynamic dispatch
This commit is contained in:
parent
7f6d328760
commit
dc2e117cce
@ -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;
|
||||
}
|
||||
|
31
tests/performance/unary_logical_functions.xml
Normal file
31
tests/performance/unary_logical_functions.xml
Normal 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>
|
Loading…
Reference in New Issue
Block a user