Skip to content

Commit 4683cc1

Browse files
mengdilinfacebook-github-bot
authored andcommitted
create perf_tests directory and onboard all scalar quantizer types to benchmark (#3824)
Summary: Pull Request resolved: #3824 We currently have a 6bit quantizer benchmark running on servicelab during difftime. This diff creates `faiss/perf_tests` directory which will host all the benchmarks that run as performance regression tests. It generalizes `bench_6bit_codec` to work for all quantizer types. I am not deleting the existing `bench_6bit_codec` experiments yet because I want to play around with parameters: {num_trials, num_iterations, strobelight_profiling} in the new sets of experiments to see which combinations provide the least amount of noise. For now, these experiments will not run on diffs. Reviewed By: mnorris11 Differential Revision: D62033843 fbshipit-source-id: d59a67db6c68d8830b1bc8b4d95e2fe8262e8c4d
1 parent 5e61450 commit 4683cc1

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <omp.h>
9+
#include <cstdio>
10+
#include <map>
11+
12+
#include <benchmark/benchmark.h>
13+
#include <faiss/impl/ScalarQuantizer.h>
14+
#include <faiss/utils/distances.h>
15+
#include <faiss/utils/random.h>
16+
#include <faiss/utils/utils.h>
17+
18+
using namespace faiss;
19+
20+
static void bench(
21+
benchmark::State& state,
22+
ScalarQuantizer::QuantizerType type) {
23+
int d = 128;
24+
int n = 2000;
25+
26+
std::vector<float> x(d * n);
27+
28+
float_rand(x.data(), d * n, 12345);
29+
30+
// make sure it's idempotent
31+
ScalarQuantizer sq(d, type);
32+
33+
omp_set_num_threads(1);
34+
35+
sq.train(n, x.data());
36+
37+
size_t code_size = sq.code_size;
38+
state.counters["code_size"] = sq.code_size;
39+
40+
// encode
41+
std::vector<uint8_t> codes(code_size * n);
42+
sq.compute_codes(x.data(), codes.data(), n);
43+
44+
// decode
45+
std::vector<float> x2(d * n);
46+
sq.decode(codes.data(), x2.data(), n);
47+
48+
state.counters["sql2_recons_error"] =
49+
fvec_L2sqr(x.data(), x2.data(), n * d) / n;
50+
51+
// encode again
52+
std::vector<uint8_t> codes2(code_size * n);
53+
sq.compute_codes(x2.data(), codes2.data(), n);
54+
55+
size_t ndiff = 0;
56+
for (size_t i = 0; i < codes.size(); i++) {
57+
if (codes[i] != codes2[i])
58+
ndiff++;
59+
}
60+
61+
state.counters["ndiff_for_idempotence"] = ndiff;
62+
63+
state.counters["code_size_two"] = codes.size();
64+
65+
std::unique_ptr<ScalarQuantizer::SQDistanceComputer> dc(
66+
sq.get_distance_computer());
67+
dc->codes = codes.data();
68+
dc->code_size = sq.code_size;
69+
state.counters["code_size_three"] = dc->code_size;
70+
71+
for (auto _ : state) {
72+
float sum_dis = 0;
73+
for (int i = 0; i < n; i++) {
74+
dc->set_query(&x[i * d]);
75+
for (int j = 0; j < n; j++) {
76+
benchmark::DoNotOptimize(sum_dis += (*dc)(j));
77+
}
78+
}
79+
}
80+
}
81+
82+
int main(int argc, char** argv) {
83+
int iterations = 20;
84+
std::map<std::string, ScalarQuantizer::QuantizerType> benchs = {
85+
{"QT_8bit", ScalarQuantizer::QT_8bit},
86+
{"QT_4bit", ScalarQuantizer::QT_4bit},
87+
{"QT_8bit_uniform", ScalarQuantizer::QT_8bit_uniform},
88+
{"QT_4bit_uniform", ScalarQuantizer::QT_4bit_uniform},
89+
{"QT_fp16", ScalarQuantizer::QT_fp16},
90+
{"QT_8bit_direct", ScalarQuantizer::QT_8bit_direct},
91+
{"QT_6bit", ScalarQuantizer::QT_6bit},
92+
{"QT_bf16", ScalarQuantizer::QT_bf16},
93+
{"QT_8bit_direct_signed", ScalarQuantizer::QT_8bit_direct_signed}};
94+
for (auto& [bench_name, quantizer_type] : benchs) {
95+
benchmark::RegisterBenchmark(bench_name.c_str(), bench, quantizer_type)
96+
->Iterations(iterations);
97+
}
98+
benchmark::RunSpecifiedBenchmarks();
99+
benchmark::Shutdown();
100+
}

0 commit comments

Comments
 (0)