Skip to content

Commit 4ba3205

Browse files
Merge pull request #174 from rtosholdings/latest-v1.19.0
v1.19.0
2 parents e268556 + d7ea144 commit 4ba3205

36 files changed

+1574
-585
lines changed

.clang-format

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ Language: Cpp
33
# BasedOnStyle: GNU
44
AccessModifierOffset: -4
55
AlignAfterOpenBracket: Align
6-
AlignConsecutiveMacros: None
76
AlignConsecutiveAssignments: None
87
AlignConsecutiveBitFields: AcrossEmptyLinesAndComments
98
AlignConsecutiveDeclarations: None
9+
AlignConsecutiveMacros: None
1010
AlignEscapedNewlines: DontAlign
1111
AlignOperands: Align
1212
AlignTrailingComments: true
@@ -28,7 +28,6 @@ AttributeMacros:
2828
- __capability
2929
BinPackArguments: true
3030
BinPackParameters: true
31-
BreakBeforeBraces: Custom
3231
BraceWrapping:
3332
AfterCaseLabel: true
3433
AfterClass: true
@@ -50,7 +49,9 @@ BraceWrapping:
5049
SplitEmptyNamespace: true
5150
BreakBeforeBinaryOperators: None
5251
BreakBeforeConceptDeclarations: true
52+
BreakBeforeBraces: Custom
5353
BreakBeforeInheritanceComma: false
54+
BreakInheritanceList: BeforeColon
5455
BreakBeforeTernaryOperators: false
5556
BreakConstructorInitializersBeforeComma: true
5657
BreakConstructorInitializers: BeforeComma
@@ -72,8 +73,6 @@ ForEachMacros:
7273
- foreach
7374
- Q_FOREACH
7475
- BOOST_FOREACH
75-
StatementAttributeLikeMacros:
76-
- Q_EMIT
7776
IncludeBlocks: Preserve
7877
IncludeCategories:
7978
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
@@ -139,7 +138,7 @@ SpaceBeforeRangeBasedForLoopColon: true
139138
SpaceInEmptyBlock: false
140139
SpaceInEmptyParentheses: false
141140
SpacesBeforeTrailingComments: 1
142-
SpacesInAngles: false
141+
SpacesInAngles: Never
143142
SpacesInConditionalStatement: false
144143
SpacesInContainerLiterals: true
145144
SpacesInCStyleCastParentheses: false
@@ -151,6 +150,8 @@ SpacesInSquareBrackets: false
151150
SpaceBeforeSquareBrackets: false
152151
BitFieldColonSpacing: None
153152
Standard: Latest
153+
StatementAttributeLikeMacros:
154+
- Q_EMIT
154155
StatementMacros:
155156
- Q_UNUSED
156157
- QT_REQUIRE_VERSION

.github/workflows/native_sanity.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ jobs:
2121
strategy:
2222
matrix:
2323
os: [ubuntu-latest, windows-latest]
24-
python-version: ["3.10", "3.11"]
25-
numpy-version: [1.23]
24+
python-version: ["3.10", "3.11", "3.12"]
25+
numpy-version: [1.26]
2626
build-config: ["Debug", "Release"]
2727
steps:
2828
- uses: actions/checkout@v4

