]> gitweb.factorcode.org Git - factor.git/commitdiff
random.pcg-mwc[-vec]: improve performance
authorAlexander Ilin <alex.ilin@protonmail.com>
Tue, 4 Jan 2022 18:37:57 +0000 (19:37 +0100)
committerJohn Benediktsson <mrjbq7@gmail.com>
Fri, 20 Jan 2023 22:15:14 +0000 (14:15 -0800)
Use TUPLE instead of STURCT, cache unused 32 bits between calls.

extra/random/pcg-mwc-vec/pcg-mwc-vec.factor
extra/random/pcg-mwc/pcg-mwc.factor

index 0211ff0aef3729e196ed70fdbb4ca61827b31967..fbbafe56fbf41e5646830c83f901bb69bbe2725a 100644 (file)
@@ -8,7 +8,9 @@ IN: random.pcg-mwc-vec
 ! https://www.pcg-random.org/
 
 ! The state is an array of four u64 values in this order: x1, x2, x3, c.
-TUPLE: Mwc256XXA64 state ;
+! Since we are only returning 32 bits per step of this 64-bit PRNG, the rest are
+! saved in the rem field.
+TUPLE: Mwc256XXA64 state rem ;
 
 <PRIVATE
 
@@ -31,13 +33,18 @@ CONSTANT: MULTIPLIER 0xfeb3_4465_7c0a_f413
 
 : next-u64 ( obj -- n )
     dup state>> third multiply [ pick state>> first3 permute ] keep
-    swap [ update-state ] dip ;
+    swap [ update-state ] dip ; inline
+
+! If cache is f, use quot to produce a new pair of values from obj: one to be
+! cached, and one to be used. Otherwise return cache as value and cache' = f.
+: cache ( obj cache/f quot: ( obj -- n1 n2 ) -- value cache' )
+    [ nip f ] swap if* ; inline
 
 PRIVATE>
 
 : <Mwc256XXA64> ( key1 key2 -- obj )
-    0xcafef00dd15ea5e5 0x14057B7EF767814F 4array \ Mwc256XXA64 boa
-    6 [ dup next-u64 drop ] times ; inline
+    0xcafef00dd15ea5e5 0x14057B7EF767814F 4array \ Mwc256XXA64 boa
+    6 [ dup next-u64 drop ] times ;
 
 M: Mwc256XXA64 random-32*
-    next-u64 32 bits ;
+    dup [ [ next-u64 d>w/w ] cache ] change-rem drop ;
index cf3ea1f609a28c85b3d9566c267e1191d4ba3756..f3992b68b7eab22c160068213c77c276ad0f599e 100644 (file)
@@ -7,8 +7,9 @@ IN: random.pcg-mwc
 ! https://github.com/tkaitchuck/Mwc256XXA64/blob/main/impl/src/gen64.rs
 ! https://www.pcg-random.org/
 
-STRUCT: Mwc256XXA64
-    { x1 ulonglong } { x2 ulonglong } { x3 ulonglong } { c ulonglong } ;
+! Since we are only returning 32 bits per step of this 64-bit PRNG, the rest are
+! saved in the rem field.
+TUPLE: Mwc256XXA64 x1 x2 x3 c rem ;
 
 <PRIVATE
 
@@ -23,29 +24,34 @@ CONSTANT: MULTIPLIER 0xfeb3_4465_7c0a_f413
 : permute ( high x1 x2 x3 -- n )
     [ bitxor ] 2bi@ W+ ; inline
 
-:: rot-state ( struct x1 c -- struct' )
-    struct
-        struct x2>> >>x3
-        struct x1>> >>x2
+:: rot-state ( obj x1 c -- struct' )
+    obj
+        obj x2>> >>x3
+        obj x1>> >>x2
         x1 >>x1
         c >>c ; inline
 
-: update-state ( struct low high -- )
+: update-state ( obj low high -- )
     [ over c>> + big>d/d ] dip W+ rot-state drop ; inline
 
-: next-u64 ( struct -- n )
+: next-u64 ( obj -- n )
     dup x3>> multiply [ pick [ x1>> ] [ x2>> ] [ x3>> ] tri permute ] keep
-    swap [ update-state ] dip ;
+    swap [ update-state ] dip ; inline
+
+! If cache is f, use quot to produce a new pair of values from obj: one to be
+! cached, and one to be used. Otherwise return cache as value and cache' = f.
+: cache ( obj cache/f quot: ( obj -- n1 n2 ) -- value cache' )
+    [ nip f ] swap if* ; inline
 
 PRIVATE>
 
 : <Mwc256XXA64> ( key1 key2 -- obj )
-    0xcafef00dd15ea5e5 0x14057B7EF767814F Mwc256XXA64 <struct-boa>
+    0xcafef00dd15ea5e5 0x14057B7EF767814F f Mwc256XXA64 boa
     6 [ dup next-u64 drop ] times ;
 
 M: Mwc256XXA64 random-32*
-    next-u64 32 bits ;
+    dup [ [ next-u64 d>w/w ] cache ] change-rem drop ;
 
 ! USING: random random.pcg-mwc random.pcg-mwc-vec ;
 ! gc 0 0 random.pcg-mwc:<Mwc256XXA64> [ 10,000,000 [ dup random-32* drop ] times ] time drop
-! gc 0 0 random.pcg-mwc-vec:<Mwc256XXA64> [ 10,000,000 [ dup random-32* drop ] times ] time drop
\ No newline at end of file
+! gc 0 0 random.pcg-mwc-vec:<Mwc256XXA64> [ 10,000,000 [ dup random-32* drop ] times ] time drop