JDK-8267743 : Create a separate library for x86 Intel SVML assembly intrinsics
  • Type: CSR
  • Component: hotspot
  • Sub-Component: compiler
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 17
  • Submitted: 2021-05-25
  • Updated: 2021-06-02
  • Resolved: 2021-06-02
Related Reports
CSR :  
Description
Summary
-------

Relax monotonicity requirement for Vector API transcendental math operations while keeping the accuracy requirement.

Problem
-------

The SVML implementations used by the Vector API transcendental math operations are not guaranteed to be semi-monotonic.

To maximize performance the implementations avoid branching instructions, thereby allowing an optimal sequence of vector hardware instructions to be expressed. Consequently, the implementations do not produce correctly rounded results for some inputs.

Note that the SVML implementations do, however, follow accuracy specifications of the equivalent Java operations.

Solution
--------

Remove the monotonicity guarantee for the following Vector API math operations:
SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LOG, LOG10, CBRT, SINH, COSH, TANH, EXPM1, LOG1P, ATAN2, POW, HYPOT


Specification
-------------

Please see the JavaDoc linked here and attached as docs_2.tgz:
https://cr.openjdk.java.net/~sviswanathan/CSRs/CSR_for_JDK_8265783/docs_2/api/jdk.incubator.vector/jdk/incubator/vector/VectorOperators.html

The corresponding webrev is at https://cr.openjdk.java.net/~sviswanathan/CSRs/CSR_for_JDK_8265783/webrev_2/. Also it is attached as webrev_2.tgz.

The section "Operations on floating point vectors" is changed as follows:

     * <h2>Operations on floating point vectors</h2>
     * <ul>
     * <li>Lane-wise vector operations that apply to floating point vectors
     * follow the accuracy and monotonicity specifications of the equivalent
     * Java operation or method mentioned in its documentation unless specified otherwise.
     * If the vector element type is {@code float} and the Java operation or
     * method only accepts and returns {@code double} values, then the scalar operation
     * on each lane is adapted to cast operands and the result, specifically widening
     * {@code float} operands to {@code double} operands and narrowing the {@code double}
     * result to a {@code float}.

The description for SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LOG, LOG10, CBRT, SINH, COSH, TANH, EXPM1, LOG1P, ATAN2, POW, HYPOT is changed as follows:
  

       /** Produce {@code sin(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary SIN = unary("SIN", "sin", VectorSupport.VECTOR_OP_SIN, VO_ONLYFP);
        /** Produce {@code cos(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary COS = unary("COS", "cos", VectorSupport.VECTOR_OP_COS, VO_ONLYFP);
        /** Produce {@code tan(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary TAN = unary("TAN", "tan", VectorSupport.VECTOR_OP_TAN, VO_ONLYFP);
        /** Produce {@code asin(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary ASIN = unary("ASIN", "asin", VectorSupport.VECTOR_OP_ASIN, VO_ONLYFP);
        /** Produce {@code acos(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary ACOS = unary("ACOS", "acos", VectorSupport.VECTOR_OP_ACOS, VO_ONLYFP);
        /** Produce {@code atan(a)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Unary ATAN = unary("ATAN", "atan", VectorSupport.VECTOR_OP_ATAN, VO_ONLYFP);
       /** Produce {@code exp(a)}.  Floating only.
        *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
        */
       public static final /*float*/ Unary EXP = unary("EXP", "exp", VectorSupport.VECTOR_OP_EXP, VO_ONLYFP);
       /** Produce {@code log(a)}.  Floating only.
        *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
        */
       public static final /*float*/ Unary LOG = unary("LOG", "log", VectorSupport.VECTOR_OP_LOG, VO_ONLYFP);
       /** Produce {@code log10(a)}.  Floating only.
        *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
        */
       public static final /*float*/ Unary LOG10 = unary("LOG10", "log10", VectorSupport.VECTOR_OP_LOG10, VO_ONLYFP);
      /** Produce {@code cbrt(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
      public static final /*float*/ Unary CBRT = unary("CBRT", "cbrt", VectorSupport.VECTOR_OP_CBRT, VO_ONLYFP);
      /** Produce {@code sinh(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
      public static final /*float*/ Unary SINH = unary("SINH", "sinh", VectorSupport.VECTOR_OP_SINH, VO_ONLYFP);
      /** Produce {@code cosh(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
      public static final /*float*/ Unary COSH = unary("COSH", "cosh", VectorSupport.VECTOR_OP_COSH, VO_ONLYFP);
      /** Produce {@code tanh(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
      */
      public static final /*float*/ Unary TANH = unary("TANH", "tanh", VectorSupport.VECTOR_OP_TANH, VO_ONLYFP);
      /** Produce {@code expm1(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
      public static final /*float*/ Unary EXPM1 = unary("EXPM1", "expm1", VectorSupport.VECTOR_OP_EXPM1, VO_ONLYFP);
      /** Produce {@code log1p(a)}.  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
      public static final /*float*/ Unary LOG1P = unary("LOG1P", "log1p", VectorSupport.VECTOR_OP_LOG1P, VO_ONLYFP);
      /** Produce {@code atan2(a,b)}. See  Floating only.
       *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
       */
        public static final /*float*/ Binary ATAN2 = binary("ATAN2", "atan2", VectorSupport.VECTOR_OP_ATAN2, VO_ONLYFP);
        /** Produce {@code pow(a,b)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Binary POW = binary("POW", "pow", VectorSupport.VECTOR_OP_POW, VO_ONLYFP);
        /** Produce {@code hypot(a,b)}.  Floating only.
         *  Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
         */
        public static final /*float*/ Binary HYPOT = binary("HYPOT", "hypot", VectorSupport.VECTOR_OP_HYPOT, VO_ONLYFP);


