Skip to content

Commit b3a5672

Browse files
committed
Enhance ConcurrentBitset and BitsetView
Signed-off-by: zhenshan.cao <zhenshan.cao@zilliz.com>
1 parent b40dfb2 commit b3a5672

12 files changed

Lines changed: 635 additions & 301 deletions

File tree

knowhere/CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ if ( LINUX )
128128
set(depend_libs
129129
faiss
130130
pthread
131-
knowhere_utils
132131
)
133132

134133
if (KNOWHERE_SUPPORT_SPTAG)
@@ -179,10 +178,12 @@ if ( LINUX )
179178
${vector_index_srcs}
180179
${vector_offset_index_srcs}
181180
)
182-
target_include_directories(knowhere PUBLIC ${KNOWHERE_SOURCE_DIR}/knowere)
181+
target_include_directories(knowhere PUBLIC ${KNOWHERE_SOURCE_DIR}/knowhere)
183182
endif ()
184-
185183
target_link_libraries(knowhere ${depend_libs})
184+
target_link_libraries(knowhere -Wl,--whole-archive knowhere_utils -Wl,--no-whole-archive)
185+
#target_link_libraries(knowhere knowhere_utils)
186+
186187
set(KNOWHERE_INCLUDE_DIRS
187188
${KNOWHERE_SOURCE_DIR}
188189
${KNOWHERE_SOURCE_DIR}/thirdparty
@@ -212,7 +213,10 @@ if (MACOS)
212213
)
213214
endif ()
214215

215-
target_link_libraries(knowhere pthread knowhere_utils)
216+
target_link_libraries(knowhere pthread)
217+
target_link_libraries(knowhere -Wl,--whole-archive knowhere_utils -Wl,--no-whole-archive)
218+
#target_link_libraries(knowhere knowhere_utils)
219+
216220
set(KNOWHERE_INCLUDE_DIRS ${KNOWHERE_SOURCE_DIR})
217221
endif()
218222

