mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
More safe CPU dispatching
This commit is contained in:
parent
cdbc9d9fa0
commit
b00c66cb36
@ -1,5 +1,7 @@
|
|||||||
configure_file(config_functions.h.in ${ConfigIncludePath}/config_functions.h)
|
configure_file(config_functions.h.in ${ConfigIncludePath}/config_functions.h)
|
||||||
|
|
||||||
|
add_subdirectory(divide)
|
||||||
|
|
||||||
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
||||||
add_headers_and_sources(clickhouse_functions .)
|
add_headers_and_sources(clickhouse_functions .)
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ target_link_libraries(clickhouse_functions
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
boost::filesystem
|
boost::filesystem
|
||||||
libdivide
|
divide_impl
|
||||||
)
|
)
|
||||||
|
|
||||||
if (OPENSSL_CRYPTO_LIBRARY)
|
if (OPENSSL_CRYPTO_LIBRARY)
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
#include <Functions/FunctionFactory.h>
|
#include <Functions/FunctionFactory.h>
|
||||||
#include <Functions/FunctionBinaryArithmetic.h>
|
#include <Functions/FunctionBinaryArithmetic.h>
|
||||||
#include <Functions/TargetSpecific.h>
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#include "divide/divide.h"
|
||||||
#define LIBDIVIDE_SSE2 1
|
|
||||||
#define LIBDIVIDE_AVX2 1
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang attribute push(__attribute__((target("sse,sse2,sse3,ssse3,sse4,popcnt,avx,avx2"))), apply_to=function)
|
|
||||||
#else
|
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,avx,avx2,tune=native")
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libdivide.h>
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang attribute pop
|
|
||||||
#else
|
|
||||||
#pragma GCC pop_options
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -37,83 +16,6 @@ namespace
|
|||||||
|
|
||||||
/// Optimizations for integer division by a constant.
|
/// Optimizations for integer division by a constant.
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
|
|
||||||
DECLARE_DEFAULT_CODE (
|
|
||||||
template <typename A, typename B, typename ResultType>
|
|
||||||
void divideImpl(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
|
|
||||||
{
|
|
||||||
libdivide::divider<A> divider(b);
|
|
||||||
const A * a_end = a_pos + size;
|
|
||||||
|
|
||||||
static constexpr size_t values_per_simd_register = 16 / sizeof(A);
|
|
||||||
const A * a_end_simd = a_pos + size / values_per_simd_register * values_per_simd_register;
|
|
||||||
|
|
||||||
while (a_pos < a_end_simd)
|
|
||||||
{
|
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c_pos),
|
|
||||||
_mm_loadu_si128(reinterpret_cast<const __m128i *>(a_pos)) / divider);
|
|
||||||
|
|
||||||
a_pos += values_per_simd_register;
|
|
||||||
c_pos += values_per_simd_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (a_pos < a_end)
|
|
||||||
{
|
|
||||||
*c_pos = *a_pos / divider;
|
|
||||||
++a_pos;
|
|
||||||
++c_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
DECLARE_AVX2_SPECIFIC_CODE (
|
|
||||||
template <typename A, typename B, typename ResultType>
|
|
||||||
void divideImpl(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
|
|
||||||
{
|
|
||||||
libdivide::divider<A> divider(b);
|
|
||||||
const A * a_end = a_pos + size;
|
|
||||||
|
|
||||||
static constexpr size_t values_per_simd_register = 32 / sizeof(A);
|
|
||||||
const A * a_end_simd = a_pos + size / values_per_simd_register * values_per_simd_register;
|
|
||||||
|
|
||||||
while (a_pos < a_end_simd)
|
|
||||||
{
|
|
||||||
_mm256_storeu_si256(reinterpret_cast<__m256i *>(c_pos),
|
|
||||||
_mm256_loadu_si256(reinterpret_cast<const __m256i *>(a_pos)) / divider);
|
|
||||||
|
|
||||||
a_pos += values_per_simd_register;
|
|
||||||
c_pos += values_per_simd_register;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (a_pos < a_end)
|
|
||||||
{
|
|
||||||
*c_pos = *a_pos / divider;
|
|
||||||
++a_pos;
|
|
||||||
++c_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <typename A, typename B, typename ResultType>
|
|
||||||
void divideImpl(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
|
|
||||||
{
|
|
||||||
libdivide::divider<A> divider(b);
|
|
||||||
const A * a_end = a_pos + size;
|
|
||||||
|
|
||||||
while (a_pos < a_end)
|
|
||||||
{
|
|
||||||
*c_pos = *a_pos / divider;
|
|
||||||
++a_pos;
|
|
||||||
++c_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
struct DivideIntegralByConstantImpl
|
struct DivideIntegralByConstantImpl
|
||||||
: BinaryOperation<A, B, DivideIntegralImpl<A, B>>
|
: BinaryOperation<A, B, DivideIntegralImpl<A, B>>
|
||||||
@ -164,20 +66,7 @@ struct DivideIntegralByConstantImpl
|
|||||||
if (unlikely(static_cast<A>(b) == 0))
|
if (unlikely(static_cast<A>(b) == 0))
|
||||||
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
||||||
|
|
||||||
#if USE_MULTITARGET_CODE
|
divideImpl(a_pos, b, c_pos, size);
|
||||||
if (isArchSupported(TargetArch::AVX2))
|
|
||||||
{
|
|
||||||
TargetSpecific::AVX2::divideImpl(a_pos, b, c_pos, size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#if __x86_64__
|
|
||||||
TargetSpecific::Default::divideImpl(a_pos, b, c_pos, size);
|
|
||||||
#else
|
|
||||||
divideImpl(a_pos, b, c_pos, size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user