Commit Graph

36934 Commits

Author SHA1 Message Date
Adrien Grand 58b9352cc2
Add a specialized bulk scorer for regular conjunctions. (#12719)
PR #12382 added a bulk scorer for top-k hits on conjunctions that yielded a
significant speedup (annotation
[FP](http://people.apache.org/~mikemccand/lucenebench/AndHighHigh.html)). This
change proposes a similar change for exhaustive collection of conjunctive
queries, e.g. for counting, faceting, etc.
2023-10-30 16:11:19 +01:00
Benjamin Trent 2ed60e8073
Ensure negative scores are not returned by vector similarity functions (#12727)
We shouldn't ever return negative scores from vector similarity functions. Given vector panama and nearly antipodal float[] vectors, it is possible that cosine and (normalized) dot-product become slightly negative due to compounding floating point errors.

Since we don't want to make panama vector incredibly slow, we stick to float32 operations for now, and just snap to `0` if the score is negative after our correction.

closes: https://github.com/apache/lucene/issues/12700
2023-10-30 10:05:52 -04:00
Shubham Chaudhary 7943b7ad1c
Return the same input vector if its a unit vector in VectorUtil#l2normalize (#12726)
### Description

While going through [VectorUtil](https://github.com/apache/lucene/blob/main/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java) class, I observed we don't have a check for unit vector in `VectorUtil#l2normalize` so passing a unit vector goes thorough the whole L2 normalization(which is totally not required and it should early exit?). I confirmed this by trying out a silly example of `VectorUtil.l2normalize(VectorUtil.l2normalize(nonUnitVector))` and it performed every calculation twice. We could also argue that user should not call for this for a unit vector but I believe there would be cases where user simply want to perform the L2 normalization without checking the vector or if there are some overflowing values.

TL;DR : We should early exit in `VectorUtil#l2normalize`, returning the same input vector if its a unit vector

This is easily avoidable if we introduce a light check to see if the L1 norm or squared sum of input vector is equal to 1.0 (or) maybe just check `Math.abs(l1norm - 1.0d) <= 1e-5` (as in this PR) because that unit vector dot product(`v x v`) are not exactly 1.0 but like example : `0.9999999403953552` etc. With `1e-5` delta here we would be assuming a vector v having `v x v` >= `0.99999` is a unit vector or say already L2 normalized which seems fine as the delta is really small? and also the check is not heavy one?.
2023-10-30 09:52:28 -04:00
Benjamin Trent 2a8d187a99
Add back maxConn & beamWidth HNSW codec ctor (#12728)
follow up to https://github.com/apache/lucene/pull/12582

For user convenience, I added back the two parameter ctor for the HNSW codec.
2023-10-30 09:31:04 -04:00
Mike McCandless 11436a848c fix TestAutomaton.testRandomFinite test bug that was trying to StringsToAutomaton.build a Collection of BytesRefs containing a too-massive (> 1000 UTF-8 bytes) term; corrected the exception message to make it clear the limit is in UTF-8 bytes, not java (UTF-16) characters 2023-10-29 11:41:40 -04:00
Uwe Schindler cfef47f243 Log FMA usage 2023-10-28 23:24:53 +02:00
Patrick Zhai a8c52e2e19
Concurrent HNSW Merge (#12660) 2023-10-28 11:03:22 -07:00
Robert Muir a2016d1d50
Speedup float cosine vectors, use FMA where fast and available to reduce error 2023-10-27 23:45:14 -04:00
Vigya Sharma f5776c8844
Remove test dependency on Java default exception message (#12724) 2023-10-27 15:09:44 -07:00
Benjamin Trent c3f48587fd Adding CHANGES for PR #12582 2023-10-27 15:52:26 -04:00
Luca Cavanna 09da2291c5
Make IndexSearcher#getSlices final and clarify docs (#12718)
IndexSearcher exposes a public getSlices method, that is used to
retrieve the slices that the searcher executes queries against, as well
as slices, which is supposed to be overridden to customize the creation
of slices.

I believe that getSlices should be final: there is no reason to override
the method. Also, it is too easy to confuse the two and end up
overriding the wrong one by mistake.
2023-10-26 12:34:37 +02:00
gf2121 c701a5d9be
Disable suffix sharing for block tree index (#12722) 2023-10-26 12:34:48 +08:00
Dzung Bui 12fc7bf49f
Consolidate FSTStore and BytesStore in FST (#12709)
* Remove direct dependency of NodeHash to FST

* Fix index out of bounds when writing FST to different metaOut (#12697)

* Tidify code

* Update CHANGES.txt

* Re-add assertion

* Remove direct dependency of NodeHash to FST

* Hold off the FSTTraversal changes

* Rename variable

* Add Javadoc

* Add @Override

* tidy

* tidy

* Change to FSTReader

* Update CHANGES.txt
2023-10-25 18:26:27 -07:00
Simon Willnauer 01acb1c37b Close IndexWriter and Directory in try blocks Relates to #12685 2023-10-25 23:36:02 +02:00
Adrien Grand 5966ec6e79 Fix comment. 2023-10-25 20:26:01 +02:00
Adrien Grand 8db38f8713 Fix test failures. 2023-10-25 20:18:06 +02:00
Adrien Grand 3d4082ca3d Run merge-on-full-flush even though no changes got flushed. (#12549)
Currently, merge-on-full-flush only checks if merges need to run if changes
have been flushed to disk. This prevents from having different merging logic
for refreshes and commits, since the merge policy would not be checked upon
commit if no new documents got indexed since the previous refresh.
2023-10-25 14:29:44 +02:00
gf2121 779592771a
Speed up the sort when building forward index (#12712) 2023-10-25 13:36:52 +08:00
gf2121 676dceb081
Use Arrays#mismatch for Outputs#common operations (#12710) 2023-10-25 10:25:10 +08:00
Luca Cavanna fbdc458f86 Address TestTaskExecutor issues
- Use a thread factory
- Remove unused imports
2023-10-24 20:51:45 +02:00
Luca Cavanna eefa0ab85e Add missing CHANGES entry for #12689 2023-10-24 20:43:17 +02:00
Luca Cavanna f6ca54523c Address TestTaskExecutor test failure
Turns out that testCancelTasksOnException require a single threaded
executor. Given that most tests in the class rely make more sense with a
single thread, I went back to 1 thread for the shared executor and used
a multi-threaded executor in the only test that relies on multiple
threads.
2023-10-24 20:40:58 +02:00
Benjamin Trent f2bf5339e5
Add new int8 scalar quantization to HNSW codec (#12582)
Adds new int8 scalar quantization for HNSW codec. This uses a new lucene9.9 format and auto quantizes floating point vectors into bytes on flush and merge.
2023-10-24 14:31:54 -04:00
Nelson Osacky e5b55761d0
Build: build scans on ge.apache.org to benefit from deep build insights (#12293)
Apache committers who opt-in (via authentication) can have their local build scans be submitted to ge.apache.org.

Co-authored-by: Clay Johnson <cjohnson@gradle.com>
2023-10-24 12:32:18 -04:00
Adrien Grand c95a8f6513 Move CHANGES to the right section. 2023-10-24 18:03:53 +02:00
Adrien Grand 611bbbd951
Sometimes intersect the essential clause and the best non-essential clause. (#12589)
The idea behind MAXSCORE is to run disjunctions as `+(essentialClause1 ...
essentialClauseM) nonEssentialClause1 ... nonEssentialClauseN`, moving more and
more clauses from the essential list to the non-essential list as the minimum
competitive score increases. For instance, a query such as `the book of life`
which I found in the Tantivy benchmark ends up running as `+book the of life`
after some time, ie. with one required clause and other clauses optional. This
is because matching `the`, `of` and `life` alone is not good enough for
yielding a match.

Here some statistics in that case:
 - min competitive score: 3.4781857
 - max_window_score(book): 2.8796153
 - max_window_score(life): 2.037863
 - max_window_score(the): 0.103848875
 - max_window_score(of): 0.19427927

Actually if you look at these statistics, we could do better, because a match
may only be competitive if it matches both `book` and `life`, so this query
could actually execute as `+book +life the of`, which may help evaluate fewer
documents compared to `+book the of life`. Especially if you enable recursive
graph bisection.

This is what this PR tries to achieve: in the event when there is a single
essential clause and matching all clauses but the best non-essential clause
cannot produce a competitive match, then the scorer will only evaluate
documents that match the intersection of the essential clause and the best
non-essential clause.

It's worth noting that this optimization would kick in very frequently on
2-clauses disjunctions.
2023-10-24 17:54:23 +02:00
Adrien Grand 5bca0aa391 Revert "Run merge-on-full-flush even though no changes got flushed. (#12549)"
This reverts commit 71c4ea74ba.
2023-10-24 17:43:57 +02:00
Luca Cavanna 1200ecce3a
TaskExecutor to cancel all tasks on exception (#12689)
When operations are parallelized, like query rewrite, or search, or
createWeight, one of the tasks may throw an exception. In that case we
wait for all tasks to be completed before re-throwing the exception that
were caught. Tasks that were not started when the exception is captured
though can be safely skipped. Ideally we would also cancel ongoing tasks
but I left that for another time.
2023-10-24 17:38:25 +02:00
Adrien Grand 71c4ea74ba
Run merge-on-full-flush even though no changes got flushed. (#12549)
Currently, merge-on-full-flush only checks if merges need to run if changes
have been flushed to disk. This prevents from having different merging logic
for refreshes and commits, since the merge policy would not be checked upon
commit if no new documents got indexed since the previous refresh.
2023-10-24 16:57:05 +02:00
Shubham Chaudhary 5461d1a160
Scorer should sum up scores into a double (#12682)
### Description

Addresses #12675 . Along with `MultiSimilarity.MultiSimScorer` found some others candidate scorer implementations for this fix.
2023-10-23 13:01:06 -04:00
Simon Willnauer 6677109ee6
Record if block API has been used in SegmentInfo (#12685)
If the add/updateDocuments(List<>) API is used, lucene guarantees that
all documents are indexed in the same segment with consecutive document IDs.
This enables features like nested documents etc. This change records the usage
of this API in SegmentsInfo and preserves this property across merges.

Relates to #12665
2023-10-23 09:46:12 +02:00
Uwe Schindler bbf197fdc2
MMapDirectory with MemorySegment: Confirm that scope/session is no longer alive before throwing AlreadyClosedException (#12707) 2023-10-22 19:14:29 +02:00
Uwe Schindler 9729123369
Improve handling of NullPointerException in MMapDirectory's IndexInputs (check the "closed" condition) (#12705) 2023-10-22 10:58:44 +02:00
Dzung Bui ad06ee57b8
Remove direct dependency of NodeHash to FST (#12690)
* Remove direct dependency of NodeHash to FST

* tidy
2023-10-21 08:26:07 -04:00
Shubham Chaudhary de8ae1de7c
Optimize computing number of levels in MultiLevelSkipListWriter#bufferSkip (#12653)
* Optimize computing number of levels in MultiLevelSkipListWriter#bufferSkip

* CHANGES.txt entry
2023-10-21 07:52:28 -04:00
Rob Muir 90f8bac9f7 slight correction 2023-10-21 02:05:34 -04:00
Rob Muir c09fb560f7 add hsdis instructions for the macos 2023-10-21 02:02:24 -04:00
Michael McCandless afb2a60751
Bound the RAM used by the NodeHash (sharing common suffixes) during FST compilation (#12633)
* tweak comments; change if to switch

* remove old SOPs, minor comment styling, fixed silly performance bug on rehash using the wrong bitsRequired (count vs node)

* first raw cut; some nocommits added; some tests fail

* tests pass!

* fix silly fallback hash bug

* remove SOPs; add some temporary debugging metrics

* add temporary tool to test FST performance across differing NodeHash sizes

* remove (now deleted) shouldShareNonSingletonNodes call from Lucene90BlockTreeTermsWriter

* add simple tool to render results table to GitHub MD

* add simple temporary tool to iterate all terms from a provided luceneutil wikipedia index and build an FST from them

* first cut at using packed ints for hash t able again

* add some nocommits; tweak test_all_sizes.py to new RAM usage approach; when half of the double barrel is full, allocate new primary hash at full size to save cost of continuously rehashing for a large FST

* switch to limit suffix hash by RAM usage not count (more intuitive for users); clean up some stale nocommits

* switch to more intuitive approximate RAM (mb) limit for allowed size of NodeHash

* nuke a few nocommits; a few more remain

* remove DO_PRINT_HASH_RAM

* no more FST pruning

* remove final nocommit: randomly change allowed NodeHash suffix RAM size in TestFSTs.testRealTerms

* remove SOP

* tidy

* delete temp utility tools

* remove dead (FST pruning) code

* add CHANGES entry; fix one missed fst.addNode -> fstCompiler.addNode during merge conflict resolution

* remove a mal-formed nocommit

* fold PR feedback

* fold feedback

* add gradle help test details on how to specify heap size for the test JVM; fix bogus assert (uncovered by Test2BFST); add TODO to Test2BFST anticipating building massive FSTs in small bounded RAM

* suppress sysout checks for Test2BFSTs; add helpful comment showing how to run it directly

* tidy
2023-10-20 11:52:55 -04:00
Dzung Bui 0d8a3e6c4f
Fix index out of bounds when writing FST to different metaOut (#12697) (#12698)
* Fix index out of bounds when writing FST to different metaOut (#12697)

* Tidify code

* Update CHANGES.txt

* Re-add assertion
2023-10-20 07:25:04 -04:00
gf2121 343a9e7100
Avoid object construction when linear searching arcs (#12692) 2023-10-20 00:41:09 +08:00
Stéphane Campinas 6fde1db228
chore: update the Javadoc example in Analyzer (#12693)
Close #12666
2023-10-18 10:19:19 -04:00
iverase 723c05b047 coorect position on entry in CHANGES.txt 2023-10-18 08:14:56 +02:00
Ignacio Vera 17ea6d5a0d
Refactor ByteBlockPool so it is just a "shift/mask big array" (#12625)
Moved all the hairy allocSlice stuff as static method in TermsHashPerField and I introduce a BytesRefBlockPool to
 encapsulate of the BytesRefHash write/read logic.
2023-10-18 08:10:48 +02:00
Benjamin Trent ea272d0eda
Extract the hnsw graph merging from being part of the vector writer (#12657)
While working on the quantization codec & thinking about how merging will evolve, it became clearer that having merging attached directly to the vector writer is weird.

I extracted it out to its own class and removed the "initializedNodes" logic from the base class builder.

Also, there was on other refactoring around grabbing sorted nodes from the neighbor iterator, I just moved that static method so its not attached to the writer (as all bwc writers need it and all future HNSW writers will as well).
2023-10-17 13:45:25 -04:00
Adrien Grand 218eddec70
Specialize `BlockImpactsDocsEnum#nextDoc()`. (#12670)
When we initially introduced support for dynamic pruning, we had an
implementation of WAND that would almost exclusively use `advance()`. Now that
we switched to MAXSCORE and rely much more on `nextDoc()`, it makes sense to
specialize nextDoc() as well.
2023-10-17 14:13:40 +02:00
Adrien Grand f055ac6e16
Speed up TestIndexOrDocValuesQuery. (#12672)
This changes the following:
 - fewer docs indexed in non-nightly runs,
 - `QueryUtils#checkFirstSkipTo` uses the `ScorerSupplier` API to convey it
   will only check one doc,
 - `QueryUtils#checkFirstSkipTo` no longer relies on timing to run in a
   reasonably amount of time.
2023-10-17 14:13:21 +02:00
gf2121 8961dda2a4
Remove over-counting of deleted terms (#12586) 2023-10-17 19:13:24 +08:00
gf2121 da032535d6
Use MergeSorter in StableStringSorter (#12652) 2023-10-17 17:52:16 +08:00
gf2121 c6e76d3e01
Use radix sort to speed up the sorting of terms in TermInSetQuery (#12587) 2023-10-17 17:31:29 +08:00
Dawid Weiss 6dac2f7afc
Add timeouts to github jobs. Estimates taken from empirical run times (actions history), with a generous buffer added. (#12687) 2023-10-17 08:02:53 +02:00