From 148236a50b215cfa117006f0a67b530fb276ca6f Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Fri, 16 Jun 2023 12:28:29 +0200 Subject: [PATCH] This allows VectorUtilProvider tests to be executed although hardware may not fully support vectorization or if C2 is not enabled (#12376) --- .../org/apache/lucene/util/VectorUtil.java | 3 +-- .../lucene/util/VectorUtilProvider.java | 9 ++++---- .../lucene/util/VectorUtilPanamaProvider.java | 22 ++++++++++++------- .../lucene/util/TestVectorUtilProviders.java | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java b/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java index c9e1d368334..0921bb75a66 100644 --- a/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java +++ b/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java @@ -20,8 +20,7 @@ package org.apache.lucene.util; /** Utilities for computations with numeric arrays */ public final class VectorUtil { - // visible for testing - static final VectorUtilProvider PROVIDER = VectorUtilProvider.lookup(); + private static final VectorUtilProvider PROVIDER = VectorUtilProvider.lookup(false); private VectorUtil() {} diff --git a/lucene/core/src/java/org/apache/lucene/util/VectorUtilProvider.java b/lucene/core/src/java/org/apache/lucene/util/VectorUtilProvider.java index ee5547f66a6..3fd29c2bf34 100644 --- a/lucene/core/src/java/org/apache/lucene/util/VectorUtilProvider.java +++ b/lucene/core/src/java/org/apache/lucene/util/VectorUtilProvider.java @@ -54,7 +54,7 @@ interface VectorUtilProvider { /** The minimal version of Java that has the bugfix for JDK-8301190. */ static final Version VERSION_JDK8301190_FIXED = Version.parse("20.0.2"); - static VectorUtilProvider lookup() { + static VectorUtilProvider lookup(boolean testMode) { final int runtimeVersion = Runtime.version().feature(); if (runtimeVersion >= 20 && runtimeVersion <= 21) { // is locale sane (only buggy in Java 20) @@ -71,7 +71,7 @@ interface VectorUtilProvider { "Java vector incubator module is not readable. For optimal vector performance, pass '--add-modules jdk.incubator.vector' to enable Vector API."); return new VectorUtilDefaultProvider(); } - if (isClientVM()) { + if (!testMode && isClientVM()) { LOG.warning("C2 compiler is disabled; Java vector incubator API can't be enabled"); return new VectorUtilDefaultProvider(); } @@ -80,9 +80,10 @@ interface VectorUtilProvider { // have private access through the lookup: final var lookup = MethodHandles.lookup(); final var cls = lookup.findClass("org.apache.lucene.util.VectorUtilPanamaProvider"); - final var constr = lookup.findConstructor(cls, MethodType.methodType(void.class)); + final var constr = + lookup.findConstructor(cls, MethodType.methodType(void.class, boolean.class)); try { - return (VectorUtilProvider) constr.invoke(); + return (VectorUtilProvider) constr.invoke(testMode); } catch (UnsupportedOperationException uoe) { // not supported because preferred vector size too small or similar LOG.warning("Java vector incubator API was not enabled. " + uoe.getMessage()); diff --git a/lucene/core/src/java20/org/apache/lucene/util/VectorUtilPanamaProvider.java b/lucene/core/src/java20/org/apache/lucene/util/VectorUtilPanamaProvider.java index 61ec15e0d22..a1a5a404223 100644 --- a/lucene/core/src/java20/org/apache/lucene/util/VectorUtilPanamaProvider.java +++ b/lucene/core/src/java20/org/apache/lucene/util/VectorUtilPanamaProvider.java @@ -43,8 +43,7 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { *

it could be that it has only AVX1 and integer vectors are fast. it could also be that it has * no AVX and integer vectors are extremely slow. don't use integer vectors to avoid landmines. */ - private static final boolean IS_AMD64_WITHOUT_AVX2 = - Constants.OS_ARCH.equals("amd64") && INT_SPECIES_PREF_BIT_SIZE < 256; + private final boolean hasFastIntegerVectors; static { if (INT_SPECIES_PREF_BIT_SIZE >= 256) { @@ -67,8 +66,8 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { return AccessController.doPrivileged(action); } - VectorUtilPanamaProvider() { - if (INT_SPECIES_PREF_BIT_SIZE < 128) { + VectorUtilPanamaProvider(boolean testMode) { + if (!testMode && INT_SPECIES_PREF_BIT_SIZE < 128) { throw new UnsupportedOperationException( "Vector bit size is less than 128: " + INT_SPECIES_PREF_BIT_SIZE); } @@ -83,9 +82,16 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { "We hit initialization failure described in JDK-8309727: " + se); } + // check if the system is x86 and less than 256-bit vectors: + var isAMD64withoutAVX2 = Constants.OS_ARCH.equals("amd64") && INT_SPECIES_PREF_BIT_SIZE < 256; + this.hasFastIntegerVectors = testMode || false == isAMD64withoutAVX2; + var log = Logger.getLogger(getClass().getName()); log.info( - "Java vector incubator API enabled; uses preferredBitSize=" + INT_SPECIES_PREF_BIT_SIZE); + "Java vector incubator API enabled" + + (testMode ? " (test mode)" : "") + + "; uses preferredBitSize=" + + INT_SPECIES_PREF_BIT_SIZE); } @Override @@ -295,7 +301,7 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { int res = 0; // only vectorize if we'll at least enter the loop a single time, and we have at least 128-bit // vectors (256-bit on intel to dodge performance landmines) - if (a.length >= 16 && IS_AMD64_WITHOUT_AVX2 == false) { + if (a.length >= 16 && hasFastIntegerVectors) { // compute vectorized dot product consistent with VPDPBUSD instruction if (INT_SPECIES_PREF_BIT_SIZE >= 256) { // optimized 256/512 bit implementation, processes 8/16 bytes at a time @@ -352,7 +358,7 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { int norm2 = 0; // only vectorize if we'll at least enter the loop a single time, and we have at least 128-bit // vectors (256-bit on intel to dodge performance landmines) - if (a.length >= 16 && IS_AMD64_WITHOUT_AVX2 == false) { + if (a.length >= 16 && hasFastIntegerVectors) { if (INT_SPECIES_PREF_BIT_SIZE >= 256) { // optimized 256/512 bit implementation, processes 8/16 bytes at a time int upperBound = PREF_BYTE_SPECIES.loopBound(a.length); @@ -442,7 +448,7 @@ final class VectorUtilPanamaProvider implements VectorUtilProvider { int res = 0; // only vectorize if we'll at least enter the loop a single time, and we have at least 128-bit // vectors (256-bit on intel to dodge performance landmines) - if (a.length >= 16 && IS_AMD64_WITHOUT_AVX2 == false) { + if (a.length >= 16 && hasFastIntegerVectors) { if (INT_SPECIES_PREF_BIT_SIZE >= 256) { // optimized 256/512 bit implementation, processes 8/16 bytes at a time int upperBound = PREF_BYTE_SPECIES.loopBound(a.length); diff --git a/lucene/core/src/test/org/apache/lucene/util/TestVectorUtilProviders.java b/lucene/core/src/test/org/apache/lucene/util/TestVectorUtilProviders.java index 3aa5b76bd6d..be1205890bd 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestVectorUtilProviders.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestVectorUtilProviders.java @@ -27,7 +27,7 @@ public class TestVectorUtilProviders extends LuceneTestCase { private static final double DELTA = 1e-3; private static final VectorUtilProvider LUCENE_PROVIDER = new VectorUtilDefaultProvider(); - private static final VectorUtilProvider JDK_PROVIDER = VectorUtil.PROVIDER; + private static final VectorUtilProvider JDK_PROVIDER = VectorUtilProvider.lookup(true); private static final int[] VECTOR_SIZES = { 1, 4, 6, 8, 13, 16, 25, 32, 64, 100, 128, 207, 256, 300, 512, 702, 1024