.github/workflows/python_package.yml

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ jobs:
2020
strategy:
2121
matrix:
2222
os: ["ubuntu-latest", "windows-2022"]
23-
python-version: ["3.10", "3.11"]
24-
numpy-version: [1.23]
23+
python-version: ["3.10", "3.11", "3.12"]
24+
numpy-version: [1.26]
2525
steps:
2626
- name: Checkout repo
2727
uses: actions/checkout@v4
@@ -85,13 +85,14 @@ jobs:
8585
shell: bash -l {0}
8686
strategy:
8787
matrix:
88-
os: [ubuntu-latest, windows-2022]
89-
python-version: ["3.10", "3.11"]
90-
numpy-version: [1.23]
91-
exclude:
92-
# only latest needed for sdist, so exlude all others
88+
os: [windows-2022]
89+
python-version: ["3.10", "3.11", "3.12"]
90+
numpy-version: [1.26]
91+
include:
92+
# only one python/numpy combo needed for sdist
9393
- os: ubuntu-latest
94-
python-version: "3.10"
94+
python-version: "3.12"
95+
numpy-version: 1.26
9596
steps:
9697
- name: Checkout repo
9798
uses: actions/checkout@v4
@@ -150,7 +151,14 @@ jobs:
150151
matrix:
151152
os: ["ubuntu-latest", "windows-2022"]
152153
python-version: ["3.10", "3.11"]
153-
numpy-version: [1.23, 1.24]
154+
numpy-version: [1.23, 1.24, 1.25, 1.26]
155+
include:
156+
- os: "ubuntu-latest"
157+
python-version: "3.12"
158+
numpy-version: "1.26"
159+
- os: "windows-2022"
160+
python-version: "3.12"
161+
numpy-version: "1.26"
154162
env:
155163
ANACONDA_USER: rtosholdings
156164
BUILD_VERSION: ${{needs.conda_build.outputs.build_version}}
@@ -214,7 +222,14 @@ jobs:
214222
matrix:
215223
os: [ubuntu-latest, windows-2022]
216224
python-version: ["3.10", "3.11"]
217-
numpy-version: [1.23, 1.24]
225+
numpy-version: [1.23, 1.24, 1.25, 1.26]
226+
include:
227+
- os: "ubuntu-latest"
228+
python-version: "3.12"
229+
numpy-version: "1.26"
230+
- os: "windows-2022"
231+
python-version: "3.12"
232+
numpy-version: "1.26"
218233
steps:
219234
- name: Checkout repo (sparse)
220235
uses: actions/checkout@v4

bench/riptide_bench/riptide_bench/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ set(TARGET_NAME riptide_bench)
33
set(CMAKE_VERBOSE_MAKEFILE on)
44