Comments
[~darcy] thank you. We do plan to revisit this area during incubation. Perhaps first by documenting the source implementations to better understand their behavior, and possibly consider additional operators that provide the same guarantees in j.l.Math (maybe the implementations are compositional?)
02-06-2021

One ulp accuracy is not particularly high accuracy, but it isn't too bad either. Semi-monotonicity is equivalent to making use there aren't uneven adjacent sections of a sidewalk for pedestrians to trip on. There are certainly reasonable use-cases that can fail/get unexpected results if the methods are not sufficiently monotonic even if they are otherwise accurate. That said, for the use-case of the vector API, the users may be assumed to have a different set of trade-offs between raw performance and usability. Moving to Approved.
02-06-2021

Updated the java doc to "Not guaranteed to be semi-monotonic" for the transcendental method. These routines are not tested for monotonicity so it will be hard for us to guarantee semi-monotonicity. Please approve.
02-06-2021

We would like to bring the performance improvement of SVML to Java Vector API. The SVML functions included as part of Java Vector API are high accuracy (within 1ulp). Accuracy is a much more important characteristic for vector math functions, than monotonicity. Performance is also extremely important for many users. These functions are highly accurate and have good performance, compared to many other implementations. They have been used in Intel compilers, in Android, and to some extent in GLIBC and OpenCL as well as by some major closed-source software vendors for about two decades now, without issues. As an example of other languages, SVML routines are also available with Python���s numba JIT: https://software.intel.com/content/www/us/en/develop/articles/intel-optimized-packages-for-the-intel-distribution-for-python.html https://numba.readthedocs.io/en/stable/user/performance-tips.html#intel-svml
02-06-2021

It's performance vs. guaranteed semi-monotonicity for all inputs. In this case performance wins, given the use cases of the Vector API, which are aligned with use cases of Intel's SVML library. My understanding is it's not possible to reliably and concisely specify under what conditions semi-monotonicity is not guaranteed. So the best we can do is is make the more general statement.
26-05-2021

Moving to Provisional, *not* Approved. In general, java.lang.Math also does not require "correctly rounded" behavior. The *semi*-monotonicity requirement is an additional ease of use guarantee for users. It would be disappointing if functions like log or exp were not semi-monotonic.
26-05-2021