Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,15 @@ public class SqlExpressionBenchmark extends SqlBaseQueryBenchmark
// 61-63: cast
"SELECT CAST(string1 as BIGINT) + CAST(string3 as DOUBLE) + long3, COUNT(*) FROM expressions GROUP BY 1 ORDER BY 2",
"SELECT COUNT(*), SUM(CAST(string1 as BIGINT) + CAST(string3 as BIGINT)) FROM expressions WHERE double3 < 1010.0 AND double3 > 100.0",
"SELECT COUNT(*) FROM expressions WHERE __time >= TIMESTAMP '2000-01-01 00:00:00' AND __time < TIMESTAMP '2000-01-02 00:00:00' AND (UPPER(COALESCE(string3,'')) LIKE '1%' OR TRIM(UPPER(COALESCE(string3,''))) LIKE '1%' OR SUBSTRING(UPPER(COALESCE(string3,'')),1,1) IN ('1','2','3','4','5') OR ('X' || UPPER(COALESCE(string3,''))) LIKE 'X1%') AND (UPPER(COALESCE(string5,'')) LIKE '2%' OR TRIM(UPPER(COALESCE(string5,''))) LIKE '2%' OR SUBSTRING(UPPER(COALESCE(string5,'')),1,1) IN ('1','2','3','4','5') OR ('Y' || UPPER(COALESCE(string5,''))) LIKE 'Y2%') AND CAST(double4 * 1000 AS BIGINT) BETWEEN -850000000 AND 850000000"
"SELECT COUNT(*) FROM expressions WHERE __time >= TIMESTAMP '2000-01-01 00:00:00' AND __time < TIMESTAMP '2000-01-02 00:00:00' AND (UPPER(COALESCE(string3,'')) LIKE '1%' OR TRIM(UPPER(COALESCE(string3,''))) LIKE '1%' OR SUBSTRING(UPPER(COALESCE(string3,'')),1,1) IN ('1','2','3','4','5') OR ('X' || UPPER(COALESCE(string3,''))) LIKE 'X1%') AND (UPPER(COALESCE(string5,'')) LIKE '2%' OR TRIM(UPPER(COALESCE(string5,''))) LIKE '2%' OR SUBSTRING(UPPER(COALESCE(string5,'')),1,1) IN ('1','2','3','4','5') OR ('Y' || UPPER(COALESCE(string5,''))) LIKE 'Y2%') AND CAST(double4 * 1000 AS BIGINT) BETWEEN -850000000 AND 850000000",
// 64,65: unary negate on a double column (companion to 15 which does long negate)
"SELECT SUM(-double1) FROM expressions",
"SELECT SUM(-double4) FROM expressions",
// 66,67: unary abs on long and double columns
"SELECT SUM(ABS(long4)) FROM expressions",
"SELECT SUM(ABS(double1)) FROM expressions",
// 68: unary abs of a binary subtraction (composes SIMD sub with SIMD abs)
"SELECT SUM(ABS(long1 - long4)) FROM expressions"
);

@Param({
Expand Down Expand Up @@ -248,7 +256,12 @@ public class SqlExpressionBenchmark extends SqlBaseQueryBenchmark
"60",
"61",
"62",
"63"
"63",
"64",
"65",
"66",
"67",
"68"
})
private String query;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,56 @@
package org.apache.druid.math.expr.vector;

import org.apache.druid.math.expr.Expr;
import org.apache.druid.math.expr.ExpressionProcessing;
import org.apache.druid.math.expr.vector.functional.DoubleUnivariateDoubleFunction;
import org.apache.druid.math.expr.vector.functional.LongUnivariateLongFunction;
import org.apache.druid.math.expr.vector.simd.SimdProcessors;
import org.apache.druid.math.expr.vector.simd.SimdSupportedUnaryOp;

import javax.annotation.Nullable;

/**
* Make a 1 argument math processor with the following type rules
* long -> long
* double -> double
* using simple scalar functions {@link LongUnivariateLongFunction} and {@link DoubleUnivariateDoubleFunction}
* using simple scalar functions {@link LongUnivariateLongFunction} and {@link DoubleUnivariateDoubleFunction}.
*
* If a non-null {@link SimdSupportedUnaryOp} is supplied to the constructor and
* {@link ExpressionProcessing#useVectorApi()} is true, this factory will return SIMD-specialized processors backed
* by the JDK incubator {@code jdk.incubator.vector} API instead of the standard scalar implementations.
*/
public class SimpleVectorMathUnivariateProcessorFactory extends VectorMathUnivariateProcessorFactory
{
private final LongUnivariateLongFunction longFunction;
private final DoubleUnivariateDoubleFunction doubleFunction;
@Nullable
private final SimdSupportedUnaryOp simdOp;

public SimpleVectorMathUnivariateProcessorFactory(
LongUnivariateLongFunction longFunction,
DoubleUnivariateDoubleFunction doubleFunction
)
{
this(longFunction, doubleFunction, null);
}

protected SimpleVectorMathUnivariateProcessorFactory(
LongUnivariateLongFunction longFunction,
DoubleUnivariateDoubleFunction doubleFunction,
@Nullable SimdSupportedUnaryOp simdOp
)
{
this.longFunction = longFunction;
this.doubleFunction = doubleFunction;
this.simdOp = simdOp;
}

@Override
public final ExprVectorProcessor<long[]> longProcessor(Expr.VectorInputBindingInspector inspector, Expr arg)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeLongUnary(arg.asVectorProcessor(inspector), simdOp, longFunction);
}
return new LongUnivariateLongFunctionVectorProcessor(
arg.asVectorProcessor(inspector),
longFunction
Expand All @@ -55,6 +79,9 @@ public final ExprVectorProcessor<long[]> longProcessor(Expr.VectorInputBindingIn
@Override
public final ExprVectorProcessor<double[]> doubleProcessor(Expr.VectorInputBindingInspector inspector, Expr arg)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeDoubleUnary(arg.asVectorProcessor(inspector), simdOp, doubleFunction);
}
return new DoubleUnivariateDoubleFunctionVectorProcessor(
arg.asVectorProcessor(inspector),
doubleFunction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.math.expr.Function;
import org.apache.druid.math.expr.vector.simd.SimdSupportedBinaryOp;
import org.apache.druid.math.expr.vector.simd.SimdSupportedUnaryOp;

public class VectorMathProcessors
{
Expand Down Expand Up @@ -411,7 +412,8 @@ public Negate()
{
super(
input -> -input,
input -> -input
input -> -input,
SimdSupportedUnaryOp.NEG
);
}
}
Expand Down Expand Up @@ -542,7 +544,7 @@ public static final class Abs extends SimpleVectorMathUnivariateProcessorFactory

public Abs()
{
super(Math::abs, Math::abs);
super(Math::abs, Math::abs, SimdSupportedUnaryOp.ABS);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.druid.math.expr.vector.simd;

import jdk.incubator.vector.DoubleVector;
import org.apache.druid.math.expr.vector.ExprVectorProcessor;
import org.apache.druid.math.expr.vector.functional.DoubleUnivariateDoubleFunction;

import java.util.Arrays;

/**
* SIMD specialization of {@code (double[]) -> double[]} absolute value. The op is hardcoded to
* {@link DoubleVector#abs} so the JIT statically resolves it to the platform's double-abs intrinsic.
*/
public final class SimdDoubleAbsProcessor extends SimdDoubleUnaryProcessor
{
public SimdDoubleAbsProcessor(ExprVectorProcessor<?> input, DoubleUnivariateDoubleFunction scalarFallback)
{
super(input, scalarFallback);
}

@Override
protected void processVector(double[] input, boolean[] inputNulls, int currentSize)
{
final int laneCount = SPECIES.length();
final int upperBound = SPECIES.loopBound(currentSize);
int i = 0;
for (; i < upperBound; i += laneCount) {
DoubleVector.fromArray(SPECIES, input, i).abs().intoArray(outValues, i);
}
for (; i < currentSize; i++) {
outValues[i] = scalarFallback.process(input[i]);
}
if (inputNulls == null) {
Arrays.fill(outNulls, 0, currentSize, false);
} else {
System.arraycopy(inputNulls, 0, outNulls, 0, currentSize);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.druid.math.expr.vector.simd;

import jdk.incubator.vector.DoubleVector;
import org.apache.druid.math.expr.vector.ExprVectorProcessor;
import org.apache.druid.math.expr.vector.functional.DoubleUnivariateDoubleFunction;

import java.util.Arrays;

/**
* SIMD specialization of {@code (double[]) -> double[]} negation. The op is hardcoded to {@link DoubleVector#neg}
* so the JIT statically resolves it to the platform's double-negate intrinsic.
*/
public final class SimdDoubleNegProcessor extends SimdDoubleUnaryProcessor
{
public SimdDoubleNegProcessor(ExprVectorProcessor<?> input, DoubleUnivariateDoubleFunction scalarFallback)
{
super(input, scalarFallback);
}

@Override
protected void processVector(double[] input, boolean[] inputNulls, int currentSize)
{
final int laneCount = SPECIES.length();
final int upperBound = SPECIES.loopBound(currentSize);
int i = 0;
for (; i < upperBound; i += laneCount) {
DoubleVector.fromArray(SPECIES, input, i).neg().intoArray(outValues, i);
}
for (; i < currentSize; i++) {
outValues[i] = scalarFallback.process(input[i]);
}
if (inputNulls == null) {
Arrays.fill(outNulls, 0, currentSize, false);
} else {
System.arraycopy(inputNulls, 0, outNulls, 0, currentSize);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.druid.math.expr.vector.simd;

import jdk.incubator.vector.DoubleVector;
import jdk.incubator.vector.VectorSpecies;
import org.apache.druid.math.expr.Expr;
import org.apache.druid.math.expr.ExpressionType;
import org.apache.druid.math.expr.vector.CastToTypeVectorProcessor;
import org.apache.druid.math.expr.vector.ExprEvalDoubleVector;
import org.apache.druid.math.expr.vector.ExprEvalVector;
import org.apache.druid.math.expr.vector.ExprVectorProcessor;
import org.apache.druid.math.expr.vector.functional.DoubleUnivariateDoubleFunction;

import javax.annotation.Nullable;

/**
* Abstract base for SIMD processors that compute {@code (double[]) -> double[]} unary ops. See
* {@link SimdLongUnaryProcessor} for the design rationale.
*/
abstract class SimdDoubleUnaryProcessor implements ExprVectorProcessor<double[]>
{
static final VectorSpecies<Double> SPECIES = DoubleVector.SPECIES_PREFERRED;

private final ExprVectorProcessor<double[]> input;
final DoubleUnivariateDoubleFunction scalarFallback;
final double[] outValues;
final boolean[] outNulls;

protected SimdDoubleUnaryProcessor(
ExprVectorProcessor<?> input,
DoubleUnivariateDoubleFunction scalarFallback
)
{
this.input = CastToTypeVectorProcessor.cast(input, ExpressionType.DOUBLE);
this.scalarFallback = scalarFallback;
this.outValues = new double[this.input.maxVectorSize()];
this.outNulls = new boolean[this.input.maxVectorSize()];
}

@Override
public final ExprEvalVector<double[]> evalVector(Expr.VectorInputBinding bindings)
{
final ExprEvalVector<double[]> lhs = input.evalVector(bindings);
processVector(lhs.values(), lhs.getNullVector(), bindings.getCurrentVectorSize());
return new ExprEvalDoubleVector(outValues, outNulls);
}

protected abstract void processVector(double[] input, @Nullable boolean[] inputNulls, int currentSize);

@Override
public final ExpressionType getOutputType()
{
return ExpressionType.DOUBLE;
}

@Override
public final int maxVectorSize()
{
return outValues.length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.druid.math.expr.vector.simd;

import jdk.incubator.vector.LongVector;
import org.apache.druid.math.expr.vector.ExprVectorProcessor;
import org.apache.druid.math.expr.vector.functional.LongUnivariateLongFunction;

import java.util.Arrays;

/**
* SIMD specialization of {@code (long[]) -> long[]} absolute value. The op is hardcoded to {@link LongVector#abs}
* so the JIT statically resolves it to the platform's long-abs intrinsic.
*/
public final class SimdLongAbsProcessor extends SimdLongUnaryProcessor
{
public SimdLongAbsProcessor(ExprVectorProcessor<?> input, LongUnivariateLongFunction scalarFallback)
{
super(input, scalarFallback);
}

@Override
protected void processVector(long[] input, boolean[] inputNulls, int currentSize)
{
final int laneCount = SPECIES.length();
final int upperBound = SPECIES.loopBound(currentSize);
int i = 0;
for (; i < upperBound; i += laneCount) {
LongVector.fromArray(SPECIES, input, i).abs().intoArray(outValues, i);
}
for (; i < currentSize; i++) {
outValues[i] = scalarFallback.process(input[i]);
}
if (inputNulls == null) {
Arrays.fill(outNulls, 0, currentSize, false);
} else {
System.arraycopy(inputNulls, 0, outNulls, 0, currentSize);
}
}
}
Loading
Loading