Skip to content

Commit cb4b44a

Browse files
committed
rabitq works inside of HNSW
1 parent 8376a59 commit cb4b44a

File tree

15 files changed

+90
-104
lines changed

15 files changed

+90
-104
lines changed

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/AbstractStorageAdapter.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import com.apple.foundationdb.ReadTransaction;
2424
import com.apple.foundationdb.Transaction;
2525
import com.apple.foundationdb.linear.AffineOperator;
26-
import com.apple.foundationdb.linear.VectorOperator;
26+
import com.apple.foundationdb.linear.Quantizer;
2727
import com.apple.foundationdb.subspace.Subspace;
2828
import com.apple.foundationdb.tuple.Tuple;
2929
import org.slf4j.Logger;
@@ -251,15 +251,17 @@ private Node<N> checkNode(@Nullable final Node<N> node) {
251251
* debug logging upon completion.
252252
*
253253
* @param transaction the non-null {@link Transaction} context for this write operation
254+
* @param quantizer the quantizer to use
254255
* @param node the non-null {@link Node} to be written to storage
255256
* @param layer the layer index where the node is being written
256257
* @param changeSet the non-null {@link NeighborsChangeSet} detailing the modifications
257258
* to the node's neighbors
258259
*/
259260
@Override
260-
public void writeNode(@Nonnull Transaction transaction, @Nonnull Node<N> node, int layer,
261-
@Nonnull NeighborsChangeSet<N> changeSet) {
262-
writeNodeInternal(transaction, node, layer, changeSet);
261+
public void writeNode(@Nonnull final Transaction transaction, @Nonnull final Quantizer quantizer,
262+
@Nonnull final Node<N> node, final int layer,
263+
@Nonnull final NeighborsChangeSet<N> changeSet) {
264+
writeNodeInternal(transaction, quantizer, node, layer, changeSet);
263265
if (logger.isTraceEnabled()) {
264266
logger.trace("written node with key={} at layer={}", node.getPrimaryKey(), layer);
265267
}
@@ -274,12 +276,14 @@ public void writeNode(@Nonnull Transaction transaction, @Nonnull Node<N> node, i
274276
* to the node's neighbors, as detailed in the {@code changeSet}.
275277
*
276278
* @param transaction the non-null transaction context for the write operation
279+
* @param quantizer the quantizer to use
277280
* @param node the non-null {@link Node} to write
278281
* @param layer the layer or level of the node in the structure
279282
* @param changeSet the non-null {@link NeighborsChangeSet} detailing additions or
280283
* removals of neighbor links
281284
*/
282-
protected abstract void writeNodeInternal(@Nonnull Transaction transaction, @Nonnull Node<N> node, int layer,
285+
protected abstract void writeNodeInternal(@Nonnull Transaction transaction, @Nonnull Quantizer quantizer,
286+
@Nonnull Node<N> node, int layer,
283287
@Nonnull NeighborsChangeSet<N> changeSet);
284288

285289
}

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/BaseNeighborsChangeSet.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package com.apple.foundationdb.async.hnsw;
2222

2323
import com.apple.foundationdb.Transaction;
24+
import com.apple.foundationdb.linear.Quantizer;
2425
import com.apple.foundationdb.tuple.Tuple;
2526
import com.google.common.collect.ImmutableList;
2627

@@ -88,7 +89,7 @@ public List<N> merge() {
8889
*/
8990
@Override
9091
public void writeDelta(@Nonnull final InliningStorageAdapter storageAdapter, @Nonnull final Transaction transaction,
91-
final int layer, @Nonnull final Node<N> node,
92+
@Nonnull final Quantizer quantizer, final int layer, @Nonnull final Node<N> node,
9293
@Nonnull final Predicate<Tuple> primaryKeyPredicate) {
9394
// nothing to be written
9495
}

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/CompactStorageAdapter.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.apple.foundationdb.async.AsyncIterable;
2929
import com.apple.foundationdb.async.AsyncUtil;
3030
import com.apple.foundationdb.linear.AffineOperator;
31+
import com.apple.foundationdb.linear.Quantizer;
3132
import com.apple.foundationdb.linear.RealVector;
3233
import com.apple.foundationdb.subspace.Subspace;
3334
import com.apple.foundationdb.tuple.ByteArrayUtil;
@@ -244,20 +245,22 @@ private Node<NodeReference> compactNodeFromTuples(@Nonnull final AffineOperator
244245
* registered write listeners via {@code onNodeWritten} and {@code onKeyValueWritten}.
245246
*
246247
* @param transaction the {@link Transaction} to use for the write operation.
248+
* @param quantizer the quantizer to use
247249
* @param node the {@link Node} to be serialized and written; it is processed as a {@link CompactNode}.
248250
* @param layer the graph layer index for the node, used to construct the storage key.
249251
* @param neighborsChangeSet a {@link NeighborsChangeSet} containing the additions and removals, which are
250252
* merged to determine the final set of neighbors to be written.
251253
*/
252254
@Override
253-
public void writeNodeInternal(@Nonnull final Transaction transaction, @Nonnull final Node<NodeReference> node,
254-
final int layer, @Nonnull final NeighborsChangeSet<NodeReference> neighborsChangeSet) {
255+
public void writeNodeInternal(@Nonnull final Transaction transaction, @Nonnull final Quantizer quantizer,
256+
@Nonnull final Node<NodeReference> node, final int layer,
257+
@Nonnull final NeighborsChangeSet<NodeReference> neighborsChangeSet) {
255258
final byte[] key = getDataSubspace().pack(Tuple.from(layer, node.getPrimaryKey()));
256259

257260
final List<Object> nodeItems = Lists.newArrayListWithExpectedSize(3);
258261
nodeItems.add(NodeKind.COMPACT.getSerialized());
259262
final CompactNode compactNode = node.asCompactNode();
260-
nodeItems.add(StorageAdapter.tupleFromVector(compactNode.getVector()));
263+
nodeItems.add(StorageAdapter.tupleFromVector(quantizer.encode(compactNode.getVector())));
261264

262265
final Iterable<NodeReference> neighbors = neighborsChangeSet.merge();
263266

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/DeleteNeighborsChangeSet.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package com.apple.foundationdb.async.hnsw;
2222

2323
import com.apple.foundationdb.Transaction;
24+
import com.apple.foundationdb.linear.Quantizer;
2425
import com.apple.foundationdb.tuple.Tuple;
2526
import com.google.common.collect.ImmutableSet;
2627
import com.google.common.collect.Iterables;
@@ -112,6 +113,7 @@ public Iterable<N> merge() {
112113
* relationship for the given {@code node}.
113114
*
114115
* @param storageAdapter the storage adapter to which the changes are written
116+
* @param quantizer the quantizer to use
115117
* @param transaction the transaction context for the write operations
116118
* @param layer the layer index where the write operations should occur
117119
* @param node the node for which the delta is being written
@@ -120,8 +122,9 @@ public Iterable<N> merge() {
120122
*/
121123
@Override
122124
public void writeDelta(@Nonnull final InliningStorageAdapter storageAdapter, @Nonnull final Transaction transaction,
123-
final int layer, @Nonnull final Node<N> node, @Nonnull final Predicate<Tuple> tuplePredicate) {
124-
getParent().writeDelta(storageAdapter, transaction, layer, node,
125+
@Nonnull final Quantizer quantizer, final int layer, @Nonnull final Node<N> node,
126+
@Nonnull final Predicate<Tuple> tuplePredicate) {
127+
getParent().writeDelta(storageAdapter, transaction, quantizer, layer, node,
125128
tuplePredicate.and(tuple -> !deletedNeighborsPrimaryKeys.contains(tuple)));
126129

127130
for (final Tuple deletedNeighborPrimaryKey : deletedNeighborsPrimaryKeys) {

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/HNSW.java

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import com.apple.foundationdb.async.AsyncUtil;
2828
import com.apple.foundationdb.async.MoreAsyncUtil;
2929
import com.apple.foundationdb.linear.AffineOperator;
30-
import com.apple.foundationdb.linear.DoubleRealVector;
3130
import com.apple.foundationdb.linear.Estimator;
3231
import com.apple.foundationdb.linear.FhtKacRotator;
3332
import com.apple.foundationdb.linear.Metric;
@@ -61,7 +60,6 @@
6160
import java.util.concurrent.CompletableFuture;
6261
import java.util.concurrent.Executor;
6362
import java.util.concurrent.PriorityBlockingQueue;
64-
import java.util.concurrent.atomic.AtomicLong;
6563
import java.util.concurrent.atomic.AtomicReference;
6664
import java.util.function.BiFunction;
6765
import java.util.function.Consumer;
@@ -606,46 +604,12 @@ public OnReadListener getOnReadListener() {
606604
return onReadListener;
607605
}
608606

609-
@Nonnull
610-
@SuppressWarnings("PMD.UseUnderscoresInNumericLiterals")
611-
DoubleRealVector centroid() {
612-
final double[] centroidData = {29.0548, 16.785500000000003, 10.708300000000001, 9.7645, 11.3086, 13.3,
613-
15.288300000000001, 17.6192, 32.8404, 31.009500000000003, 35.9102, 21.5091, 16.005300000000002, 28.0939,
614-
32.1253, 22.924, 36.2481, 22.5343, 36.420500000000004, 29.186500000000002, 16.4631, 19.899800000000003,
615-
30.530800000000003, 34.2486, 27.014100000000003, 15.5669, 17.084600000000002, 17.197100000000002,
616-
14.266, 9.9115, 9.4123, 17.4541, 56.876900000000006, 24.6039, 13.7209, 16.6006, 22.0627, 27.7478,
617-
24.7289, 27.4496, 61.2528, 41.6972, 36.5536, 23.1854, 23.075200000000002, 37.342800000000004, 35.1334,
618-
30.1793, 58.946200000000005, 25.0348, 40.7383, 40.7892, 26.500500000000002, 23.0211, 29.471, 45.475,
619-
51.758300000000006, 20.662100000000002, 24.361900000000002, 31.923000000000002, 30.0682,
620-
20.075200000000002, 14.327900000000001, 28.1643, 56.229800000000004, 20.611, 23.8963, 26.3485, 22.6032,
621-
18.0076, 14.595400000000001, 29.842000000000002, 62.9647, 24.6328, 35.617000000000004,
622-
34.456700000000005, 22.788600000000002, 23.7647, 33.1924, 49.4097, 57.7928, 37.629000000000005,
623-
32.409600000000005, 22.2239, 26.907300000000003, 43.5585, 39.6792, 29.811, 52.783300000000004, 23.4802,
624-
14.2668, 19.1766, 28.8002, 32.9715, 25.8216, 26.553800000000003, 28.622, 15.4585, 16.7753,
625-
14.228900000000001, 11.7788, 9.0432, 9.502500000000001, 18.150100000000002, 36.7239, 21.61, 33.1623,
626-
25.9082, 15.449000000000002, 20.7373, 33.7562, 36.1929, 32.265, 29.1111, 32.9189, 20.323900000000002,
627-
16.6245, 31.5031, 35.2207, 22.3947, 28.102500000000003, 15.747100000000001, 10.4765, 10.4483, 13.3939,
628-
15.767800000000001, 16.2652, 17.000600000000002};
629-
return new DoubleRealVector(centroidData);
630-
}
631-
632-
@Nonnull
633-
@SuppressWarnings("PMD.UseUnderscoresInNumericLiterals")
634-
RealVector centroidRot(@Nonnull final FhtKacRotator rotator) {
635-
final DoubleRealVector centroid = centroid();
636-
return rotator.applyTranspose(centroid);
637-
}
638-
639607
@Nonnull
640608
private AffineOperator storageTransform(@Nullable final AccessInfo accessInfo) {
641609
if (accessInfo == null || !accessInfo.canUseRaBitQ()) {
642610
return AffineOperator.identity();
643611
}
644612

645-
// final FhtKacRotator rotator1 = new FhtKacRotator(3, getConfig().getNumDimensions(), 10);
646-
// return new StorageTransform(3,
647-
// getConfig().getNumDimensions(), centroidRot(rotator1));
648-
649613
return new StorageTransform(accessInfo.getRotatorSeed(),
650614
getConfig().getNumDimensions(), Objects.requireNonNull(accessInfo.getCentroid()));
651615
}
@@ -1233,8 +1197,6 @@ public CompletableFuture<Void> insert(@Nonnull final Transaction transaction,
12331197
return insert(transaction, nodeReferenceWithVector.getPrimaryKey(), nodeReferenceWithVector.getVector());
12341198
}
12351199

1236-
public static AtomicLong cK = new AtomicLong(0);
1237-
12381200
/**
12391201
* Inserts a new vector with its associated primary key into the HNSW graph.
12401202
* <p>
@@ -1262,13 +1224,9 @@ public CompletableFuture<Void> insert(@Nonnull final Transaction transaction, @N
12621224
logger.trace("new node with key={} selected to be inserted into layer={}", newPrimaryKey, insertionLayer);
12631225
}
12641226

1265-
cK.set(newPrimaryKey.getLong(0));
1266-
12671227
return StorageAdapter.fetchAccessInfo(getConfig(), transaction, getSubspace(), getOnReadListener())
12681228
.thenCompose(accessInfo -> {
12691229
final AccessInfo currentAccessInfo;
1270-
// final FhtKacRotator rotator1 = new FhtKacRotator(3, getConfig().getNumDimensions(), 10);
1271-
// final AccessInfo staticAccessInfo = new AccessInfo(accessInfo == null ? null : accessInfo.getEntryNodeReference(), 3, centroidRot(rotator1));
12721230
final AffineOperator storageTransform = storageTransform(accessInfo);
12731231
final RealVector transformedNewVector = storageTransform.applyInvert(newVector);
12741232
final Quantizer quantizer = quantizer(accessInfo);
@@ -1376,17 +1334,13 @@ public CompletableFuture<Void> insert(@Nonnull final Transaction transaction, @N
13761334
StorageAdapter.writeAccessInfo(transaction, getSubspace(), newAccessInfo, onWriteListener);
13771335
StorageAdapter.removeAllSampledVectors(transaction, getSubspace());
13781336
if (logger.isTraceEnabled()) {
1379-
//logger.info("at primary key ={}", newPrimaryKey);
13801337
logger.trace("established rotatorSeed={}, centroid with count={}, centroid={}",
13811338
rotatorSeed, partialCount, transformedCentroid);
13821339
}
13831340
}
13841341
}
13851342
return null;
13861343
});
1387-
// final FhtKacRotator rotator1 = new FhtKacRotator(3, getConfig().getNumDimensions(), 10);
1388-
// final AccessInfo staticAccessInfo = new AccessInfo(accessInfo == null ? null : accessInfo.getEntryNodeReference(), 3, centroidRot(rotator1));
1389-
// StorageAdapter.writeAccessInfo(transaction, getSubspace(), staticAccessInfo, onWriteListener);
13901344
}
13911345
}
13921346
return AsyncUtil.DONE;
@@ -1639,14 +1593,14 @@ layer, getConfig().getM(), getConfig().isExtendCandidates(), nodeCache, newVecto
16391593
// regular vectors)
16401594

16411595
final Node<N> newNode =
1642-
nodeFactory.create(newPrimaryKey, quantizer.encode(newVector),
1596+
nodeFactory.create(newPrimaryKey, newVector,
16431597
NodeReferenceAndNode.getReferences(selectedNeighbors));
16441598

16451599
final NeighborsChangeSet<N> newNodeChangeSet =
16461600
new InsertNeighborsChangeSet<>(new BaseNeighborsChangeSet<>(ImmutableList.of()),
16471601
newNode.getNeighbors());
16481602

1649-
storageAdapter.writeNode(transaction, newNode, layer, newNodeChangeSet);
1603+
storageAdapter.writeNode(transaction, quantizer, newNode, layer, newNodeChangeSet);
16501604

16511605
// create change sets for each selected neighbor and insert new node into them
16521606
final Map<Tuple /* primaryKey */, NeighborsChangeSet<N>> neighborChangeSetMap =
@@ -1680,8 +1634,8 @@ layer, getConfig().getM(), getConfig().isExtendCandidates(), nodeCache, newVecto
16801634
for (int i = 0; i < selectedNeighbors.size(); i++) {
16811635
final NodeReferenceAndNode<N> selectedNeighbor = selectedNeighbors.get(i);
16821636
final NeighborsChangeSet<N> changeSet = changeSets.get(i);
1683-
storageAdapter.writeNode(transaction, selectedNeighbor.getNode(),
1684-
layer, changeSet);
1637+
storageAdapter.writeNode(transaction, quantizer,
1638+
selectedNeighbor.getNode(), layer, changeSet);
16851639
}
16861640
return ImmutableList.copyOf(references);
16871641
});
@@ -2053,9 +2007,9 @@ private <N extends NodeReference> void writeLonelyNodeOnLayer(@Nonnull final Qua
20532007
final int layer,
20542008
@Nonnull final Tuple primaryKey,
20552009
@Nonnull final RealVector vector) {
2056-
storageAdapter.writeNode(transaction,
2010+
storageAdapter.writeNode(transaction, quantizer,
20572011
storageAdapter.getNodeFactory()
2058-
.create(primaryKey, quantizer.encode(vector), ImmutableList.of()), layer,
2012+
.create(primaryKey, vector, ImmutableList.of()), layer,
20592013
new BaseNeighborsChangeSet<>(ImmutableList.of()));
20602014
if (logger.isTraceEnabled()) {
20612015
logger.trace("written lonely node at key={} on layer={}", primaryKey, layer);

0 commit comments

Comments
 (0)