Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ Improvements

Optimizations
---------------------
(No changes)
* GITHUB#16283: Use Panama Vector API to SIMD-evaluate fixed-cardinality sorted numeric range
queries in rangeIntoBitSet. (Costin Leau)

Bug Fixes
---------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,29 +495,6 @@ private static int fixedCardinality(
return (int) cardinality;
}

private static void sortedNumericScalarRangeIntoBitSet(
LongValues values,
int fromDoc,
int toDoc,
int cardinality,
long minValue,
long maxValue,
FixedBitSet bitSet,
int offset) {
for (int doc = fromDoc; doc < toDoc; doc++) {
long valueOffset = (long) doc * cardinality;
for (int i = 0; i < cardinality; i++) {
long value = values.get(valueOffset + i);
if (value >= minValue) {
if (value <= maxValue) {
bitSet.set(doc - offset);
}
break;
}
}
}
}

private static boolean sortedNumericMatchesRange(
LongValues values, long start, long end, long minValue, long maxValue) {
for (long valueOffset = start; valueOffset < end; valueOffset++) {
Expand Down Expand Up @@ -1906,7 +1883,7 @@ public void rangeIntoBitSet(
}
int cardinality = denseFixedCardinality;
if (cardinality > 1) {
sortedNumericScalarRangeIntoBitSet(
DOC_VALUES_RANGE_SUPPORT.sortedNumericRangeIntoBitSet(
values, fromDoc, endDoc, cardinality, minValue, maxValue, bitSet, offset);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,31 @@ void rangeIntoBitSet(
long maxValue,
FixedBitSet bitSet,
int offset);

/**
* Fills {@code bitSet} with docs in {@code [fromDoc, toDoc)} whose {@code cardinality} sorted
* values contain at least one value in {@code [minValue, maxValue]}.
*/
default void sortedNumericRangeIntoBitSet(
LongValues values,
int fromDoc,
int toDoc,
int cardinality,
long minValue,
long maxValue,
FixedBitSet bitSet,
int offset) {
for (int doc = fromDoc; doc < toDoc; doc++) {
long valueOffset = (long) doc * cardinality;
for (int i = 0; i < cardinality; i++) {
long value = values.get(valueOffset + i);
if (value >= minValue) {
if (value <= maxValue) {
bitSet.set(doc - offset);
}
break;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,60 @@ public void rangeIntoBitSet(
}
}
}

@Override
public void sortedNumericRangeIntoBitSet(
LongValues values,
int fromDoc,
int toDoc,
int cardinality,
long minValue,
long maxValue,
FixedBitSet bitSet,
int offset) {
final int vectorLen = LONG_SPECIES.length();
final int docsPerVector = vectorLen / cardinality;
Comment thread
costin marked this conversation as resolved.
if (docsPerVector == 0 || vectorLen % cardinality != 0) {
DocValuesRangeSupport.super.sortedNumericRangeIntoBitSet(
values, fromDoc, toDoc, cardinality, minValue, maxValue, bitSet, offset);
return;
}

final long[] scratch = new long[vectorLen];
final int vectorDocEnd = fromDoc + (toDoc - fromDoc) / docsPerVector * docsPerVector;
int doc = fromDoc;
for (; doc < vectorDocEnd; doc += docsPerVector) {
long valueOffset = (long) doc * cardinality;
for (int lane = 0; lane < vectorLen; lane++) {
scratch[lane] = values.get(valueOffset + lane);
}
Comment thread
costin marked this conversation as resolved.
LongVector vector = LongVector.fromArray(LONG_SPECIES, scratch, 0);
// Flat range check on all lanes. Equivalent to the scalar early-break on sorted values:
// a value outside [min,max] that is >= min must be > max, so its lane stays unset, and
// collapseToDocMask OR-reduces lanes per doc to match "any value in range" semantics.
VectorMask<Long> inRange =
vector
.compare(VectorOperators.GE, minValue)
.and(vector.compare(VectorOperators.LE, maxValue));
long docMask = collapseToDocMask(inRange.toLong(), cardinality, docsPerVector);
if (docMask != 0) {
bitSet.orMask(doc - offset, docMask, docsPerVector);
}
}

DocValuesRangeSupport.super.sortedNumericRangeIntoBitSet(
values, doc, toDoc, cardinality, minValue, maxValue, bitSet, offset);
}

private static long collapseToDocMask(long valueMask, int cardinality, int docsPerVector) {
final long valueMaskPerDoc = (1L << cardinality) - 1L;
long docMask = 0L;
for (int d = 0; d < docsPerVector; d++) {
long perDoc = (valueMask >>> (d * cardinality)) & valueMaskPerDoc;
if (perDoc != 0) {
docMask |= 1L << d;
}
}
return docMask;
}
}
Loading