GHC - tight loop rotation

I am trying to learn / evaluate Haskell and I am afraid to get an efficient executable for a simple case. The test I'm using is a PRNG sequence (PCG32 RNG replication). I wrote this as an iteration of the basic state transition function (now I only look at the state).

{-# LANGUAGE BangPatterns #-}
import System.Environment (getArgs)
import Data.Bits
import Data.Word

iterate' f !x = x : iterate' f (f x)

main = print $ pcg32_rng 100000000

pcg32_random_r :: Word64 -> Word64 -> Word64
pcg32_random_r !i !state = state * (6364136223846793005 :: Word64) + (i .|. 1)
{-# INLINE pcg32_random_r #-}

pcg32_rng_s = iterate' (pcg32_random_r 1) 0

pcg32_rng n = pcg32_rng_s !! (n - 1)

I can get this code to compile and run. It still uses a lot more memory than it should, and runs 10 times slower than the C equivalent. The main problem is that the iteration does not turn into a simple loop.

What am I missing to get GHC to create faster / more efficient code here?

EDIT

C, , , , , . , , - .

#include <stdio.h>
#include <stdint.h>

int main() {
  uint64_t oldstate,state;
  int i;

  for(i=0;i<100000000;i++) {
    oldstate = state;
    // Advance internal state
    state = oldstate * 6364136223846793005ULL + (1|1);
  }
  printf("%ld\n",state);
}

initly Prelude iterate, . "" ​​ .

, GHC inline pcg32_random_r , , , , . ​​GHC, .

@WillemVanOnsem , perform C, pcg32_random_r . Haskell GHC. , perform , ?

, ?

, , , ( /,...), , , Haskell .

+4
1

, , i- . , , .

( ). , n times:

perform_n :: (a -> a) -> Int -> a -> a
perform_n !f = step
    where step !n !x | n <= 0 = x
                     | otherwise = step (n-1) (f x)

, f n . :

pcg32_rng n = perform_n (pcg32_random_r 1) (n-1) 0

ghc -O2 file.hs (GHC 8.0.2), time, :

$ time ./file
2264354473547460187
0.14user 0.00system 0:00.14elapsed 99%CPU (0avgtext+0avgdata 3408maxresident)k
0inputs+0outputs (0major+161minor)pagefaults 0swaps

:

$ time ./file2
2264354473547460187
0.54user 0.00system 0:00.55elapsed 99%CPU (0avgtext+0avgdata 3912maxresident)k
0inputs+0outputs (0major+287minor)pagefaults 0swaps

@WillNess , , : , , .

, , , :

{-# LANGUAGE BangPatterns #-}
import System.Environment (getArgs)
import Data.Bits
import Data.Word

iterate' f !x = x : iterate' f (f x)

main = print $ pcg32_rng 100000000

pcg32_random_r :: Word64 -> Word64 -> Word64
pcg32_random_r !i !state = state * (6364136223846793005 :: Word64) + (i .|. 1)
{-# INLINE pcg32_random_r #-}

pcg32_rng n = iterate' (pcg32_random_r 1) 0 !! (n - 1)

:

$ time ./speedtest3
2264354473547460187
0.54user 0.01system 0:00.56elapsed 99%CPU (0avgtext+0avgdata 3908maxresident)k
0inputs+0outputs (0major+291minor)pagefaults 0swaps

, . , , , cons. . ( ), .

+5

Source: https://habr.com/ru/post/1686487/


All Articles