RFR: 8263006: Add optimization for Max(*)Node and Min(*)Node [v2]
Wang Huang
whuang at openjdk.java.net
Thu Apr 22 01:52:20 UTC 2021
On Fri, 16 Apr 2021 01:40:01 GMT, Wang Huang <whuang at openjdk.org> wrote:
>> * I optimize `max` and `min` by using these identities
>> - op (max(a,b) , min(a,b))=== op(a,b)
>> - if op is commutable
>> - example :
>> - max(a,b) + min(a,b))=== a + b // op = add
>> - max(a,b) * min(a,b))=== a * b // op = mul
>> - max( max(a,b) , min(a,b)))=== max(a,b) // op = max()
>> - min( max(a,b) , min(a,b)))=== max(a,b) // op = min()
>> * Test case
>> ```java
>> /*
>> * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved.
>> * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> *
>> * This code is free software; you can redistribute it and/or modify it
>> * under the terms of the GNU General Public License version 2 only, as
>> * published by the Free Software Foundation.
>> *
>> * This code is distributed in the hope that it will be useful, but WITHOUT
>> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
>> * version 2 for more details (a copy is included in the LICENSE file that
>> * accompanied this code).
>> *
>> * You should have received a copy of the GNU General Public License version
>> * 2 along with this work; if not, write to the Free Software Foundation,
>> * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> *
>> * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> * or visit www.oracle.com if you need additional information or have any
>> * questions.
>> */
>> package org.sample;
>>
>> import org.openjdk.jmh.annotations.Benchmark;
>> import org.openjdk.jmh.annotations.*;
>>
>> import java.util.Random;
>> import java.util.concurrent.TimeUnit;
>> import org.openjdk.jmh.infra.Blackhole;
>>
>> @BenchmarkMode({Mode.AverageTime})
>> @OutputTimeUnit(TimeUnit.MICROSECONDS)
>> public class MyBenchmark {
>>
>> static int length = 100000;
>> static double[] data1 = new double[length];
>> static double[] data2 = new double[length];
>> static Random random = new Random();
>>
>> static {
>> for(int i = 0; i < length; ++i) {
>> data1[i] = random.nextDouble();
>> data2[i] = random.nextDouble();
>> }
>> }
>>
>> @Benchmark
>> public void testAdd(Blackhole bh) {
>> double sum = 0;
>> for (int i = 0; i < length; i++) {
>> sum += Math.max(data1[i], data2[i]) + Math.min(data1[i], data2[i]);
>> }
>> bh.consume(sum);
>> }
>>
>> @Benchmark
>> public void testMax(Blackhole bh) {
>> double sum = 0;
>> for (int i = 0; i < length; i++) {
>> sum += Math.max(Math.max(data1[i], data2[i]), Math.min(data1[i], data2[i]));
>> }
>> bh.consume(sum);
>> }
>>
>> @Benchmark
>> public void testMin(Blackhole bh) {
>> double sum = 0;
>> for (int i = 0; i < length; i++) {
>> sum += Math.min(Math.max(data1[i], data2[i]), Math.min(data1[i], data2[i]));
>> }
>> bh.consume(sum);
>> }
>>
>> @Benchmark
>> public void testMul(Blackhole bh) {
>> double sum = 0;
>> for (int i = 0; i < length; i++) {
>> sum += (Math.max(data1[i], data2[i]) * Math.min(data1[i], data2[i]));
>> }
>> bh.consume(sum);
>> }
>> }
>> ```
>>
>> * The result is listed here (aarch64):
>>
>> before:
>>
>> |Benchmark| Mode| Samples| Score| Score error| Units|
>> |---| ---| ---| ---| --- | ---|
>> |o.s.MyBenchmark.testAdd |avgt | 10 | 556.048 | 32.368 | us/op |
>> | o.s.MyBenchmark.testMax | avgt | 10 |543.065 | 54.221 | us/op |
>> | o.s.MyBenchmark.testMin | avgt |10 |570.731 | 37.630 | us/op |
>> | o.s.MyBenchmark.testMul | avgt | 10 | 531.906 | 20.518 | us/op |
>>
>> after:
>>
>> |Benchmark| Mode| Samples| Score| Score error| Units|
>> |---| ---| ---| ---| --- | ---|
>> | o.s.MyBenchmark.testAdd | avgt | 10 | 319.350 | 9.248 | us/op |
>> | o.s.MyBenchmark.testMax | avgt | 10 | 356.138 | 10.736 | us/op |
>> | o.s.MyBenchmark.testMin | avgt | 10 | 323.731 | 16.621 | us/op |
>> | o.s.MyBenchmark.testMul | avgt | 10 | 338.458 | 23.755 | us/op |
>>
>> * I have tested `NaN` ` INFINITY` and `-INFINITY` and got same result (before/after)
>
> Wang Huang has updated the pull request incrementally with one additional commit since the last revision:
>
> adjust code style
> Running MyBenchmark test listed in the summary on x86_64 Haswell XEON with this patch results in:
>
> ```
> # Benchmark: org.sample.MyBenchmark.testMax
>
> # Run progress: 25.00% complete, ETA 00:03:57
> # Fork: 1 of 1 # Warmup Iteration 1: 112.714 us/op
> # Warmup Iteration 2: # To suppress the following error report, specify this argument
> # after -XX: or in .hotspotrc: SuppressErrorAt=/register.hpp:152 #
> # A fatal error has been detected by the Java Runtime Environment:
> #
> # Internal Error (/home/mgkwill/src/git/jdk/src/hotspot/share/asm/register.hpp:152), pid=3450238, tid=3450253
> # assert(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e && d != e) failed: registers must be different: a=0x0000000000000001, b=0x0000000000000001, c=0x0000000000000003, d=0x0000000000000004, e=0x0000000000000005
> #
> # JRE version: OpenJDK Runtime Environment (17.0) (slowdebug build 17-internal+0-adhoc.mgkwill.jdk)
> ```
>
> AND
>
> ```
> # Benchmark: org.sample.MyBenchmark.testMin
>
> # Run progress: 25.00% complete, ETA 00:03:57
> # Fork: 1 of 1
> # Warmup Iteration 1: 112.445 us/op
> # Warmup Iteration 2: # To suppress the following error report, specify this argument
> # after -XX: or in .hotspotrc: SuppressErrorAt=/register.hpp:152
> #
> # A fatal error has been detected by the Java Runtime Environment:
> #
> # Internal Error (/home/mgkwill/src/git/jdk/src/hotspot/share/asm/register.hpp:152), pid=3450444, tid=3450481
> # assert(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e && d != e) failed: registers must be different: a=0x0000000000000001, b=0x0000000000000001, c=0x0000000000000003, d=0x0000000000000004, e=0x0000000000000005
> #
> # JRE version: OpenJDK Runtime Environment (17.0) (slowdebug build 17-internal+0-adhoc.mgkwill.jdk)
> ```
>
> Otherwise the results are below.
>
> ```
> Baseline
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testAdd avgt 5 149.581 ? 13.626 us/op
> MyBenchmark.testMax avgt 5 223.362 ? 195.007 us/op
> MyBenchmark.testMin avgt 5 206.096 ? 16.840 us/op
> MyBenchmark.testMul avgt 5 149.366 ? 9.558 us/op
> Finished running test 'micro:MyBenchmark'
> ```
>
> ```
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testAdd avgt 5 107.874 ? 0.148 us/op
> MyBenchmark.testMul avgt 5 107.881 ? 0.015 us/op
> Finished running test 'micro:MyBenchmark'
> ```
> MyBenchmark.testAdd avgt 5 149.581 ? 13.626 us/op
> MyBenchmark.testMax avgt 5 223.362 ? 195.007 us/op
> MyBenchmark.testMin avgt 5 206.096 ? 16.840 us/op
> MyBenchmark.testMul avgt 5 149.366 ? 9.558 us/op
I run this test case by `java -jar target/benchmarks.jar -i 10 -wi 10 -f 1 ``on ` Intel(R) Xeon(R) CPU E7-8890 v4 @ 2.20GHz` without crash. Can you give me your jvm options and this crash log? Thank you very much.
-------------
PR: https://git.openjdk.java.net/jdk/pull/3513
More information about the hotspot-compiler-dev
mailing list