deglib 0.2.3__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deglib-0.2.3/src/deglib.egg-info → deglib-0.2.4}/PKG-INFO +15 -19
- {deglib-0.2.3 → deglib-0.2.4}/README.md +14 -18
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/quantization/evp_quantize.h +80 -8
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/quantization/scalar_quantize.h +161 -190
- deglib-0.2.4/lib/deglib/include/deglib/search/searcher.h +493 -0
- deglib-0.2.4/lib/deglib/include/deglib/search.h +253 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deg_cpp/deglib_cpp.cpp +23 -176
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/__init__.py +1 -1
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/search.py +31 -55
- {deglib-0.2.3 → deglib-0.2.4/src/deglib.egg-info}/PKG-INFO +15 -19
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_scalar_quantizer.py +22 -35
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_searcher.py +33 -29
- deglib-0.2.3/lib/deglib/include/deglib/search/searcher.h +0 -454
- deglib-0.2.3/lib/deglib/include/deglib/search.h +0 -112
- {deglib-0.2.3 → deglib-0.2.4}/CMakeLists.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/LICENSE +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/MANIFEST.in +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/CMakeLists.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/CMakeLists.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/benchmark.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/build.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/dataset.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/file_io.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/logging.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/repository.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/stats.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/bench/include/stopwatch.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/cmake_modules/DetectCPUFeatures.cmake +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/CMakeLists.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/analysis.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/builder.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/concurrent.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/config.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/deglib.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/evp_ip.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp16.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp16_ip.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp16_l2.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp32.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp32_ip.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/fp32_l2.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/int8.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/int8_ip.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/int8_l2.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/residual_mode.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/uint8.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/uint8_ip.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distance/uint8_l2.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/distances.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/filter.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/dynamic_graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/internal_graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/intrusive_list.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/mutable_graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/readonly_graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/sizebounded_graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph/visited_list_pool.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/graph.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/flas/fast_linear_assignment_sorter.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/flas/fast_linear_assignment_sorter_mt.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/flas/junker_volgenant_solver.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/pruning.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/transform.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/utils/cpu.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/utils/memory.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/utils/random.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/test/CMakeLists.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/lib/test/src/common/test_helpers.h +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/pyproject.toml +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/setup.cfg +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/setup.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/analysis.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/builder.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/cpu.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/distances.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/graph.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/optimization.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib/utils.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib.egg-info/SOURCES.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib.egg-info/dependency_links.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib.egg-info/requires.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/src/deglib.egg-info/top_level.txt +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_analysis.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_builder.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_filter.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_graph.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_presort.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_rerank.py +0 -0
- {deglib-0.2.3 → deglib-0.2.4}/tests/test_transform.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deglib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Python bindings for the Dynamic Exploration Graph library by Nico Hezel
|
|
5
5
|
Author: Nico Hezel
|
|
6
6
|
Author-email: Bruno Schilling <bruno.schilling@htw-berlin.de>
|
|
@@ -216,17 +216,17 @@ explored_labels, distances = graph.explore(entry_external_label=105, k=10, eps=0
|
|
|
216
216
|
|
|
217
217
|
### Graph Optimization, Quantization & Reranking Pipeline
|
|
218
218
|
|
|
219
|
-
A complete end-to-end pipeline demonstrating **FLAS pre-sorting**, **multithreaded graph building**, **RNG edge pruning**, **Int8 quantization**, **ReadOnlyGraph conversion**, and
|
|
219
|
+
A complete end-to-end pipeline demonstrating **FLAS pre-sorting**, **multithreaded graph building**, **RNG edge pruning**, **Int8 quantization**, **ReadOnlyGraph conversion**, and deployment with **`Searcher`** for automatic query quantization and high-precision reranking:
|
|
220
220
|
|
|
221
221
|
```python
|
|
222
222
|
import numpy as np
|
|
223
223
|
import deglib
|
|
224
224
|
from deglib.optimization import presort, prune_non_rng_edges, ScalarQuantizerInt8
|
|
225
|
-
from deglib.search import
|
|
225
|
+
from deglib.search import create_searcher
|
|
226
226
|
|
|
227
227
|
num_vectors, dims = 10_000, 128
|
|
228
228
|
data = np.random.randn(num_vectors, dims).astype(np.float32)
|
|
229
|
-
query = np.random.randn(
|
|
229
|
+
query = np.random.randn(dims).astype(np.float32)
|
|
230
230
|
|
|
231
231
|
# 1. Pre-sort vectors using FLAS for improved memory locality and index construction speed
|
|
232
232
|
perm = presort(data, metric=deglib.Metric.FP32_InnerProduct, callback="progress")
|
|
@@ -253,23 +253,19 @@ int8_space = deglib.FloatSpace.create(dims, deglib.Metric.Int8_InnerProduct)
|
|
|
253
253
|
# 5. Convert mutable graph to a compact ReadOnlyGraph equipped with the quantized features
|
|
254
254
|
readonly_graph = graph.to_readonly(feature_space=int8_space, custom_features=quant_int8_data)
|
|
255
255
|
|
|
256
|
-
# 6.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
space=fp32_space,
|
|
264
|
-
queries=query,
|
|
265
|
-
candidate_indices=candidate_indices,
|
|
266
|
-
base_vectors=sorted_data,
|
|
267
|
-
k_top=10,
|
|
268
|
-
return_distances=True,
|
|
256
|
+
# 6. Create high-performance Searcher equipped with base vectors for exact candidate reranking
|
|
257
|
+
rerank_space = deglib.FloatSpace.create(dims, deglib.Metric.FP32_InnerProduct)
|
|
258
|
+
searcher = create_searcher(
|
|
259
|
+
graph=readonly_graph,
|
|
260
|
+
quantizer=quantizer,
|
|
261
|
+
refine_space=rerank_space,
|
|
262
|
+
refine_data=sorted_data,
|
|
269
263
|
)
|
|
270
264
|
|
|
271
|
-
|
|
272
|
-
|
|
265
|
+
# 7. Query search (query is automatically quantized and top candidates are reranked)
|
|
266
|
+
indices, distances = searcher.search(query, k=10, eps=0.1, rerank_factor=1.5, return_distances=True)
|
|
267
|
+
print("Top-10 nearest neighbor indices:", indices)
|
|
268
|
+
print("Top-10 exact distances:", distances)
|
|
273
269
|
```
|
|
274
270
|
|
|
275
271
|
---
|
|
@@ -188,17 +188,17 @@ explored_labels, distances = graph.explore(entry_external_label=105, k=10, eps=0
|
|
|
188
188
|
|
|
189
189
|
### Graph Optimization, Quantization & Reranking Pipeline
|
|
190
190
|
|
|
191
|
-
A complete end-to-end pipeline demonstrating **FLAS pre-sorting**, **multithreaded graph building**, **RNG edge pruning**, **Int8 quantization**, **ReadOnlyGraph conversion**, and
|
|
191
|
+
A complete end-to-end pipeline demonstrating **FLAS pre-sorting**, **multithreaded graph building**, **RNG edge pruning**, **Int8 quantization**, **ReadOnlyGraph conversion**, and deployment with **`Searcher`** for automatic query quantization and high-precision reranking:
|
|
192
192
|
|
|
193
193
|
```python
|
|
194
194
|
import numpy as np
|
|
195
195
|
import deglib
|
|
196
196
|
from deglib.optimization import presort, prune_non_rng_edges, ScalarQuantizerInt8
|
|
197
|
-
from deglib.search import
|
|
197
|
+
from deglib.search import create_searcher
|
|
198
198
|
|
|
199
199
|
num_vectors, dims = 10_000, 128
|
|
200
200
|
data = np.random.randn(num_vectors, dims).astype(np.float32)
|
|
201
|
-
query = np.random.randn(
|
|
201
|
+
query = np.random.randn(dims).astype(np.float32)
|
|
202
202
|
|
|
203
203
|
# 1. Pre-sort vectors using FLAS for improved memory locality and index construction speed
|
|
204
204
|
perm = presort(data, metric=deglib.Metric.FP32_InnerProduct, callback="progress")
|
|
@@ -225,23 +225,19 @@ int8_space = deglib.FloatSpace.create(dims, deglib.Metric.Int8_InnerProduct)
|
|
|
225
225
|
# 5. Convert mutable graph to a compact ReadOnlyGraph equipped with the quantized features
|
|
226
226
|
readonly_graph = graph.to_readonly(feature_space=int8_space, custom_features=quant_int8_data)
|
|
227
227
|
|
|
228
|
-
# 6.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
space=fp32_space,
|
|
236
|
-
queries=query,
|
|
237
|
-
candidate_indices=candidate_indices,
|
|
238
|
-
base_vectors=sorted_data,
|
|
239
|
-
k_top=10,
|
|
240
|
-
return_distances=True,
|
|
228
|
+
# 6. Create high-performance Searcher equipped with base vectors for exact candidate reranking
|
|
229
|
+
rerank_space = deglib.FloatSpace.create(dims, deglib.Metric.FP32_InnerProduct)
|
|
230
|
+
searcher = create_searcher(
|
|
231
|
+
graph=readonly_graph,
|
|
232
|
+
quantizer=quantizer,
|
|
233
|
+
refine_space=rerank_space,
|
|
234
|
+
refine_data=sorted_data,
|
|
241
235
|
)
|
|
242
236
|
|
|
243
|
-
|
|
244
|
-
|
|
237
|
+
# 7. Query search (query is automatically quantized and top candidates are reranked)
|
|
238
|
+
indices, distances = searcher.search(query, k=10, eps=0.1, rerank_factor=1.5, return_distances=True)
|
|
239
|
+
print("Top-10 nearest neighbor indices:", indices)
|
|
240
|
+
print("Top-10 exact distances:", distances)
|
|
245
241
|
```
|
|
246
242
|
|
|
247
243
|
---
|
{deglib-0.2.3 → deglib-0.2.4}/lib/deglib/include/deglib/optimization/quantization/evp_quantize.h
RENAMED
|
@@ -17,17 +17,17 @@ namespace deglib::quantization::evp {
|
|
|
17
17
|
// ============================================================================
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Quantizes a single fp32 vector
|
|
20
|
+
* Quantizes a single fp32 vector directly into a pre-allocated EVP byte buffer.
|
|
21
21
|
*
|
|
22
22
|
* Layout: [ones (dim/8 bytes)][negative_ones (dim/8 bytes)]
|
|
23
23
|
*
|
|
24
24
|
* @param embedding Pointer to dim float values (row-major)
|
|
25
25
|
* @param dim Dimension (must be divisible by 8)
|
|
26
26
|
* @param non_zeros Number of top-K elements by absolute value
|
|
27
|
-
* @
|
|
27
|
+
* @param out_bytes Pointer to buffer of at least 2 * dim/8 bytes
|
|
28
28
|
* @throws std::invalid_argument if dim % 8 != 0 or non_zeros >= dim
|
|
29
29
|
*/
|
|
30
|
-
inline
|
|
30
|
+
inline void quantize_single_into(const float* embedding, uint32_t dim, uint32_t non_zeros, std::byte* out_bytes) {
|
|
31
31
|
if (dim % 8 != 0) {
|
|
32
32
|
throw std::invalid_argument("quantize_single: dim must be divisible by 8, got " + std::to_string(dim));
|
|
33
33
|
}
|
|
@@ -36,8 +36,6 @@ inline std::vector<std::byte> quantize_single(const float* embedding, uint32_t d
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const size_t mask_bytes = dim / 8;
|
|
39
|
-
std::vector<std::byte> result(2 * mask_bytes);
|
|
40
|
-
|
|
41
39
|
std::vector<std::pair<float, uint32_t>> abs_vals(dim);
|
|
42
40
|
for (uint32_t i = 0; i < dim; ++i) {
|
|
43
41
|
abs_vals[i] = {std::abs(embedding[i]), i};
|
|
@@ -51,8 +49,8 @@ inline std::vector<std::byte> quantize_single(const float* embedding, uint32_t d
|
|
|
51
49
|
is_top[abs_vals[j].second] = 1;
|
|
52
50
|
}
|
|
53
51
|
|
|
54
|
-
std::byte* ones_dst =
|
|
55
|
-
std::byte* negs_dst =
|
|
52
|
+
std::byte* ones_dst = out_bytes;
|
|
53
|
+
std::byte* negs_dst = out_bytes + mask_bytes;
|
|
56
54
|
|
|
57
55
|
for (uint32_t byte_idx = 0; byte_idx < mask_bytes; ++byte_idx) {
|
|
58
56
|
int byte_val = 0;
|
|
@@ -77,7 +75,23 @@ inline std::vector<std::byte> quantize_single(const float* embedding, uint32_t d
|
|
|
77
75
|
}
|
|
78
76
|
negs_dst[byte_idx] = static_cast<std::byte>(byte_val);
|
|
79
77
|
}
|
|
78
|
+
}
|
|
80
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Quantizes a single fp32 vector to EVP bytes.
|
|
82
|
+
*
|
|
83
|
+
* Layout: [ones (dim/8 bytes)][negative_ones (dim/8 bytes)]
|
|
84
|
+
*
|
|
85
|
+
* @param embedding Pointer to dim float values (row-major)
|
|
86
|
+
* @param dim Dimension (must be divisible by 8)
|
|
87
|
+
* @param non_zeros Number of top-K elements by absolute value
|
|
88
|
+
* @return std::vector<std::byte> with 2 * dim/8 bytes
|
|
89
|
+
* @throws std::invalid_argument if dim % 8 != 0 or non_zeros >= dim
|
|
90
|
+
*/
|
|
91
|
+
inline std::vector<std::byte> quantize_single(const float* embedding, uint32_t dim, uint32_t non_zeros) {
|
|
92
|
+
const size_t mask_bytes = dim / 8;
|
|
93
|
+
std::vector<std::byte> result(2 * mask_bytes);
|
|
94
|
+
quantize_single_into(embedding, dim, non_zeros, result.data());
|
|
81
95
|
return result;
|
|
82
96
|
}
|
|
83
97
|
|
|
@@ -378,11 +392,69 @@ inline std::vector<std::byte> quantize_batch(const std::vector<std::vector<std::
|
|
|
378
392
|
return result;
|
|
379
393
|
}
|
|
380
394
|
|
|
395
|
+
/**
|
|
396
|
+
* Quantizes a single FP16 (uint16_t) vector directly into a pre-allocated EVP byte buffer.
|
|
397
|
+
*
|
|
398
|
+
* Layout: [ones (dim/8 bytes)][negative_ones (dim/8 bytes)]
|
|
399
|
+
*/
|
|
400
|
+
inline void quantize_single_into(const uint16_t* embedding, uint32_t dim, uint32_t non_zeros, std::byte* out_bytes) {
|
|
401
|
+
if (dim % 8 != 0) {
|
|
402
|
+
throw std::invalid_argument("quantize_single: dim must be divisible by 8, got " + std::to_string(dim));
|
|
403
|
+
}
|
|
404
|
+
if (non_zeros >= dim) {
|
|
405
|
+
throw std::invalid_argument("quantize_single: non_zeros must be < dim");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const size_t mask_bytes = dim / 8;
|
|
409
|
+
std::vector<std::pair<uint16_t, uint32_t>> abs_vals(dim);
|
|
410
|
+
for (uint32_t i = 0; i < dim; ++i) {
|
|
411
|
+
abs_vals[i] = {static_cast<uint16_t>(embedding[i] & 0x7FFFu), i};
|
|
412
|
+
}
|
|
413
|
+
std::nth_element(abs_vals.begin(), abs_vals.begin() + (dim - non_zeros), abs_vals.end(), [](const auto& a, const auto& b) {
|
|
414
|
+
return a.first != b.first ? a.first < b.first : a.second < b.second;
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
std::vector<uint8_t> is_top(dim, 0);
|
|
418
|
+
for (uint32_t j = dim - non_zeros; j < dim; ++j) {
|
|
419
|
+
is_top[abs_vals[j].second] = 1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
std::byte* ones_dst = out_bytes;
|
|
423
|
+
std::byte* negs_dst = out_bytes + mask_bytes;
|
|
424
|
+
|
|
425
|
+
for (uint32_t byte_idx = 0; byte_idx < mask_bytes; ++byte_idx) {
|
|
426
|
+
int bv = 0;
|
|
427
|
+
for (int bit = 0; bit < 8; ++bit) {
|
|
428
|
+
const uint32_t bit_idx = byte_idx * 8 + bit;
|
|
429
|
+
if (bit_idx >= dim) break;
|
|
430
|
+
if (is_top[bit_idx] && (embedding[bit_idx] & 0x8000u) == 0 && (embedding[bit_idx] & 0x7FFFu) > 0) {
|
|
431
|
+
bv |= (1 << bit);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
ones_dst[byte_idx] = static_cast<std::byte>(bv);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for (uint32_t byte_idx = 0; byte_idx < mask_bytes; ++byte_idx) {
|
|
438
|
+
int bv = 0;
|
|
439
|
+
for (int bit = 0; bit < 8; ++bit) {
|
|
440
|
+
const uint32_t bit_idx = byte_idx * 8 + bit;
|
|
441
|
+
if (bit_idx >= dim) break;
|
|
442
|
+
if (is_top[bit_idx] && (embedding[bit_idx] & 0x8000u) != 0 && (embedding[bit_idx] & 0x7FFFu) > 0) {
|
|
443
|
+
bv |= (1 << bit);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
negs_dst[byte_idx] = static_cast<std::byte>(bv);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
381
450
|
/**
|
|
382
451
|
* Quantizes a single FP16 (uint16_t) vector to EVP bytes.
|
|
383
452
|
*/
|
|
384
453
|
inline std::vector<std::byte> quantize_single(const uint16_t* embedding, uint32_t dim, uint32_t non_zeros) {
|
|
385
|
-
|
|
454
|
+
const size_t mask_bytes = dim / 8;
|
|
455
|
+
std::vector<std::byte> result(2 * mask_bytes);
|
|
456
|
+
quantize_single_into(embedding, dim, non_zeros, result.data());
|
|
457
|
+
return result;
|
|
386
458
|
}
|
|
387
459
|
|
|
388
460
|
} // namespace deglib::quantization::evp
|