Commit b86a15d9 authored by s_kleplj's avatar s_kleplj
Browse files

.

parent 74d4d707
...@@ -3,52 +3,254 @@ ...@@ -3,52 +3,254 @@
#include <cstdint> #include <cstdint>
#include <utility> #include <utility>
#include <limits>
#include <vector>
#include <immintrin.h>
/////////////////////////////// ///////////////////////////////
namespace bsearchsol { namespace bsearchsol {
using data_element = std::int32_t; using data_element = std::int32_t;
template< typename policy>
class bsearch_outer;
struct policy_scalar {
};
struct policy_sse {
};
struct policy_avx {
};
struct policy_avx512 {
};
template<typename policy>
struct policy_data_base {
using data_packed = std::size_t;
};
template<>
struct policy_data_base<policy_sse> {
using data_packed = __m128i;
};
#ifdef USE_AVX
template<>
struct policy_data_base<policy_avx> {
using data_packed = __m256i;
};
#endif
#ifdef USE_AVX512
template<>
struct policy_data_base<policy_avx512> {
using data_packed = std::uint32_t[16];
};
#endif
template<typename policy>
struct policy_data {
using data_packed = typename policy_data_base<policy>::data_packed;
static constexpr std::size_t pack_size = sizeof(data_packed) / sizeof(data_element);
};
template<typename policy, std::size_t size>
struct get_jump_long {
private:
static constexpr std::size_t pack_size = policy_data<policy>::pack_size;
public:
using value_type = std::size_t;
static constexpr value_type value =
size > pack_size * pack_size
? get_jump_long<policy, size / pack_size>::value * pack_size + pack_size
: 0;
};
template< typename policy> template<typename policy, std::size_t size>
class bsearch_inner { struct get_jump {
private:
static constexpr std::size_t pack_size = policy_data<policy>::pack_size;
public:
using value_type = std::size_t;
static constexpr value_type value =
size > pack_size * pack_size
? get_jump_long<policy, size / pack_size>::value * pack_size + pack_size
: size / pack_size;
};
template<typename policy, std::size_t size>
struct get_real_jump {
private:
public:
using value_type = std::size_t;
static constexpr value_type value = get_jump<policy, size>::value / policy_data<policy>::pack_size;
};
template<typename policy, std::size_t size>
struct next_size {
private:
static constexpr std::size_t pack_size = policy_data<policy>::pack_size;
public:
using value_type = std::size_t;
static constexpr value_type value =
size > pack_size
? size / pack_size
: 1;
};
constexpr std::size_t i = get_jump<policy_avx512, 8192>::value;
template<typename policy>
class bsearch_inner {
using data_packed = typename policy_data<policy>::data_packed;
static constexpr std::size_t pack_size = policy_data<policy>::pack_size;
public: public:
bsearch_inner(const data_element* data, std::size_t size) bsearch_inner(const data_element* data, std::size_t size)
: structure{}
, isize{size}
{ {
append_data(data, isize / pack_size, isize);
for (std::size_t i = 0; i < isize; ++i) {
structure.emplace_back(data[i]);
}
} }
};
template< typename policy> void append_data(const data_element* data, std::size_t step, std::size_t count)
class bsearch_outer { {
public: if (step > 1) {
for (std::size_t i = step; i <= count; i += step) {
structure.emplace_back(data[i - 1]);
}
for (std::size_t i = 0; i <= count; i += step) {
append_data(data + i, step / pack_size, step);
}
}
}
std::size_t find(const data_element num) const
{
switch (isize)
{
case 64:
return _find<64>(0, num);
break;
case 256:
return _find<256>(0, num);
break;
case 1024:
return _find<1024>(0, num);
break;
case 4096:
return _find<4096>(0, num);
break;
case 16384:
return _find<16384>(0, num);
break;
case 262144:
return _find<262144>(0, num);
break;
case 1048576:
return _find<1048576>(0, num);
break;
}
return 0;
}
const std::size_t &size() const { return isize; }
private:
template<std::size_t size>
std::size_t _find(const std::size_t offset, const data_element num) const;
std::vector<data_element> structure;
std::size_t isize;
};
template<typename policy>
template<std::size_t size>
std::size_t bsearch_inner<policy>::_find(const std::size_t offset, const data_element num) const
{
return 0;
}
static const __m128i popcount_mask = _mm_set1_epi8(0x0F);
static const __m128i popcount_table = _mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
static inline __m128i popcnt8(__m128i n) {
const __m128i pcnt0 = _mm_shuffle_epi8(popcount_table, _mm_and_si128(n, popcount_mask));
const __m128i pcnt1 = _mm_shuffle_epi8(popcount_table, _mm_and_si128(_mm_srli_epi16(n, 4), popcount_mask));
return _mm_add_epi8(pcnt0, pcnt1);
}
template<>
template<std::size_t size>
inline std::size_t bsearch_inner<policy_sse>::_find(const std::size_t offset, const data_element num) const
{
auto tmp = _mm_cmplt_epi32(_mm_loadu_si128((data_packed*)&structure[offset]), _mm_set1_epi32(num));
return _find<next_size<policy_sse,size>::value>(offset + pack_size+ (__builtin_popcount(_mm_movemask_epi8(tmp)) >> 2) * get_jump<policy_sse,size>::value, num);
}
template<>
template<>
inline std::size_t bsearch_inner<policy_sse>::_find<1>(const std::size_t offset, const data_element num) const
{
auto tmp = _mm_cmplt_epi32(_mm_loadu_si128((data_packed*)&structure[offset]), _mm_set1_epi32(num));
return __builtin_popcount(_mm_movemask_epi8(tmp)) >> 2;
}
template<std::size_t base, std::size_t exp>
struct pow {
using value_type = std::size_t;
static constexpr value_type value = pow<base, exp - 1>::value * base;
};
template<std::size_t base>
struct pow<base, 0> {
using value_type = std::size_t;
static constexpr value_type value = 1;
};
template<typename policy>
class bsearch_outer {
using data_packed = typename policy_data<policy>::data_packed;
static constexpr std::size_t pack_size = sizeof(data_packed) / sizeof(data_element);
public:
bsearch_outer(const bsearch_inner< policy>& inner, std::size_t osize) bsearch_outer(const bsearch_inner< policy>& inner, std::size_t osize)
: inner_{inner}
, osize_{osize}
, buckets_(inner.size() + 1)
{ {
} }
void bucketize(const data_element* data) // size of data is osize void bucketize(const data_element* data) // size of data is osize
{ {
for (
const data_element* p_data = data + osize_;
--p_data != data;
) {
buckets_[inner_.find(*p_data)].emplace_back(*p_data);
}
} }
using bucket_rv = std::pair< const data_element*, std::size_t>; using bucket_rv = std::pair< const data_element*, std::size_t>;
bucket_rv bucket(std::size_t k) const bucket_rv bucket(std::size_t k) const
{ {
return bucket_rv(0, 0); // return reference to bucket contents return bucket_rv(buckets_[k].data(), buckets_[k].size()); // return reference to bucket contents
} }
};
struct policy_scalar {
};
struct policy_sse { const bsearch_inner<policy>& inner_;
}; std::vector<std::vector<data_element>> buckets_;
const std::size_t osize_;
struct policy_avx { };
};
struct policy_avx512 {
};
} }
#endif #endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment