Skip to content
Open
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
20 changes: 20 additions & 0 deletions benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,26 @@

<build>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
<inherited>true</inherited>
<configuration>
<release>${maven.compiler.release}</release>
<annotationProcessors>
<annotationProcessor>org.openjdk.jmh.generators.BenchmarkProcessor</annotationProcessor>
</annotationProcessors>
<annotationProcessorPaths combine.children="append">
<path>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.druid.math.expr.ExpressionProcessing;
import org.apache.druid.query.QueryContexts;
import org.apache.druid.query.groupby.GroupByQueryConfig;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

Expand Down Expand Up @@ -171,6 +174,9 @@ public class SqlExpressionBenchmark extends SqlBaseQueryBenchmark
})
private String deferExpressionDimensions;

@Param({"false", "true"})
private boolean useVectorApi;

@Param({
// non-expression reference
"0",
Expand Down Expand Up @@ -238,6 +244,16 @@ public class SqlExpressionBenchmark extends SqlBaseQueryBenchmark
})
private String query;

@Setup(Level.Trial)
public void setupExpressionProcessing()
{
if (useVectorApi) {
ExpressionProcessing.initializeForVectorApiTests();
} else {
ExpressionProcessing.initializeForTests();
}
}

@Override
public String getQuery()
{
Expand Down
6 changes: 5 additions & 1 deletion docs/operations/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,9 @@ added. There are many ways of doing this. Choose the one that works best for you
--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED \
--add-modules=jdk.incubator.vector
```

The `--add-modules=jdk.incubator.vector` flag is optional, but adding it makes the JDK's incubator Vector API available
to Druid to support `druid.expressions.useVectorApi=true`.
1 change: 1 addition & 0 deletions examples/bin/run-java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ then
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED \
--add-modules=jdk.incubator.vector \
"$@"
else
exec "$JAVA_BIN" "$@"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ public class ForkingTaskRunner
"--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED",
"--add-opens=java.base/java.io=ALL-UNNAMED",
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED"
"--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED",
"--add-modules=jdk.incubator.vector"
);

private final ForkingTaskRunnerConfig config;
Expand Down
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@

<!-- required for certain EqualsVerifier tests (not required in production) -->
--add-opens=java.base/java.util=ALL-UNNAMED

<!-- required for SIMD for druid.expressions.useVectorApi -->
--add-modules=jdk.incubator.vector
</jdk.strong.encapsulation.argLine>
<jdk.security.manager.allow.argLine><!-- empty placeholder --></jdk.security.manager.allow.argLine>
<repoOrgId>maven.org</repoOrgId>
Expand Down Expand Up @@ -1793,6 +1796,8 @@
<exclude>**/*_jmhType_*.class</exclude>
<exclude>**/*_jmhTest_*.class</exclude>
<exclude>**/*_generated*.class</exclude>
<!-- forbidden-apis can't resolve jdk.incubator.vector classes from its own classpath -->
<exclude>**/math/expr/vector/simd/Simd*.class</exclude>
</excludes>
<suppressAnnotations>
<annotation>**.SuppressForbidden</annotation>
Expand Down Expand Up @@ -2142,6 +2147,11 @@

<!-- HadoopFsWrapper javadocs cannot be generated due to missing annotations -->
<excludePackageNames>org.apache.hadoop.fs</excludePackageNames>

<!-- required for SIMD expression vector processors that import jdk.incubator.vector -->
<additionalOptions>
<additionalOption>--add-modules=jdk.incubator.vector</additionalOption>
</additionalOptions>
</configuration>
</plugin>
<plugin>
Expand All @@ -2151,6 +2161,9 @@
<inherited>true</inherited>
<configuration>
<release>${maven.compiler.release}</release>
<compilerArgs>
<arg>--add-modules=jdk.incubator.vector</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
Expand Down Expand Up @@ -2211,6 +2224,8 @@
<arg>-J--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>-J--add-modules=jdk.incubator.vector</arg>
<arg>--add-modules=jdk.incubator.vector</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,19 @@ public class ExpressionProcessing
@VisibleForTesting
public static void initializeForTests()
{
INSTANCE = new ExpressionProcessingConfig(null, null, null);
INSTANCE = new ExpressionProcessingConfig(null, null, null, null);
}

@VisibleForTesting
public static void initializeForHomogenizeNullMultiValueStrings()
{
INSTANCE = new ExpressionProcessingConfig(null, true, null);
INSTANCE = new ExpressionProcessingConfig(null, true, null, null);
}

@VisibleForTesting
public static void initializeForVectorApiTests()
{
INSTANCE = new ExpressionProcessingConfig(null, null, null, true);
}

/**
Expand Down Expand Up @@ -81,6 +87,18 @@ public static boolean allowVectorizeFallback()
return INSTANCE.allowVectorizeFallback();
}

/**
* Whether {@link org.apache.druid.math.expr.vector.ExprVectorProcessor} implementations may dispatch to specialized
* {@code jdk.incubator.vector} (SIMD) variants for supported math operations. Off by default; opt-in via
* {@link ExpressionProcessingConfig#USE_VECTOR_API}. Requires the JVM to be started with
* {@code --add-modules=jdk.incubator.vector}, which Druid already adds to its standard launch arguments.
*/
public static boolean useVectorApi()
{
checkInitialized();
return INSTANCE.useVectorApi();
}

private static void checkInitialized()
{
// this should only be null in a unit test context, in production this will be injected by the null handling module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class ExpressionProcessingConfig
public static final String HOMOGENIZE_NULL_MULTIVALUE_STRING_ARRAYS =
"druid.expressions.homogenizeNullMultiValueStringArrays";
public static final String ALLOW_VECTORIZE_FALLBACK = "druid.expressions.allowVectorizeFallback";
public static final String USE_VECTOR_API = "druid.expressions.useVectorApi";

@JsonProperty("processArraysAsMultiValueStrings")
private final boolean processArraysAsMultiValueStrings;
Expand All @@ -44,11 +45,15 @@ public class ExpressionProcessingConfig
@JsonProperty("allowVectorizeFallback")
private final boolean allowVectorizeFallback;

@JsonProperty("useVectorApi")
private final boolean useVectorApi;

@JsonCreator
public ExpressionProcessingConfig(
@JsonProperty("processArraysAsMultiValueStrings") @Nullable Boolean processArraysAsMultiValueStrings,
@JsonProperty("homogenizeNullMultiValueStringArrays") @Nullable Boolean homogenizeNullMultiValueStringArrays,
@JsonProperty("allowVectorizeFallback") @Nullable Boolean allowVectorizeFallback
@JsonProperty("allowVectorizeFallback") @Nullable Boolean allowVectorizeFallback,
@JsonProperty("useVectorApi") @Nullable Boolean useVectorApi
)
{
this.processArraysAsMultiValueStrings = getWithPropertyFallbackFalse(
Expand All @@ -64,6 +69,7 @@ public ExpressionProcessingConfig(
ALLOW_VECTORIZE_FALLBACK,
"true"
);
this.useVectorApi = getWithPropertyFallbackFalse(useVectorApi, USE_VECTOR_API);
}

public boolean processArraysAsMultiValueStrings()
Expand All @@ -81,6 +87,11 @@ public boolean allowVectorizeFallback()
return allowVectorizeFallback;
}

public boolean useVectorApi()
{
return useVectorApi;
}

private static boolean getWithPropertyFallbackFalse(@Nullable Boolean value, String property)
{
return getWithPropertyFallback(value, property, "false");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,72 @@
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.DoubleBivariateDoubleLongFunction;
import org.apache.druid.math.expr.vector.functional.DoubleBivariateDoublesFunction;
import org.apache.druid.math.expr.vector.functional.DoubleBivariateLongDoubleFunction;
import org.apache.druid.math.expr.vector.functional.LongBivariateLongsFunction;
import org.apache.druid.math.expr.vector.simd.SimdProcessors;
import org.apache.druid.math.expr.vector.simd.SimdSupportedBinaryOp;

import javax.annotation.Nullable;

/**
* Make a 2 argument, math processor with the following type rules
* long, long -> long
* long, double -> double
* double, long -> double
* double, double -> double
*
* If a non-null {@link SimdSupportedBinaryOp} 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 SimpleVectorMathBivariateProcessorFactory extends VectorMathBivariateProcessorFactory
{
private final LongBivariateLongsFunction longsFunction;
private final DoubleBivariateLongDoubleFunction longDoubleFunction;
private final DoubleBivariateDoubleLongFunction doubleLongFunction;
private final DoubleBivariateDoublesFunction doublesFunction;
@Nullable
private final SimdSupportedBinaryOp simdOp;

protected SimpleVectorMathBivariateProcessorFactory(
LongBivariateLongsFunction longsFunction,
DoubleBivariateLongDoubleFunction longDoubleFunction,
DoubleBivariateDoubleLongFunction doubleLongFunction,
DoubleBivariateDoublesFunction doublesFunction
)
{
this(longsFunction, longDoubleFunction, doubleLongFunction, doublesFunction, null);
}

protected SimpleVectorMathBivariateProcessorFactory(
LongBivariateLongsFunction longsFunction,
DoubleBivariateLongDoubleFunction longDoubleFunction,
DoubleBivariateDoubleLongFunction doubleLongFunction,
DoubleBivariateDoublesFunction doublesFunction,
@Nullable SimdSupportedBinaryOp simdOp
)
{
this.longsFunction = longsFunction;
this.longDoubleFunction = longDoubleFunction;
this.doubleLongFunction = doubleLongFunction;
this.doublesFunction = doublesFunction;
this.simdOp = simdOp;
}

@Override
public final ExprVectorProcessor<long[]> longsProcessor(Expr.VectorInputBindingInspector inspector, Expr left, Expr right)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeLongLong(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
simdOp,
longsFunction
);
}
return new LongBivariateLongsFunctionVectorProcessor(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
Expand All @@ -69,6 +100,14 @@ public final ExprVectorProcessor<double[]> longDoubleProcessor(
Expr right
)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeLongDouble(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
simdOp,
longDoubleFunction
);
}
return new DoubleBivariateLongDoubleFunctionVectorProcessor(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
Expand All @@ -83,6 +122,14 @@ public final ExprVectorProcessor<double[]> doubleLongProcessor(
Expr right
)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeDoubleLong(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
simdOp,
doubleLongFunction
);
}
return new DoubleBivariateDoubleLongFunctionVectorProcessor(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
Expand All @@ -97,6 +144,14 @@ public final ExprVectorProcessor<double[]> doublesProcessor(
Expr right
)
{
if (simdOp != null && ExpressionProcessing.useVectorApi()) {
return SimdProcessors.makeDoubleDouble(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
simdOp,
doublesFunction
);
}
return new DoubleBivariateDoublesFunctionVectorProcessor(
left.asVectorProcessor(inspector),
right.asVectorProcessor(inspector),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.common.primitives.Ints;
import org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.math.expr.Function;
import org.apache.druid.math.expr.vector.simd.SimdSupportedBinaryOp;

public class VectorMathProcessors
{
Expand Down Expand Up @@ -300,7 +301,7 @@ public static final class Add extends SimpleVectorMathBivariateProcessorFactory

public Add()
{
super(Long::sum, Double::sum, Double::sum, Double::sum);
super(Long::sum, Double::sum, Double::sum, Double::sum, SimdSupportedBinaryOp.ADD);
}
}

Expand All @@ -314,7 +315,8 @@ public Subtract()
(left, right) -> left - right,
(left, right) -> (double) left - right,
(left, right) -> left - (double) right,
(left, right) -> left - right
(left, right) -> left - right,
SimdSupportedBinaryOp.SUB
);
}
}
Expand All @@ -325,7 +327,13 @@ public static final class Multiply extends SimpleVectorMathBivariateProcessorFac

public Multiply()
{
super(Multiply::multiply, Multiply::multiply, Multiply::multiply, Multiply::multiply);
super(
Multiply::multiply,
Multiply::multiply,
Multiply::multiply,
Multiply::multiply,
SimdSupportedBinaryOp.MUL
);
}

private static long multiply(long x, long y)
Expand Down
Loading
Loading