Commit dcd83ac
committed
Rework MersenneTwisterEngine using Ilya Yaroshenko's faster algorithm
This patch updates MersenneTwisterEngine's implementation to use the new
and much faster implementation Ilya prepared for `mir.random`.
The original Mersenne Twister algorithm (as per the reference C code by
Matsumoto and Nishimura) first regenerates the contents of the entire
state array, before looping over the resulting values and tempering them
in order to generate the actual variates. Once the entire state array
has been iterated over, the array's values are then regenerated, and so
on and so forth.
Ilya's implementation reworks this idea to intertwine update of a single
entry in the state array with the tempering of another value to produce
the next variate. This ensures that all the registers concerned stay
'hot' in the CPU's memory and hence ensures significant speedup.
(Just as a mention: as an experiment while adapting this code for phobos
I tried splitting apart the lines responsible for updating the internal
state array from those responsible for tempering the next variate, so
that they could be run sequentially instead of mixed up together; this
resulted in a fairly significant speed hit.)
In contrast to most (all?) other Mersenne Twister implementations, this
one iterates backwards through the state array, which allows for a few
extra compiler optimizations that speed up the algorithm. It has thus
been necessary to rework the range-based `seed` method to take account
of this.
Besides the algorithmic change, this patch introduces two new template
variables: an extra tempering variable `d`, and the initialization
multiplier `f`, which brings the template implementation in line with
that of the C++11 standard. These extra template variables are needed
in order to effectively implement the standard 64-bit version of the
Mersenne Twister, which will be added in a follow-up patch.
Finally, this implementation introduces corrections to the handling of
the word size `w` to ensure that the right sequences are produced when
the word size is less than the number of bits in `UIntType`. Unittests
will be added for this in a follow-up patch.
------------------------------------------------------------------------
Where this implementation differs from that in `mir.random`:
Ilya's original design has been reworked as a drop-in replacement for
the existing Phobos implementation, which is currently implemented as a
forward range (although it should ideally be an input range, but that
design flaw should be fixed as a separate issue).
There appears to be no significant speed hit from reworking Ilya's code
as a range rather than as a functor. However, some other aspects of the
original design have required rather intrusive changes in order to get
the full speed benefits without introducing breaking change.
The original MersenneTwisterEngine allows for implicit instantiation of
generator instances without providing a seed. This is handled by
checking in the `front` and `popFront` method whether the generator has
been properly initialized, and seeding it with the default seed if not.
However, these runtime checks on every single call result in a massive
speed hit. The current implementation therefore takes a number of steps
in order to ensure that the internal state of the generator can be set
to its default-seeded values at compile time:
* all the internal state variables have been wrapped up in a nested
`State` struct to facilitate generation;
* the internals of the `seed` and `popFront` methods have been
separated out into CTFE'able private static methods (`seedImpl`
and `popFrontImpl`) which take a reference to a `State` instance
as input;
* a CTFE'able private static `defaultState` method has been added
which generates a `State` instance matching that generated by
instantiating the generator with the `defaultSeed`.
The `defaultState` method is then used to initialize the default value
of the internal `State` instance at compile-time, replicating the effect
of the original runtime seeding check.
These latter workarounds could be removed in future if the generator
were updated to `@disable this();` and therefore always require explicit
seeding, but this would be a breaking change and so is avoided for now.1 parent 73e262a commit dcd83ac
1 file changed
+184
-86
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
47 | 48 | | |
48 | 49 | | |
49 | 50 | | |
| |||
527 | 528 | | |
528 | 529 | | |
529 | 530 | | |
530 | | - | |
| 531 | + | |
531 | 532 | | |
532 | | - | |
| 533 | + | |
533 | 534 | | |
534 | 535 | | |
535 | 536 | | |
536 | 537 | | |
537 | 538 | | |
538 | 539 | | |
539 | 540 | | |
| 541 | + | |
540 | 542 | | |
541 | 543 | | |
542 | 544 | | |
| |||
549 | 551 | | |
550 | 552 | | |
551 | 553 | | |
552 | | - | |
| 554 | + | |
| 555 | + | |
553 | 556 | | |
554 | 557 | | |
555 | 558 | | |
556 | 559 | | |
557 | 560 | | |
| 561 | + | |
558 | 562 | | |
559 | 563 | | |
560 | 564 | | |
561 | 565 | | |
562 | 566 | | |
563 | | - | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
564 | 570 | | |
565 | 571 | | |
566 | 572 | | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
567 | 627 | | |
568 | 628 | | |
569 | 629 | | |
| |||
572 | 632 | | |
573 | 633 | | |
574 | 634 | | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
575 | 648 | | |
576 | 649 | | |
577 | 650 | | |
578 | | - | |
579 | | - | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
580 | 655 | | |
581 | 656 | | |
582 | 657 | | |
583 | | - | |
584 | | - | |
585 | | - | |
586 | | - | |
587 | | - | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
588 | 669 | | |
589 | | - | |
590 | | - | |
| 670 | + | |
591 | 671 | | |
592 | | - | |
| 672 | + | |
| 673 | + | |
593 | 674 | | |
594 | | - | |
595 | | - | |
596 | | - | |
597 | | - | |
598 | | - | |
599 | | - | |
600 | | - | |
601 | | - | |
602 | | - | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
603 | 680 | | |
604 | | - | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
605 | 689 | | |
606 | 690 | | |
607 | 691 | | |
| |||
612 | 696 | | |
613 | 697 | | |
614 | 698 | | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
615 | 709 | | |
616 | 710 | | |
617 | 711 | | |
618 | 712 | | |
619 | | - | |
| 713 | + | |
| 714 | + | |
620 | 715 | | |
621 | 716 | | |
622 | | - | |
| 717 | + | |
| 718 | + | |
623 | 719 | | |
624 | 720 | | |
625 | 721 | | |
| |||
630 | 726 | | |
631 | 727 | | |
632 | 728 | | |
633 | | - | |
634 | | - | |
635 | | - | |
636 | | - | |
637 | | - | |
638 | | - | |
639 | | - | |
640 | | - | |
641 | | - | |
642 | | - | |
643 | | - | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
644 | 734 | | |
645 | 735 | | |
646 | 736 | | |
647 | 737 | | |
648 | 738 | | |
649 | 739 | | |
650 | 740 | | |
651 | | - | |
652 | | - | |
653 | | - | |
654 | | - | |
655 | | - | |
656 | | - | |
657 | | - | |
658 | | - | |
| 741 | + | |
| 742 | + | |
659 | 743 | | |
660 | | - | |
661 | | - | |
662 | | - | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
663 | 756 | | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
669 | | - | |
670 | | - | |
671 | | - | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
680 | | - | |
681 | | - | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
682 | 770 | | |
683 | | - | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
684 | 778 | | |
685 | 779 | | |
686 | | - | |
687 | | - | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
693 | 792 | | |
694 | | - | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
695 | 798 | | |
696 | 799 | | |
697 | 800 | | |
698 | 801 | | |
699 | 802 | | |
700 | | - | |
| 803 | + | |
701 | 804 | | |
702 | | - | |
703 | | - | |
| 805 | + | |
704 | 806 | | |
705 | 807 | | |
706 | 808 | | |
| |||
713 | 815 | | |
714 | 816 | | |
715 | 817 | | |
716 | | - | |
717 | | - | |
718 | | - | |
719 | | - | |
720 | 818 | | |
721 | 819 | | |
722 | 820 | | |
| |||
728 | 826 | | |
729 | 827 | | |
730 | 828 | | |
731 | | - | |
| 829 | + | |
732 | 830 | | |
733 | | - | |
| 831 | + | |
734 | 832 | | |
735 | 833 | | |
736 | 834 | | |
| |||
811 | 909 | | |
812 | 910 | | |
813 | 911 | | |
814 | | - | |
| 912 | + | |
815 | 913 | | |
816 | | - | |
| 914 | + | |
817 | 915 | | |
818 | 916 | | |
819 | 917 | | |
| |||
0 commit comments