From a940e79843455f48609e2360bcd0427a3d016eec Mon Sep 17 00:00:00 2001 From: Dominic Steinitz Date: Fri, 13 Oct 2023 13:25:29 +0100 Subject: [PATCH] Showing that random-fu is x4 faster than mwc and thus monad-bayes --- .envrc | 3 +- default.nix | 63 +++++++++++++++++++++++++++++++--------- samplePerformance.hs | 50 ++++++++++++++++++++++++++++++++ shell.nix | 68 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 155 insertions(+), 29 deletions(-) create mode 100644 samplePerformance.hs diff --git a/.envrc b/.envrc index b24f1171..9f901af9 100644 --- a/.envrc +++ b/.envrc @@ -1,2 +1,3 @@ +use nix # Make sure you have direnv >= 2.30 -use flake --extra-experimental-features nix-command --extra-experimental-features flakes +# use flake --extra-experimental-features nix-command --extra-experimental-features flakes diff --git a/default.nix b/default.nix index c7d0c267..db1bd5de 100644 --- a/default.nix +++ b/default.nix @@ -1,14 +1,49 @@ -( - import - ( - let - lock = builtins.fromJSON (builtins.readFile ./flake.lock); - in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } - ) - {src = ./.;} -) -.defaultNix +{ mkDerivation, abstract-par, base, brick, containers, criterion +, directory, foldl, free, histogram-fill, hspec, ieee754 +, integration, lens, lib, linear, log-domain, math-functions +, matrix, monad-coroutine, monad-extras, mtl, mwc-random +, optparse-applicative, pipes, pretty-simple, primitive, process +, QuickCheck, random, safe, scientific, statistics, text, time +, transformers, typed-process, vector, vty +}: +mkDerivation { + pname = "monad-bayes"; + version = "1.2.0"; + src = ./.; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + base brick containers foldl free histogram-fill ieee754 integration + lens linear log-domain math-functions matrix monad-coroutine + monad-extras mtl mwc-random pipes pretty-simple primitive random + safe scientific statistics text vector vty + ]; + executableHaskellDepends = [ + abstract-par base brick containers criterion directory foldl free + histogram-fill hspec ieee754 integration lens linear log-domain + math-functions matrix monad-coroutine monad-extras mtl mwc-random + optparse-applicative pipes pretty-simple primitive process + QuickCheck random safe scientific statistics text time transformers + typed-process vector vty + ]; + testHaskellDepends = [ + abstract-par base brick containers criterion directory foldl free + histogram-fill hspec ieee754 integration lens linear log-domain + math-functions matrix monad-coroutine monad-extras mtl mwc-random + optparse-applicative pipes pretty-simple primitive process + QuickCheck random safe scientific statistics text time transformers + typed-process vector vty + ]; + benchmarkHaskellDepends = [ + abstract-par base brick containers criterion directory foldl free + histogram-fill hspec ieee754 integration lens linear log-domain + math-functions matrix monad-coroutine monad-extras mtl mwc-random + optparse-applicative pipes pretty-simple primitive process + QuickCheck random safe scientific statistics text time transformers + typed-process vector vty + ]; + homepage = "http://github.com/tweag/monad-bayes#readme"; + description = "A library for probabilistic programming"; + license = lib.licenses.mit; + mainProgram = "example"; +} diff --git a/samplePerformance.hs b/samplePerformance.hs new file mode 100644 index 00000000..fa7cba9b --- /dev/null +++ b/samplePerformance.hs @@ -0,0 +1,50 @@ +{-# OPTIONS_GHC -Wall #-} +{-# OPTIONS_GHC -Wno-type-defaults #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- From random +import System.Random.Stateful + +-- From mwc-random +import qualified System.Random.MWC.Distributions as MWC + +-- From random-fu +import Data.Random + +-- From monad-bayes +import qualified Control.Monad.Bayes.Class as MonadBayes +import Control.Monad.Bayes.Sampler.Strict + +import Criterion.Main +import Control.DeepSeq (NFData) +import Foreign + + +main :: IO () +main = do + stdGen <- newIOGenM =<< newStdGen + defaultMain + [ bgroup "dists" + [ bgroup "StdGen" (dists (stdGen :: (IOGenM StdGen))) + ] + ] + +dists :: StatefulGen g IO => g -> [Benchmark] +dists gen = + [ doubleSuite gen "stdNormal" (Normal 0.0 1.0) + ] + +doubleSuite :: (Distribution d Double, StatefulGen g IO) => g -> String -> d Double -> Benchmark +doubleSuite = suite + +suite :: (Storable t, Num t, Distribution d t, NFData t, StatefulGen g IO) => g -> String -> d t -> Benchmark +suite gen name var = bgroup name + [ bench "single sample" $ nfIO $ do + sampleFrom gen var + , bench "single sample MWC" $ nfIO $ do + MWC.normal 0.0 1.0 gen + , bench "single sample monad bayes" $ nfIO $ do + sampleWith (MonadBayes.normal 0.0 1.0) gen + ] + diff --git a/shell.nix b/shell.nix index e6d91731..1c775527 100644 --- a/shell.nix +++ b/shell.nix @@ -1,14 +1,54 @@ -( - import - ( - let - lock = builtins.fromJSON (builtins.readFile ./flake.lock); - in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } - ) - {src = ./.;} -) -.shellNix +let + +myHaskellPackageOverlay = self: super: { + myHaskellPackages = super.haskellPackages.override { + overrides = hself: hsuper: rec { + random-fu = super.haskell.lib.dontCheck (hself.callCabal2nixWithOptions "random-fu" (builtins.fetchGit { + url = "https://github.com/haskell-numerics/random-fu"; + rev = "b5cf96c6d904faa6adcf010a88f3ee117b289a4f"; + }) "--subpath random-fu" { }); + rvar = super.haskell.lib.dontCheck (hself.callCabal2nixWithOptions "rvar" (builtins.fetchGit { + url = "https://github.com/haskell-numerics/random-fu"; + rev = "b5cf96c6d904faa6adcf010a88f3ee117b289a4f"; + }) "--subpath rvar" { }); + monad-bayes = super.haskell.lib.dontCheck ( + super.haskell.lib.doJailbreak ( + super.haskell.lib.disableLibraryProfiling (hself.callPackage ./. { }) + ) + ); + }; + }; +}; + +in + +{ nixpkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixpkgs-23.05-darwin.tar.gz") + { + overlays = [ myHaskellPackageOverlay ]; + config.allowBroken = true; + } +}: + +let + + pkgs = nixpkgs; + + haskellDeps = ps: with ps; [ + base criterion deepseq + mersenne-random-pure64 + monad-bayes + MonadRandom mtl mwc-random random random-fu stateref vector + ]; + +in + +pkgs.stdenv.mkDerivation { + name = "simple-shell"; + + buildInputs = [ + pkgs.cabal-install + pkgs.cabal2nix + (pkgs.myHaskellPackages.ghcWithPackages haskellDeps) + pkgs.darwin.apple_sdk.frameworks.Cocoa + ]; +}