knowhere/index/vector_index/Statistics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class Statistics {
147147

148148
void
149149
update_filter_percentage(const faiss::BitsetView bitset) {
150-
double fps = !bitset.empty() ? static_cast<double>(bitset.count_1()) / bitset.size() : 0.0;
150+
double fps = !bitset.empty() ? static_cast<double>(bitset.count()) / bitset.size() : 0.0;
151151
filter_stat[static_cast<int>(fps * 100) / 5] += 1;
152152
}
153153

knowhere/utils/Bitset.cpp

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
4+
// with the License. You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software distributed under the License
9+
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10+
// or implied. See the License for the specific language governing permissions and limitations under the License.
11+
12+
#include <cstring>
13+
#include <string>
14+
#include <memory>
15+
#include "Bitset.h"
16+
#include "BitsetView.h"
17+
18+
namespace faiss {
19+
20+
ConcurrentBitset&
21+
ConcurrentBitset::operator&=(const ConcurrentBitset& bitset) {
22+
auto u8_1 = mutable_data();
23+
auto u8_2 = bitset.data();
24+
auto u64_1 = reinterpret_cast<uint64_t*>(u8_1);
25+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
26+
27+
size_t n8 = bitset_.size();
28+
size_t n64 = n8 / 8;
29+
30+
for (size_t i = 0; i < n64; i++) {
31+
u64_1[i] &= u64_2[i];
32+
}
33+
34+
size_t remain = n8 % 8;
35+
u8_1 += n64 * 8;
36+
u8_2 += n64 * 8;
37+
for (size_t i = 0; i < remain; i++) {
38+
u8_1[i] &= u8_2[i];
39+
}
40+
41+
return *this;
42+
}
43+
44+
ConcurrentBitset&
45+
ConcurrentBitset::operator&=(const BitsetView& view) {
46+
auto u8_1 = mutable_data();
47+
auto u8_2 = view.data();
48+
auto u64_1 = reinterpret_cast<uint64_t*>(u8_1);
49+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
50+
51+
size_t n8 = bitset_.size();
52+
size_t n64 = n8 / 8;
53+
54+
for (size_t i = 0; i < n64; i++) {
55+
u64_1[i] &= u64_2[i];
56+
}
57+
58+
size_t remain = n8 % 8;
59+
u8_1 += n64 * 8;
60+
u8_2 += n64 * 8;
61+
for (size_t i = 0; i < remain; i++) {
62+
u8_1[i] &= u8_2[i];
63+
}
64+
65+
return *this;
66+
}
67+
68+
std::shared_ptr<ConcurrentBitset>
69+
ConcurrentBitset::operator&(const ConcurrentBitset& bitset) const {
70+
auto result_bitset = std::make_shared<ConcurrentBitset>(bitset.count());
71+
72+
auto result_8 = result_bitset->mutable_data();
73+
auto result_64 = reinterpret_cast<uint64_t*>(result_8);
74+
75+
auto u8_1 = data();
76+
auto u8_2 = bitset.data();
77+
auto u64_1 = reinterpret_cast<const uint64_t*>(u8_1);
78+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
79+
80+
size_t n8 = bitset_.size();
81+
size_t n64 = n8 / 8;
82+
83+
for (size_t i = 0; i < n64; i++) {
84+
result_64[i] = u64_1[i] & u64_2[i];
85+
}
86+
87+
size_t remain = n8 % 8;
88+
u8_1 += n64 * 8;
89+
u8_2 += n64 * 8;
90+
result_8 += n64 * 8;
91+
for (size_t i = 0; i < remain; i++) {
92+
result_8[i] = u8_1[i] & u8_2[i];
93+
}
94+
95+
return result_bitset;
96+
}
97+
98+
std::shared_ptr<ConcurrentBitset>
99+
ConcurrentBitset::operator&(const BitsetView& view) const {
100+
auto result_bitset = std::make_shared<ConcurrentBitset>(view.count());
101+
102+
auto result_8 = result_bitset->mutable_data();
103+
auto result_64 = reinterpret_cast<uint64_t*>(result_8);
104+
105+
auto u8_1 = data();
106+
auto u8_2 = view.data();
107+
auto u64_1 = reinterpret_cast<const uint64_t*>(u8_1);
108+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
109+
110+
size_t n8 = bitset_.size();
111+
size_t n64 = n8 / 8;
112+
113+
for (size_t i = 0; i < n64; i++) {
114+
result_64[i] = u64_1[i] & u64_2[i];
115+
}
116+
117+
size_t remain = n8 % 8;
118+
u8_1 += n64 * 8;
119+
u8_2 += n64 * 8;
120+
result_8 += n64 * 8;
121+
for (size_t i = 0; i < remain; i++) {
122+
result_8[i] = u8_1[i] & u8_2[i];
123+
}
124+
125+
return result_bitset;
126+
}
127+
128+
129+
ConcurrentBitset&
130+
ConcurrentBitset::operator|=(const ConcurrentBitset& bitset) {
131+
auto u8_1 = mutable_data();
132+
auto u8_2 = bitset.data();
133+
auto u64_1 = reinterpret_cast<uint64_t*>(u8_1);
134+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
135+
136+
size_t n8 = bitset_.size();
137+
size_t n64 = n8 / 8;
138+
139+
for (size_t i = 0; i < n64; i++) {
140+
u64_1[i] |= u64_2[i];
141+
}
142+
143+
size_t remain = n8 % 8;
144+
u8_1 += n64 * 8;
145+
u8_2 += n64 * 8;
146+
for (size_t i = 0; i < remain; i++) {
147+
u8_1[i] |= u8_2[i];
148+
}
149+
150+
return *this;
151+
}
152+
153+
ConcurrentBitset&
154+
ConcurrentBitset::operator|=(const BitsetView& view) {
155+
auto u8_1 = mutable_data();
156+
auto u8_2 = view.data();
157+
auto u64_1 = reinterpret_cast<uint64_t*>(u8_1);
158+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
159+
160+
size_t n8 = bitset_.size();
161+
size_t n64 = n8 / 8;
162+
163+
for (size_t i = 0; i < n64; i++) {
164+
u64_1[i] |= u64_2[i];
165+
}
166+
167+
size_t remain = n8 % 8;
168+
u8_1 += n64 * 8;
169+
u8_2 += n64 * 8;
170+
for (size_t i = 0; i < remain; i++) {
171+
u8_1[i] |= u8_2[i];
172+
}
173+
174+
return *this;
175+
}
176+
177+
178+
std::shared_ptr<ConcurrentBitset>
179+
ConcurrentBitset::operator|(const ConcurrentBitset& bitset) const {
180+
auto result_bitset = std::make_shared<ConcurrentBitset>(bitset.count());
181+
182+
auto result_8 = result_bitset->mutable_data();
183+
auto result_64 = reinterpret_cast<uint64_t*>(result_8);
184+
185+
auto u8_1 = data();
186+
auto u8_2 = bitset.data();
187+
auto u64_1 = reinterpret_cast<const uint64_t*>(u8_1);
188+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
189+
190+
size_t n8 = bitset_.size();
191+
size_t n64 = n8 / 8;
192+
193+
for (size_t i = 0; i < n64; i++) {
194+
result_64[i] = u64_1[i] | u64_2[i];
195+
}
196+
197+
size_t remain = n8 % 8;
198+
u8_1 += n64 * 8;
199+
u8_2 += n64 * 8;
200+
result_8 += n64 * 8;
201+
for (size_t i = 0; i < remain; i++) {
202+
result_8[i] = u8_1[i] | u8_2[i];
203+
}
204+
205+
return result_bitset;
206+
}
207+
208+
std::shared_ptr<ConcurrentBitset>
209+
ConcurrentBitset::operator|(const BitsetView& view) const {
210+
auto result_bitset = std::make_shared<ConcurrentBitset>(view.count());
211+
212+
auto result_8 = result_bitset->mutable_data();
213+
auto result_64 = reinterpret_cast<uint64_t*>(result_8);
214+
215+
auto u8_1 = data();
216+
auto u8_2 = view.data();
217+
auto u64_1 = reinterpret_cast<const uint64_t*>(u8_1);
218+
auto u64_2 = reinterpret_cast<const uint64_t*>(u8_2);
219+
220+
size_t n8 = bitset_.size();
221+
size_t n64 = n8 / 8;
222+
223+
for (size_t i = 0; i < n64; i++) {
224+
result_64[i] = u64_1[i] | u64_2[i];
225+
}
226+
227+
size_t remain = n8 % 8;
228+
u8_1 += n64 * 8;
229+
u8_2 += n64 * 8;
230+
result_8 += n64 * 8;
231+
for (size_t i = 0; i < remain; i++) {
232+
result_8[i] = u8_1[i] | u8_2[i];
233+
}
234+
235+
return result_bitset;
236+
}
237+
238+
239+
ConcurrentBitset&
240+
ConcurrentBitset::negate() {
241+
auto u8_1 = mutable_data();
242+
auto u64_1 = reinterpret_cast<uint64_t*>(u8_1);
243+
244+
size_t n8 = bitset_.size();
245+
size_t n64 = n8 / 8;
246+
247+
for (size_t i = 0; i < n64; i++) {
248+
u64_1[i] = ~u64_1[i];
249+
}
250+
251+
size_t remain = n8 % 8;
252+
u8_1 += n64 * 8;
253+
for (size_t i = 0; i < remain; i++) {
254+
u8_1[i] = ~u8_1[i];
255+
}
256+
257+
return *this;
258+
}
259+
260+
size_t
261+
ConcurrentBitset::count() const {
262+
size_t ret = 0;
263+
auto p_data = reinterpret_cast<const uint64_t *>(data());
264+
auto len = size() >> 3;
265+
//auto remainder = size() % 8;
266+
auto popcount8 = [&](uint8_t x) -> int{
267+
x = (x & 0x55) + ((x >> 1) & 0x55);
268+
x = (x & 0x33) + ((x >> 2) & 0x33);
269+
x = (x & 0x0F) + ((x >> 4) & 0x0F);
270+
return x;
271+
};
272+
for (size_t i = 0; i < len; ++i) {
273+
ret += __builtin_popcountl(*p_data);
274+
p_data++;
275+
}
276+
auto p_byte = data() + (len << 3);
277+
for (auto i = (len << 3); i < size(); ++i) {
278+
ret += popcount8(*p_byte);
279+
p_byte++;
280+
}
281+
return ret;
282+
}
283+
284+
ConcurrentBitset::operator std::string() const {
285+
const char one = '1';
286+
const char zero = '0';
287+
const size_t len = size();
288+
std::string s;
289+
s.assign (len, zero);
290+
291+
for (size_t i = 0; i < len; ++i) {
292+
if (test(id_type_t(i)))
293+
s.assign(len - 1 - i, one);
294+
}
295+
return s;
296+
}
297+
298+
bool operator==(const ConcurrentBitset& lhs, const ConcurrentBitset& rhs) {
299+
if (std::addressof(lhs) == std::addressof(rhs)){
300+
return true;
301+
}
302+
303+
if (lhs.size() != rhs.size()){
304+
return false;
305+
}
306+
307+
if (lhs.byte_size() != rhs.byte_size()){
308+
return false;
309+
}
310+
311+
312+
auto ret = std::memcmp(lhs.data(), rhs.data(), lhs.byte_size());
313+
return ret == 0;
314+
}
315+
316+
bool operator!=(const ConcurrentBitset& lhs, const ConcurrentBitset& rhs){
317+
return !(lhs == rhs);
318+
}
319+
320+
std::ostream& operator<<(std::ostream& os, const ConcurrentBitset& bitset)
321+
{
322+
os << std::string(bitset);
323+
return os;
324+
}
325+
326+
327+
} // namespace faiss

0 commit comments

Comments
 (0)