1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have 21 * questions. 22 */ 23 24 package benchmark.jdk.incubator.vector; 25 26 import java.util.concurrent.TimeUnit; 27 import java.util.function.IntFunction; 28 29 import org.openjdk.jmh.annotations.*; 30 31 @BenchmarkMode(Mode.Throughput) 32 @OutputTimeUnit(TimeUnit.MILLISECONDS) 33 @State(Scope.Benchmark) 34 @Warmup(iterations = 3, time = 1) 35 @Measurement(iterations = 5, time = 1) 36 @Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"}) 37 public class DoubleScalar extends AbstractVectorBenchmark { 38 @Param("1024") 39 int size; 40 41 double[] fill(IntFunction<Double> f) { 42 double[] array = new double[size]; 43 for (int i = 0; i < array.length; i++) { 44 array[i] = f.apply(i); 45 } 46 return array; 47 } 48 49 double[] as, bs, cs, rs; 50 boolean[] ms, rms; 51 int[] ss; 52 53 @Setup 54 public void init() { 55 as = fill(i -> (double)(2*i)); 56 bs = fill(i -> (double)(i+1)); 57 cs = fill(i -> (double)(i+5)); 58 rs = fill(i -> (double)0); 59 ms = fillMask(size, i -> (i % 2) == 0); 60 rms = fillMask(size, i -> false); 61 62 ss = fillInt(size, i -> RANDOM.nextInt(Math.max(i,1))); 63 } 64 65 final IntFunction<double[]> fa = vl -> as; 66 final IntFunction<double[]> fb = vl -> bs; 67 final IntFunction<double[]> fc = vl -> cs; 68 final IntFunction<double[]> fr = vl -> rs; 69 final IntFunction<boolean[]> fm = vl -> ms; 70 final IntFunction<boolean[]> fmr = vl -> rms; 71 final IntFunction<int[]> fs = vl -> ss; 72 73 74 @Benchmark 75 public Object add() { 76 double[] as = fa.apply(size); 77 double[] bs = fb.apply(size); 78 double[] rs = fr.apply(size); 79 80 for (int i = 0; i < as.length; i++) { 81 double a = as[i]; 82 double b = bs[i]; 83 rs[i] = (double)(a + b); 84 } 85 86 return rs; 87 } 88 89 @Benchmark 90 public Object addMasked() { 91 double[] as = fa.apply(size); 92 double[] bs = fb.apply(size); 93 double[] rs = fr.apply(size); 94 boolean[] ms = fm.apply(size); 95 96 for (int i = 0; i < as.length; i++) { 97 double a = as[i]; 98 double b = bs[i]; 99 if (ms[i % ms.length]) { 100 rs[i] = (double)(a + b); 101 } else { 102 rs[i] = a; 103 } 104 } 105 return rs; 106 } 107 108 @Benchmark 109 public Object sub() { 110 double[] as = fa.apply(size); 111 double[] bs = fb.apply(size); 112 double[] rs = fr.apply(size); 113 114 for (int i = 0; i < as.length; i++) { 115 double a = as[i]; 116 double b = bs[i]; 117 rs[i] = (double)(a - b); 118 } 119 120 return rs; 121 } 122 123 @Benchmark 124 public Object subMasked() { 125 double[] as = fa.apply(size); 126 double[] bs = fb.apply(size); 127 double[] rs = fr.apply(size); 128 boolean[] ms = fm.apply(size); 129 130 for (int i = 0; i < as.length; i++) { 131 double a = as[i]; 132 double b = bs[i]; 133 if (ms[i % ms.length]) { 134 rs[i] = (double)(a - b); 135 } else { 136 rs[i] = a; 137 } 138 } 139 return rs; 140 } 141 142 143 @Benchmark 144 public Object div() { 145 double[] as = fa.apply(size); 146 double[] bs = fb.apply(size); 147 double[] rs = fr.apply(size); 148 149 for (int i = 0; i < as.length; i++) { 150 double a = as[i]; 151 double b = bs[i]; 152 rs[i] = (double)(a / b); 153 } 154 155 return rs; 156 } 157 158 159 160 @Benchmark 161 public Object divMasked() { 162 double[] as = fa.apply(size); 163 double[] bs = fb.apply(size); 164 double[] rs = fr.apply(size); 165 boolean[] ms = fm.apply(size); 166 167 for (int i = 0; i < as.length; i++) { 168 double a = as[i]; 169 double b = bs[i]; 170 if (ms[i % ms.length]) { 171 rs[i] = (double)(a / b); 172 } else { 173 rs[i] = a; 174 } 175 } 176 return rs; 177 } 178 179 180 @Benchmark 181 public Object mul() { 182 double[] as = fa.apply(size); 183 double[] bs = fb.apply(size); 184 double[] rs = fr.apply(size); 185 186 for (int i = 0; i < as.length; i++) { 187 double a = as[i]; 188 double b = bs[i]; 189 rs[i] = (double)(a * b); 190 } 191 192 return rs; 193 } 194 195 @Benchmark 196 public Object mulMasked() { 197 double[] as = fa.apply(size); 198 double[] bs = fb.apply(size); 199 double[] rs = fr.apply(size); 200 boolean[] ms = fm.apply(size); 201 202 for (int i = 0; i < as.length; i++) { 203 double a = as[i]; 204 double b = bs[i]; 205 if (ms[i % ms.length]) { 206 rs[i] = (double)(a * b); 207 } else { 208 rs[i] = a; 209 } 210 } 211 return rs; 212 } 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 @Benchmark 245 public Object max() { 246 double[] as = fa.apply(size); 247 double[] bs = fb.apply(size); 248 double[] rs = fr.apply(size); 249 250 for (int i = 0; i < as.length; i++) { 251 double a = as[i]; 252 double b = bs[i]; 253 rs[i] = (double)(Math.max(a, b)); 254 } 255 256 return rs; 257 } 258 259 @Benchmark 260 public Object min() { 261 double[] as = fa.apply(size); 262 double[] bs = fb.apply(size); 263 double[] rs = fr.apply(size); 264 265 for (int i = 0; i < as.length; i++) { 266 double a = as[i]; 267 double b = bs[i]; 268 rs[i] = (double)(Math.min(a, b)); 269 } 270 271 return rs; 272 } 273 274 275 276 277 @Benchmark 278 public double addAll() { 279 double[] as = fa.apply(size); 280 double r = 0; 281 for (int i = 0; i < as.length; i++) { 282 r += as[i]; 283 } 284 return r; 285 } 286 287 @Benchmark 288 public double mulAll() { 289 double[] as = fa.apply(size); 290 double r = 1; 291 for (int i = 0; i < as.length; i++) { 292 r *= as[i]; 293 } 294 return r; 295 } 296 297 @Benchmark 298 public double minAll() { 299 double[] as = fa.apply(size); 300 double r = Double.POSITIVE_INFINITY; 301 for (int i = 0; i < as.length; i++) { 302 r = (double)Math.min(r, as[i]); 303 } 304 return r; 305 } 306 307 @Benchmark 308 public double maxAll() { 309 double[] as = fa.apply(size); 310 double r = Double.NEGATIVE_INFINITY; 311 for (int i = 0; i < as.length; i++) { 312 r = (double)Math.max(r, as[i]); 313 } 314 return r; 315 } 316 317 318 319 @Benchmark 320 public boolean lessThan() { 321 double[] as = fa.apply(size); 322 double[] bs = fb.apply(size); 323 324 boolean r = false; 325 for (int i = 0; i < as.length; i++) { 326 boolean m = (as[i] < bs[i]); 327 r |= m; // accumulate so JIT can't eliminate the computation 328 } 329 330 return r; 331 } 332 333 @Benchmark 334 public boolean greaterThan() { 335 double[] as = fa.apply(size); 336 double[] bs = fb.apply(size); 337 338 boolean r = false; 339 for (int i = 0; i < as.length; i++) { 340 boolean m = (as[i] > bs[i]); 341 r |= m; // accumulate so JIT can't eliminate the computation 342 } 343 344 return r; 345 } 346 347 @Benchmark 348 public boolean equal() { 349 double[] as = fa.apply(size); 350 double[] bs = fb.apply(size); 351 352 boolean r = false; 353 for (int i = 0; i < as.length; i++) { 354 boolean m = (as[i] == bs[i]); 355 r |= m; // accumulate so JIT can't eliminate the computation 356 } 357 358 return r; 359 } 360 361 @Benchmark 362 public boolean notEqual() { 363 double[] as = fa.apply(size); 364 double[] bs = fb.apply(size); 365 366 boolean r = false; 367 for (int i = 0; i < as.length; i++) { 368 boolean m = (as[i] != bs[i]); 369 r |= m; // accumulate so JIT can't eliminate the computation 370 } 371 372 return r; 373 } 374 375 @Benchmark 376 public boolean lessThanEq() { 377 double[] as = fa.apply(size); 378 double[] bs = fb.apply(size); 379 380 boolean r = false; 381 for (int i = 0; i < as.length; i++) { 382 boolean m = (as[i] <= bs[i]); 383 r |= m; // accumulate so JIT can't eliminate the computation 384 } 385 386 return r; 387 } 388 389 @Benchmark 390 public boolean greaterThanEq() { 391 double[] as = fa.apply(size); 392 double[] bs = fb.apply(size); 393 394 boolean r = false; 395 for (int i = 0; i < as.length; i++) { 396 boolean m = (as[i] >= bs[i]); 397 r |= m; // accumulate so JIT can't eliminate the computation 398 } 399 400 return r; 401 } 402 403 @Benchmark 404 public Object blend() { 405 double[] as = fa.apply(size); 406 double[] bs = fb.apply(size); 407 double[] rs = fr.apply(size); 408 boolean[] ms = fm.apply(size); 409 410 for (int i = 0; i < as.length; i++) { 411 double a = as[i]; 412 double b = bs[i]; 413 boolean m = ms[i % ms.length]; 414 rs[i] = (m ? b : a); 415 } 416 417 return rs; 418 } 419 Object rearrangeShared(int window) { 420 double[] as = fa.apply(size); 421 int[] order = fs.apply(size); 422 double[] rs = fr.apply(size); 423 424 for (int i = 0; i < as.length; i += window) { 425 for (int j = 0; j < window; j++) { 426 double a = as[i+j]; 427 int pos = order[j]; 428 rs[i + pos] = a; 429 } 430 } 431 432 return rs; 433 } 434 435 @Benchmark 436 public Object rearrange064() { 437 int window = 64 / Double.SIZE; 438 return rearrangeShared(window); 439 } 440 441 @Benchmark 442 public Object rearrange128() { 443 int window = 128 / Double.SIZE; 444 return rearrangeShared(window); 445 } 446 447 @Benchmark 448 public Object rearrange256() { 449 int window = 256 / Double.SIZE; 450 return rearrangeShared(window); 451 } 452 453 @Benchmark 454 public Object rearrange512() { 455 int window = 512 / Double.SIZE; 456 return rearrangeShared(window); 457 } 458 459 460 @Benchmark 461 public Object sin() { 462 double[] as = fa.apply(size); 463 double[] rs = fr.apply(size); 464 465 for (int i = 0; i < as.length; i++) { 466 double a = as[i]; 467 rs[i] = (double)(Math.sin((double)a)); 468 } 469 470 return rs; 471 } 472 473 474 475 @Benchmark 476 public Object exp() { 477 double[] as = fa.apply(size); 478 double[] rs = fr.apply(size); 479 480 for (int i = 0; i < as.length; i++) { 481 double a = as[i]; 482 rs[i] = (double)(Math.exp((double)a)); 483 } 484 485 return rs; 486 } 487 488 489 490 @Benchmark 491 public Object log1p() { 492 double[] as = fa.apply(size); 493 double[] rs = fr.apply(size); 494 495 for (int i = 0; i < as.length; i++) { 496 double a = as[i]; 497 rs[i] = (double)(Math.log1p((double)a)); 498 } 499 500 return rs; 501 } 502 503 504 505 @Benchmark 506 public Object log() { 507 double[] as = fa.apply(size); 508 double[] rs = fr.apply(size); 509 510 for (int i = 0; i < as.length; i++) { 511 double a = as[i]; 512 rs[i] = (double)(Math.log((double)a)); 513 } 514 515 return rs; 516 } 517 518 519 520 @Benchmark 521 public Object log10() { 522 double[] as = fa.apply(size); 523 double[] rs = fr.apply(size); 524 525 for (int i = 0; i < as.length; i++) { 526 double a = as[i]; 527 rs[i] = (double)(Math.log10((double)a)); 528 } 529 530 return rs; 531 } 532 533 534 535 @Benchmark 536 public Object expm1() { 537 double[] as = fa.apply(size); 538 double[] rs = fr.apply(size); 539 540 for (int i = 0; i < as.length; i++) { 541 double a = as[i]; 542 rs[i] = (double)(Math.expm1((double)a)); 543 } 544 545 return rs; 546 } 547 548 549 550 @Benchmark 551 public Object cos() { 552 double[] as = fa.apply(size); 553 double[] rs = fr.apply(size); 554 555 for (int i = 0; i < as.length; i++) { 556 double a = as[i]; 557 rs[i] = (double)(Math.cos((double)a)); 558 } 559 560 return rs; 561 } 562 563 564 565 @Benchmark 566 public Object tan() { 567 double[] as = fa.apply(size); 568 double[] rs = fr.apply(size); 569 570 for (int i = 0; i < as.length; i++) { 571 double a = as[i]; 572 rs[i] = (double)(Math.tan((double)a)); 573 } 574 575 return rs; 576 } 577 578 579 580 @Benchmark 581 public Object sinh() { 582 double[] as = fa.apply(size); 583 double[] rs = fr.apply(size); 584 585 for (int i = 0; i < as.length; i++) { 586 double a = as[i]; 587 rs[i] = (double)(Math.sinh((double)a)); 588 } 589 590 return rs; 591 } 592 593 594 595 @Benchmark 596 public Object cosh() { 597 double[] as = fa.apply(size); 598 double[] rs = fr.apply(size); 599 600 for (int i = 0; i < as.length; i++) { 601 double a = as[i]; 602 rs[i] = (double)(Math.cosh((double)a)); 603 } 604 605 return rs; 606 } 607 608 609 610 @Benchmark 611 public Object tanh() { 612 double[] as = fa.apply(size); 613 double[] rs = fr.apply(size); 614 615 for (int i = 0; i < as.length; i++) { 616 double a = as[i]; 617 rs[i] = (double)(Math.tanh((double)a)); 618 } 619 620 return rs; 621 } 622 623 624 625 @Benchmark 626 public Object asin() { 627 double[] as = fa.apply(size); 628 double[] rs = fr.apply(size); 629 630 for (int i = 0; i < as.length; i++) { 631 double a = as[i]; 632 rs[i] = (double)(Math.asin((double)a)); 633 } 634 635 return rs; 636 } 637 638 639 640 @Benchmark 641 public Object acos() { 642 double[] as = fa.apply(size); 643 double[] rs = fr.apply(size); 644 645 for (int i = 0; i < as.length; i++) { 646 double a = as[i]; 647 rs[i] = (double)(Math.acos((double)a)); 648 } 649 650 return rs; 651 } 652 653 654 655 @Benchmark 656 public Object atan() { 657 double[] as = fa.apply(size); 658 double[] rs = fr.apply(size); 659 660 for (int i = 0; i < as.length; i++) { 661 double a = as[i]; 662 rs[i] = (double)(Math.atan((double)a)); 663 } 664 665 return rs; 666 } 667 668 669 670 @Benchmark 671 public Object cbrt() { 672 double[] as = fa.apply(size); 673 double[] rs = fr.apply(size); 674 675 for (int i = 0; i < as.length; i++) { 676 double a = as[i]; 677 rs[i] = (double)(Math.cbrt((double)a)); 678 } 679 680 return rs; 681 } 682 683 684 685 @Benchmark 686 public Object hypot() { 687 double[] as = fa.apply(size); 688 double[] bs = fb.apply(size); 689 double[] rs = fr.apply(size); 690 691 for (int i = 0; i < as.length; i++) { 692 double a = as[i]; 693 double b = bs[i]; 694 rs[i] = (double)(Math.hypot((double)a, (double)b)); 695 } 696 697 return rs; 698 } 699 700 701 702 @Benchmark 703 public Object pow() { 704 double[] as = fa.apply(size); 705 double[] bs = fb.apply(size); 706 double[] rs = fr.apply(size); 707 708 for (int i = 0; i < as.length; i++) { 709 double a = as[i]; 710 double b = bs[i]; 711 rs[i] = (double)(Math.pow((double)a, (double)b)); 712 } 713 714 return rs; 715 } 716 717 718 719 @Benchmark 720 public Object atan2() { 721 double[] as = fa.apply(size); 722 double[] bs = fb.apply(size); 723 double[] rs = fr.apply(size); 724 725 for (int i = 0; i < as.length; i++) { 726 double a = as[i]; 727 double b = bs[i]; 728 rs[i] = (double)(Math.atan2((double)a, (double)b)); 729 } 730 731 return rs; 732 } 733 734 735 736 @Benchmark 737 public Object fma() { 738 double[] as = fa.apply(size); 739 double[] bs = fb.apply(size); 740 double[] cs = fc.apply(size); 741 double[] rs = fr.apply(size); 742 743 for (int i = 0; i < as.length; i++) { 744 double a = as[i]; 745 double b = bs[i]; 746 double c = cs[i]; 747 rs[i] = (double)(Math.fma(a, b, c)); 748 } 749 750 return rs; 751 } 752 753 754 755 756 @Benchmark 757 public Object fmaMasked() { 758 double[] as = fa.apply(size); 759 double[] bs = fb.apply(size); 760 double[] cs = fc.apply(size); 761 double[] rs = fr.apply(size); 762 boolean[] ms = fm.apply(size); 763 764 for (int i = 0; i < as.length; i++) { 765 double a = as[i]; 766 double b = bs[i]; 767 double c = cs[i]; 768 if (ms[i % ms.length]) { 769 rs[i] = (double)(Math.fma(a, b, c)); 770 } else { 771 rs[i] = a; 772 } 773 } 774 return rs; 775 } 776 777 778 @Benchmark 779 public Object neg() { 780 double[] as = fa.apply(size); 781 double[] rs = fr.apply(size); 782 783 for (int i = 0; i < as.length; i++) { 784 double a = as[i]; 785 rs[i] = (double)(-((double)a)); 786 } 787 788 return rs; 789 } 790 791 @Benchmark 792 public Object negMasked() { 793 double[] as = fa.apply(size); 794 double[] rs = fr.apply(size); 795 boolean[] ms = fm.apply(size); 796 797 for (int i = 0; i < as.length; i++) { 798 double a = as[i]; 799 boolean m = ms[i % ms.length]; 800 rs[i] = (m ? (double)(-((double)a)) : a); 801 } 802 803 return rs; 804 } 805 806 @Benchmark 807 public Object abs() { 808 double[] as = fa.apply(size); 809 double[] rs = fr.apply(size); 810 811 for (int i = 0; i < as.length; i++) { 812 double a = as[i]; 813 rs[i] = (double)(Math.abs((double)a)); 814 } 815 816 return rs; 817 } 818 819 @Benchmark 820 public Object absMasked() { 821 double[] as = fa.apply(size); 822 double[] rs = fr.apply(size); 823 boolean[] ms = fm.apply(size); 824 825 for (int i = 0; i < as.length; i++) { 826 double a = as[i]; 827 boolean m = ms[i % ms.length]; 828 rs[i] = (m ? (double)(Math.abs((double)a)) : a); 829 } 830 831 return rs; 832 } 833 834 835 836 837 @Benchmark 838 public Object sqrt() { 839 double[] as = fa.apply(size); 840 double[] rs = fr.apply(size); 841 842 for (int i = 0; i < as.length; i++) { 843 double a = as[i]; 844 rs[i] = (double)(Math.sqrt((double)a)); 845 } 846 847 return rs; 848 } 849 850 851 852 @Benchmark 853 public Object sqrtMasked() { 854 double[] as = fa.apply(size); 855 double[] rs = fr.apply(size); 856 boolean[] ms = fm.apply(size); 857 858 for (int i = 0; i < as.length; i++) { 859 double a = as[i]; 860 boolean m = ms[i % ms.length]; 861 rs[i] = (m ? (double)(Math.sqrt((double)a)) : a); 862 } 863 864 return rs; 865 } 866 867 868 @Benchmark 869 public Object gatherBase0() { 870 double[] as = fa.apply(size); 871 int[] is = fs.apply(size); 872 double[] rs = fr.apply(size); 873 874 for (int i = 0; i < as.length; i++) { 875 int ix = 0 + is[i]; 876 rs[i] = as[ix]; 877 } 878 879 return rs; 880 } 881 882 883 Object gather(int window) { 884 double[] as = fa.apply(size); 885 int[] is = fs.apply(size); 886 double[] rs = fr.apply(size); 887 888 for (int i = 0; i < as.length; i += window) { 889 for (int j = 0; j < window; j++) { 890 int ix = i + is[i + j]; 891 rs[i + j] = as[ix]; 892 } 893 } 894 895 return rs; 896 } 897 898 @Benchmark 899 public Object gather064() { 900 int window = 64 / Double.SIZE; 901 return gather(window); 902 } 903 904 @Benchmark 905 public Object gather128() { 906 int window = 128 / Double.SIZE; 907 return gather(window); 908 } 909 910 @Benchmark 911 public Object gather256() { 912 int window = 256 / Double.SIZE; 913 return gather(window); 914 } 915 916 @Benchmark 917 public Object gather512() { 918 int window = 512 / Double.SIZE; 919 return gather(window); 920 } 921 922 923 924 @Benchmark 925 public Object scatterBase0() { 926 double[] as = fa.apply(size); 927 int[] is = fs.apply(size); 928 double[] rs = fr.apply(size); 929 930 for (int i = 0; i < as.length; i++) { 931 int ix = 0 + is[i]; 932 rs[ix] = as[i]; 933 } 934 935 return rs; 936 } 937 938 Object scatter(int window) { 939 double[] as = fa.apply(size); 940 int[] is = fs.apply(size); 941 double[] rs = fr.apply(size); 942 943 for (int i = 0; i < as.length; i += window) { 944 for (int j = 0; j < window; j++) { 945 int ix = i + is[i + j]; 946 rs[ix] = as[i + j]; 947 } 948 } 949 950 return rs; 951 } 952 953 @Benchmark 954 public Object scatter064() { 955 int window = 64 / Double.SIZE; 956 return scatter(window); 957 } 958 959 @Benchmark 960 public Object scatter128() { 961 int window = 128 / Double.SIZE; 962 return scatter(window); 963 } 964 965 @Benchmark 966 public Object scatter256() { 967 int window = 256 / Double.SIZE; 968 return scatter(window); 969 } 970 971 @Benchmark 972 public Object scatter512() { 973 int window = 512 / Double.SIZE; 974 return scatter(window); 975 } 976 977 } 978