-
Notifications
You must be signed in to change notification settings - Fork 0
/
simdsampling.h
118 lines (98 loc) · 4.27 KB
/
simdsampling.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef SIMD_SAMPLING_H
#define SIMD_SAMPLING_H
#ifndef SIMD_SAMPLING_API
#define SIMD_SAMPLING_API
#endif
#include <x86intrin.h>
#include "macros.h"
#ifdef __cplusplus
#include <cstdint>
#include <stdexcept>
#include <string>
#include <type_traits>
#else
#include <stdint.h>
#endif
#define LIB_SIMDSAMPLING_MAJOR 0
#define LIB_SIMDSAMPLING_MINOR 3
#define LIB_SIMDSAMPLING_REVISION 1
#define LIB_SIMDSAMPLING_VERSION ((LIB_SIMDSAMPLING_MAJOR << 16) | (LIB_SIMDSAMPLING_MINOR << 8)| LIB_SIMDSAMPLING_REVISION)
#ifndef SIMD_SAMPLING_HIGH_PRECISION
#define SIMD_SAMPLING_HIGH_PRECISION 1
#endif
enum SampleFmt {
WITH_REPLACEMENT = 1,
USE_EXPONENTIAL_SKIPS = 2,
NEITHER = 0,
BOTH = WITH_REPLACEMENT | USE_EXPONENTIAL_SKIPS
};
#ifdef __cplusplus
extern "C" {
#endif
SIMD_SAMPLING_API uint64_t fsimd_sample(const float *weights, size_t n, uint64_t seed, enum SampleFmt fmt);
SIMD_SAMPLING_API uint64_t dsimd_sample(const double *weights, size_t n, uint64_t seed, enum SampleFmt fmt);
SIMD_SAMPLING_API int fsimd_sample_k(const float *weights, size_t n, int k, uint64_t *ret, uint64_t seed, enum SampleFmt fmt);
SIMD_SAMPLING_API int dsimd_sample_k(const double *weights, size_t n, int k, uint64_t *ret, uint64_t seed, enum SampleFmt fmt);
// Return value: the number of selected elements; min(n, k)
// uint64_t *ret: pointer to which to write selected elements
SIMD_SAMPLING_API int simd_sample_get_version();
SIMD_SAMPLING_API int simd_sample_get_major_version();
SIMD_SAMPLING_API int simd_sample_get_minor_version();
SIMD_SAMPLING_API int simd_sample_get_revision_version();
#ifdef __cplusplus
} // extern C
#include <vector>
namespace reservoir_simd {
using std::uint64_t;
// Sample 1
template<typename FT>
inline uint64_t sample(const FT *weights, size_t n, uint64_t seed=0, enum SampleFmt fmt=NEITHER) {
throw std::runtime_error(std::string("SIMD Sampling not implemented for type ") + __PRETTY_FUNCTION__);
}
template<> inline uint64_t sample<double>(const double *weights, size_t n, uint64_t seed, enum SampleFmt fmt) {
return dsimd_sample(weights, n, seed, fmt);
}
template<> inline uint64_t sample<float>(const float *weights, size_t n, uint64_t seed, enum SampleFmt fmt) {
return fsimd_sample(weights, n, seed, fmt);
}
template<typename Container, typename=typename std::enable_if<!std::is_pointer<Container>::value>::type>
static INLINE uint64_t sample(const Container &x, uint64_t seed=0, enum SampleFmt fmt=NEITHER) {
return sample(x.data(), x.size(), seed, fmt);
}
// Sample k
template<typename FT>
inline std::vector<uint64_t> sample_k(const FT *weights, size_t n, int k, uint64_t seed=0, enum SampleFmt fmt=NEITHER) {
throw std::runtime_error(std::string("SIMD Sampling not implemented for type ") + __PRETTY_FUNCTION__);
}
template<> inline std::vector<uint64_t> sample_k<double>(const double *weights, size_t n, int k, uint64_t seed, enum SampleFmt fmt) {
std::vector<uint64_t> ret(k);
int kret = dsimd_sample_k(weights, n, k, ret.data(), seed, fmt);
if(kret != k) {
std::fprintf(stderr, "Return %u vs %u items\n", kret, k);
ret.resize(kret);
}
return ret;
}
template<> inline std::vector<uint64_t> sample_k<float>(const float *weights, size_t n, int k, uint64_t seed, enum SampleFmt fmt) {
std::vector<uint64_t> ret(k);
int kret = fsimd_sample_k(weights, n, k, ret.data(), seed, fmt);
if(kret != k) ret.resize(kret);
return ret;
}
template<typename Container, typename=typename std::enable_if<!std::is_pointer<Container>::value>::type>
static INLINE std::vector<uint64_t> sample_k(const Container &x, int k, uint64_t seed=0, enum SampleFmt fmt=NEITHER) {
return sample_k(x.data(), x.size(), k, seed, fmt);
}
template<typename T>
INLINE int sample_k(const T *weights, size_t n, int k, uint64_t *ret, uint64_t seed=0, enum SampleFmt fmt=NEITHER) {
throw std::runtime_error("Not Implemented");
}
template<> inline int sample_k<double>(const double *weights, size_t n, int k, uint64_t *ret, uint64_t seed, enum SampleFmt fmt) {
return dsimd_sample_k(weights, n, k, ret, seed, fmt);
}
template<> inline int sample_k<float>(const float *weights, size_t n, int k, uint64_t *ret, uint64_t seed, enum SampleFmt fmt) {
return fsimd_sample_k(weights, n, k, ret, seed, fmt);
}
} // namespace reservoir_simd
#endif // ifdef __cplusplus
#endif