55
set(SOURCES main.cpp
6+
bench_groupby.cpp
67
bench_one_input.cpp
8+
bench_reduce.cpp
79
hash_linear_bench.cpp
810
memcmp_bench.cpp
911
bench_logging.cpp
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
2+
#include <benchmark/benchmark.h>
3+
#include "RipTide.h" // Required for MultiKey.h included from GroupBy.h
4+
#include "GroupBy.h"
5+
#include "numpy_traits.h"
6+
#include <random>
7+
8+
using namespace riptide::benchmark;
9+
10+
template <typename T>
11+
std::vector<T> uniform_random_vector(size_t length, T min, T max)
12+
{
13+
std::default_random_engine engine;
14+
std::uniform_int_distribution<T> distribution(min, max);
15+
16+
auto random = [&]
17+
{
18+
return distribution(engine);
19+
};
20+
21+
std::vector<T> result(length);
22+
std::generate(result.begin(), result.end(), random);
23+
return result;
24+
}
25+
26+
template <GB_FUNCTIONS function, NPY_TYPES TypeCode>
27+
static void BM_GroupByTwo(benchmark::State & state)
28+
{
29+
int64_t length = state.range(0);
30+
int64_t bins = state.range(1);
31+
32+
auto groupby = get_groupby_two_function(function, TypeCode);
33+
34+
// Allocate input/output/etc buffers
35+
std::vector<typename riptide::numpy_cpp_type<TypeCode>::type> input(length);
36+
std::vector<uint8_t> output(bins * groupby.output_type_size);
37+
std::vector<uint8_t> temp(bins * groupby.temp_type_size);
38+
std::vector<CountType> count(bins);
39+
40+
// Populate index vector to simulate real memory access patterns
41+
auto index = uniform_random_vector<IndexType>(length, 0, bins - 1);
42+
43+
for (auto _ : state)
44+
{
45+
groupby.function(input.data(), index.data(), count.data(), output.data(), length, 0, bins, -1, temp.data());
46+
}
47+
}
48+
49+
template <typename T>
50+
struct first_and_count
51+
{
52+
std::vector<T> first;
53+
std::vector<T> count;
54+
};
55+
56+
template <typename T>
57+
first_and_count<T> generate_first_and_count(int64_t length, int64_t bins)
58+
{
59+
// Groups are packed such that all elements in the same group are adjacent
60+
// Each entry is the index to the first element of that group
61+
auto first = uniform_random_vector<T>(bins, 0, length - 1);
62+
63+
// Sort it so that generating count is easier
64+
std::sort(first.begin(), first.end());
65+
// Set first entry to 0 so that we aren't missing items
66+
first[0] = 0;
67+
68+
// Each entry is the number of items in the group
69+
// We can just compute this by finding the difference between entries in first
70+
std::vector<T> count(bins);
71+
for (size_t i = 0; i < count.size() - 1; i++)
72+
count[i] = first[i + 1] - first[i];
73+
count.back() = length - first.back();
74+
75+
return { first, count };
76+
}
77+
78+
template <GB_FUNCTIONS function, NPY_TYPES TypeCode, int64_t funcParam = 0>
79+
static void BM_GroupByX(benchmark::State & state)
80+
{
81+
int64_t length = state.range(0);
82+
int64_t bins = state.range(1);
83+
84+
auto groupby = get_groupby_x_function(function, TypeCode);
85+
86+
// The values here don't matter
87+
std::vector<typename riptide::numpy_cpp_type<TypeCode>::type> input(length);
88+
std::vector<uint8_t> output;
89+
90+
if constexpr (function >= GB_ROLLING_SUM)
91+
// Rolling functions require that the output the same size as the input
92+
output = std::vector<uint8_t>(length * groupby.output_type_size);
93+
else
94+
// Other functions require the number of bins
95+
output = std::vector<uint8_t>(bins * groupby.output_type_size);
96+
97+
// Populate group, first and count to simulate real memory access patterns
98+
auto group = uniform_random_vector<IndexType>(length, 0, length - 1);
99+
auto [first, count] = generate_first_and_count<IndexType>(length, bins);
100+
101+
for (auto _ : state)
102+
{
103+
groupby.function(input.data(), group.data(), first.data(), count.data(), output.data(), 0, bins, length,
104+
groupby.output_type_size, funcParam);
105+
}
106+
}
107+
108+
static void GroupByArguments(benchmark::internal::Benchmark * b)
109+
{
110+
// Benchmark with 1 million values and 1000 groups
111+
b->Args({ 1000000, 1000 });
112+
}
113+
114+
#define BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_FUNCTION) \
115+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_INT8>)->Apply(GroupByArguments); \
116+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_INT16>)->Apply(GroupByArguments); \
117+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_INT32>)->Apply(GroupByArguments); \
118+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_INT64>)->Apply(GroupByArguments); \
119+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_UINT8>)->Apply(GroupByArguments); \
120+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_UINT16>)->Apply(GroupByArguments); \
121+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_UINT32>)->Apply(GroupByArguments); \
122+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_UINT64>)->Apply(GroupByArguments); \
123+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_FLOAT>)->Apply(GroupByArguments); \
124+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_DOUBLE>)->Apply(GroupByArguments); \
125+
BENCHMARK(BM_GroupByTwo<GB_FUNCTION, NPY_LONGDOUBLE>)->Apply(GroupByArguments);
126+
127+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_SUM);
128+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_MEAN);
129+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_MIN);
130+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_MAX);
131+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_VAR);
132+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_STD);
133+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANSUM);
134+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANMEAN);
135+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANMIN);
136+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANMAX);
137+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANVAR);
138+
BENCHMARK_GROUPBY_TWO_ALL_TYPES(GB_NANSTD);
139+
140+
// Parameters for GroupByX functions
141+
namespace
142+
{
143+
constexpr int64_t unused = 0;
144+
constexpr int64_t nth = 5;
145+
constexpr int64_t window = 10;
146+
constexpr int64_t multiplier = 1e9;
147+
constexpr int64_t quantile = 0.2 * multiplier;
148+
constexpr int64_t quantile_and_window = quantile + window * (multiplier + 1);
149+
}
150+
151+
#define BENCHMARK_GROUPBY_X_ALL_TYPES(GB_FUNCTION, funcParam) \
152+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_INT8, funcParam>)->Apply(GroupByArguments); \
153+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_INT16, funcParam>)->Apply(GroupByArguments); \
154+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_INT32, funcParam>)->Apply(GroupByArguments); \
155+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_INT64, funcParam>)->Apply(GroupByArguments); \
156+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_UINT8, funcParam>)->Apply(GroupByArguments); \
157+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_UINT16, funcParam>)->Apply(GroupByArguments); \
158+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_UINT32, funcParam>)->Apply(GroupByArguments); \
159+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_UINT64, funcParam>)->Apply(GroupByArguments); \
160+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_FLOAT, funcParam>)->Apply(GroupByArguments); \
161+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_DOUBLE, funcParam>)->Apply(GroupByArguments); \
162+
BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_LONGDOUBLE, funcParam>)->Apply(GroupByArguments);
163+
164+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_FIRST, unused);
165+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_NTH, nth);
166+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_LAST, unused);
167+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_MEDIAN, unused);
168+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_MODE, unused);
169+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_TRIMBR, unused);
170+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_QUANTILE_MULT, quantile);
171+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_SUM, window);
172+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_NANSUM, window);
173+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_DIFF, window);
174+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_SHIFT, window);
175+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_MEAN, window);
176+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_NANMEAN, window);
177+
BENCHMARK_GROUPBY_X_ALL_TYPES(GB_ROLLING_QUANTILE, quantile_and_window);
178+
179+
BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_INT8, 0>)->Apply(GroupByArguments);
180+
BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_INT16, 0>)->Apply(GroupByArguments);
181+
BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_INT32, 0>)->Apply(GroupByArguments);
182+
BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_INT64, 0>)->Apply(GroupByArguments);
183+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_UINT8, 0>)->Apply(GroupByArguments);
184+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_UINT16, 0>)->Apply(GroupByArguments);
185+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_UINT32, 0>)->Apply(GroupByArguments);
186+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_UINT64, 0>)->Apply(GroupByArguments);
187+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_FLOAT, 0>)->Apply(GroupByArguments);
188+
// BENCHMARK(BM_GroupByX<GB_ROLLING_COUNT, NPY_DOUBLE, 0>)->Apply(GroupByArguments);
189+
// BENCHMARK(BM_GroupByX<GB_FUNCTION, NPY_LONGDOUBLE, 0>)->Apply(GroupByArguments);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <benchmark/benchmark.h>
2+
#include "RipTide.h"
3+
#include "numpy_traits.h"
4+
#include "Reduce.h"
5+
6+
using namespace riptide::benchmark;
7+
8+
template <REDUCE_FUNCTIONS function, NPY_TYPES TypeCode>
9+
static void BM_Reduce(benchmark::State & state)
10+
{
11+
int64_t length = state.range(0);
12+
std::vector<typename riptide::numpy_cpp_type<TypeCode>::type> input(length);
13+
14+
for (auto _ : state)
15+
{
16+
call_reduce_function(function, TypeCode, input.data(), length);
17+
}
18+
}
19+
20+
static void BM_ReduceArguments(benchmark::internal::Benchmark * b)
21+
{
22+
// Benchmark with input length of 1m values
23+
b->Args({ 1000000 });
24+
}
25+
26+
#define BENCHMARK_REDUCE_ALL_TYPES(REDUCE_FUNCTION) \
27+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_INT8>)->Apply(BM_ReduceArguments); \
28+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_INT16>)->Apply(BM_ReduceArguments); \
29+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_INT32>)->Apply(BM_ReduceArguments); \
30+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_INT64>)->Apply(BM_ReduceArguments); \
31+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_UINT8>)->Apply(BM_ReduceArguments); \
32+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_UINT16>)->Apply(BM_ReduceArguments); \
33+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_UINT32>)->Apply(BM_ReduceArguments); \
34+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_UINT64>)->Apply(BM_ReduceArguments); \
35+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_FLOAT>)->Apply(BM_ReduceArguments); \
36+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_DOUBLE>)->Apply(BM_ReduceArguments); \
37+
BENCHMARK(BM_Reduce<REDUCE_FUNCTION, NPY_LONGDOUBLE>)->Apply(BM_ReduceArguments);
38+
39+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_SUM);
40+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANSUM);
41+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_MEAN);
42+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANMEAN);
43+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_VAR);
44+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANVAR);
45+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_STD);
46+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANSTD);
47+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_MIN);
48+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANMIN);
49+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_MAX);
50+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANMAX);
51+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_ARGMIN);
52+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANARGMIN);
53+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_ARGMAX);
54+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_NANARGMAX);
55+
BENCHMARK_REDUCE_ALL_TYPES(REDUCE_MIN_NANAWARE);

0 commit comments

Comments
 (0)