packages feed

mpi-hs 0.4.1.0 → 0.5.1.1

raw patch · 10 files changed

+1183/−580 lines, 10 filesdep +cerealdep −packmandep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: cereal

Dependencies removed: packman

Dependency ranges changed: base

API changes (from Hackage documentation)

- Control.Distributed.MPI.Packing: Comm :: (ForeignPtr (Comm)) -> Comm
- Control.Distributed.MPI.Packing: Count :: CInt -> Count
- Control.Distributed.MPI.Packing: MPIException :: String -> MPIException
- Control.Distributed.MPI.Packing: Rank :: CInt -> Rank
- Control.Distributed.MPI.Packing: Status :: !Rank -> !Tag -> Status
- Control.Distributed.MPI.Packing: Tag :: CInt -> Tag
- Control.Distributed.MPI.Packing: [msgRank] :: Status -> !Rank
- Control.Distributed.MPI.Packing: [msgTag] :: Status -> !Tag
- Control.Distributed.MPI.Packing: abort :: (Comm) -> (Int) -> IO ()
- Control.Distributed.MPI.Packing: anySource :: (Rank)
- Control.Distributed.MPI.Packing: anyTag :: (Tag)
- Control.Distributed.MPI.Packing: barrier :: (Comm) -> IO ()
- Control.Distributed.MPI.Packing: bcastRecv :: CanSerialize a => Rank -> Comm -> IO a
- Control.Distributed.MPI.Packing: bcastSend :: CanSerialize a => a -> Rank -> Comm -> IO ()
- Control.Distributed.MPI.Packing: commRank :: (Comm) -> IO ((Rank))
- Control.Distributed.MPI.Packing: commSelf :: (Comm)
- Control.Distributed.MPI.Packing: commSize :: (Comm) -> IO ((Rank))
- Control.Distributed.MPI.Packing: commWorld :: (Comm)
- Control.Distributed.MPI.Packing: data Request a
- Control.Distributed.MPI.Packing: data Status
- Control.Distributed.MPI.Packing: fromCount :: Integral i => Count -> i
- Control.Distributed.MPI.Packing: fromRank :: Enum e => Rank -> e
- Control.Distributed.MPI.Packing: fromTag :: Enum e => Tag -> e
- Control.Distributed.MPI.Packing: ibarrier :: Comm -> IO (Request ())
- Control.Distributed.MPI.Packing: ibcastRecv :: CanSerialize a => Rank -> Comm -> IO (Request a)
- Control.Distributed.MPI.Packing: ibcastSend :: CanSerialize a => a -> Rank -> Comm -> IO (Request ())
- Control.Distributed.MPI.Packing: instance GHC.Classes.Eq Control.Distributed.MPI.Packing.MPIException
- Control.Distributed.MPI.Packing: instance GHC.Classes.Eq Control.Distributed.MPI.Packing.Status
- Control.Distributed.MPI.Packing: instance GHC.Classes.Ord Control.Distributed.MPI.Packing.MPIException
- Control.Distributed.MPI.Packing: instance GHC.Classes.Ord Control.Distributed.MPI.Packing.Status
- Control.Distributed.MPI.Packing: instance GHC.Exception.Exception Control.Distributed.MPI.Packing.MPIException
- Control.Distributed.MPI.Packing: instance GHC.Read.Read Control.Distributed.MPI.Packing.MPIException
- Control.Distributed.MPI.Packing: instance GHC.Read.Read Control.Distributed.MPI.Packing.Status
- Control.Distributed.MPI.Packing: instance GHC.Show.Show Control.Distributed.MPI.Packing.MPIException
- Control.Distributed.MPI.Packing: instance GHC.Show.Show Control.Distributed.MPI.Packing.Status
- Control.Distributed.MPI.Packing: irecv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Request a)
- Control.Distributed.MPI.Packing: isend :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO (Request ())
- Control.Distributed.MPI.Packing: mainMPI :: IO () -> IO ()
- Control.Distributed.MPI.Packing: newtype Comm
- Control.Distributed.MPI.Packing: newtype Count
- Control.Distributed.MPI.Packing: newtype MPIException
- Control.Distributed.MPI.Packing: newtype Rank
- Control.Distributed.MPI.Packing: newtype Tag
- Control.Distributed.MPI.Packing: recv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Status, a)
- Control.Distributed.MPI.Packing: recv_ :: CanSerialize a => Rank -> Tag -> Comm -> IO a
- Control.Distributed.MPI.Packing: rootRank :: Rank
- Control.Distributed.MPI.Packing: send :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO ()
- Control.Distributed.MPI.Packing: sendrecv :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO (Status, b)
- Control.Distributed.MPI.Packing: sendrecv_ :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO b
- Control.Distributed.MPI.Packing: test :: Request a -> IO (Maybe (Status, a))
- Control.Distributed.MPI.Packing: test_ :: Request a -> IO (Maybe a)
- Control.Distributed.MPI.Packing: toCount :: Integral i => i -> Count
- Control.Distributed.MPI.Packing: toRank :: Enum e => e -> Rank
- Control.Distributed.MPI.Packing: toTag :: Enum e => e -> Tag
- Control.Distributed.MPI.Packing: unitTag :: Tag
- Control.Distributed.MPI.Packing: wait :: Request a -> IO (Status, a)
- Control.Distributed.MPI.Packing: wait_ :: Request a -> IO a
- Control.Distributed.MPI.Store: instance GHC.Exception.Exception Control.Distributed.MPI.Store.MPIException
+ Control.Distributed.MPI.Binary: Comm :: ForeignPtr Comm -> Comm
+ Control.Distributed.MPI.Binary: Count :: CInt -> Count
+ Control.Distributed.MPI.Binary: MPIException :: String -> MPIException
+ Control.Distributed.MPI.Binary: Rank :: CInt -> Rank
+ Control.Distributed.MPI.Binary: Status :: !Rank -> !Tag -> Status
+ Control.Distributed.MPI.Binary: Tag :: CInt -> Tag
+ Control.Distributed.MPI.Binary: [msgRank] :: Status -> !Rank
+ Control.Distributed.MPI.Binary: [msgTag] :: Status -> !Tag
+ Control.Distributed.MPI.Binary: abort :: Comm -> Int -> IO ()
+ Control.Distributed.MPI.Binary: anySource :: Rank
+ Control.Distributed.MPI.Binary: anyTag :: Tag
+ Control.Distributed.MPI.Binary: barrier :: Comm -> IO ()
+ Control.Distributed.MPI.Binary: bcastRecv :: CanSerialize a => Rank -> Comm -> IO a
+ Control.Distributed.MPI.Binary: bcastSend :: CanSerialize a => a -> Rank -> Comm -> IO ()
+ Control.Distributed.MPI.Binary: commRank :: Comm -> IO Rank
+ Control.Distributed.MPI.Binary: commSelf :: Comm
+ Control.Distributed.MPI.Binary: commSize :: Comm -> IO Rank
+ Control.Distributed.MPI.Binary: commWorld :: Comm
+ Control.Distributed.MPI.Binary: data Request a
+ Control.Distributed.MPI.Binary: data Status
+ Control.Distributed.MPI.Binary: fromCount :: Integral i => Count -> i
+ Control.Distributed.MPI.Binary: fromRank :: Enum e => Rank -> e
+ Control.Distributed.MPI.Binary: fromTag :: Enum e => Tag -> e
+ Control.Distributed.MPI.Binary: ibarrier :: Comm -> IO (Request ())
+ Control.Distributed.MPI.Binary: ibcastRecv :: CanSerialize a => Rank -> Comm -> IO (Request a)
+ Control.Distributed.MPI.Binary: ibcastSend :: CanSerialize a => a -> Rank -> Comm -> IO (Request ())
+ Control.Distributed.MPI.Binary: instance Data.Binary.Class.Binary Control.Distributed.MPI.Rank
+ Control.Distributed.MPI.Binary: instance Data.Binary.Class.Binary Foreign.C.Types.CInt
+ Control.Distributed.MPI.Binary: instance GHC.Classes.Eq Control.Distributed.MPI.Binary.MPIException
+ Control.Distributed.MPI.Binary: instance GHC.Classes.Eq Control.Distributed.MPI.Binary.Status
+ Control.Distributed.MPI.Binary: instance GHC.Classes.Ord Control.Distributed.MPI.Binary.MPIException
+ Control.Distributed.MPI.Binary: instance GHC.Classes.Ord Control.Distributed.MPI.Binary.Status
+ Control.Distributed.MPI.Binary: instance GHC.Exception.Type.Exception Control.Distributed.MPI.Binary.MPIException
+ Control.Distributed.MPI.Binary: instance GHC.Read.Read Control.Distributed.MPI.Binary.MPIException
+ Control.Distributed.MPI.Binary: instance GHC.Read.Read Control.Distributed.MPI.Binary.Status
+ Control.Distributed.MPI.Binary: instance GHC.Show.Show Control.Distributed.MPI.Binary.MPIException
+ Control.Distributed.MPI.Binary: instance GHC.Show.Show Control.Distributed.MPI.Binary.Status
+ Control.Distributed.MPI.Binary: irecv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Request a)
+ Control.Distributed.MPI.Binary: isend :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO (Request ())
+ Control.Distributed.MPI.Binary: mainMPI :: IO () -> IO ()
+ Control.Distributed.MPI.Binary: newtype Comm
+ Control.Distributed.MPI.Binary: newtype Count
+ Control.Distributed.MPI.Binary: newtype MPIException
+ Control.Distributed.MPI.Binary: newtype Rank
+ Control.Distributed.MPI.Binary: newtype Tag
+ Control.Distributed.MPI.Binary: recv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Status, a)
+ Control.Distributed.MPI.Binary: recv_ :: CanSerialize a => Rank -> Tag -> Comm -> IO a
+ Control.Distributed.MPI.Binary: rootRank :: Rank
+ Control.Distributed.MPI.Binary: send :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO ()
+ Control.Distributed.MPI.Binary: sendrecv :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO (Status, b)
+ Control.Distributed.MPI.Binary: sendrecv_ :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO b
+ Control.Distributed.MPI.Binary: test :: Request a -> IO (Maybe (Status, a))
+ Control.Distributed.MPI.Binary: test_ :: Request a -> IO (Maybe a)
+ Control.Distributed.MPI.Binary: toCount :: Integral i => i -> Count
+ Control.Distributed.MPI.Binary: toRank :: Enum e => e -> Rank
+ Control.Distributed.MPI.Binary: toTag :: Enum e => e -> Tag
+ Control.Distributed.MPI.Binary: unitTag :: Tag
+ Control.Distributed.MPI.Binary: wait :: Request a -> IO (Status, a)
+ Control.Distributed.MPI.Binary: wait_ :: Request a -> IO a
+ Control.Distributed.MPI.Serialize: Comm :: ForeignPtr Comm -> Comm
+ Control.Distributed.MPI.Serialize: Count :: CInt -> Count
+ Control.Distributed.MPI.Serialize: MPIException :: String -> MPIException
+ Control.Distributed.MPI.Serialize: Rank :: CInt -> Rank
+ Control.Distributed.MPI.Serialize: Status :: !Rank -> !Tag -> Status
+ Control.Distributed.MPI.Serialize: Tag :: CInt -> Tag
+ Control.Distributed.MPI.Serialize: [msgRank] :: Status -> !Rank
+ Control.Distributed.MPI.Serialize: [msgTag] :: Status -> !Tag
+ Control.Distributed.MPI.Serialize: abort :: Comm -> Int -> IO ()
+ Control.Distributed.MPI.Serialize: anySource :: Rank
+ Control.Distributed.MPI.Serialize: anyTag :: Tag
+ Control.Distributed.MPI.Serialize: barrier :: Comm -> IO ()
+ Control.Distributed.MPI.Serialize: bcastRecv :: CanSerialize a => Rank -> Comm -> IO a
+ Control.Distributed.MPI.Serialize: bcastSend :: CanSerialize a => a -> Rank -> Comm -> IO ()
+ Control.Distributed.MPI.Serialize: commRank :: Comm -> IO Rank
+ Control.Distributed.MPI.Serialize: commSelf :: Comm
+ Control.Distributed.MPI.Serialize: commSize :: Comm -> IO Rank
+ Control.Distributed.MPI.Serialize: commWorld :: Comm
+ Control.Distributed.MPI.Serialize: data Request a
+ Control.Distributed.MPI.Serialize: data Status
+ Control.Distributed.MPI.Serialize: fromCount :: Integral i => Count -> i
+ Control.Distributed.MPI.Serialize: fromRank :: Enum e => Rank -> e
+ Control.Distributed.MPI.Serialize: fromTag :: Enum e => Tag -> e
+ Control.Distributed.MPI.Serialize: ibarrier :: Comm -> IO (Request ())
+ Control.Distributed.MPI.Serialize: ibcastRecv :: CanSerialize a => Rank -> Comm -> IO (Request a)
+ Control.Distributed.MPI.Serialize: ibcastSend :: CanSerialize a => a -> Rank -> Comm -> IO (Request ())
+ Control.Distributed.MPI.Serialize: instance GHC.Classes.Eq Control.Distributed.MPI.Serialize.MPIException
+ Control.Distributed.MPI.Serialize: instance GHC.Classes.Eq Control.Distributed.MPI.Serialize.Status
+ Control.Distributed.MPI.Serialize: instance GHC.Classes.Ord Control.Distributed.MPI.Serialize.MPIException
+ Control.Distributed.MPI.Serialize: instance GHC.Classes.Ord Control.Distributed.MPI.Serialize.Status
+ Control.Distributed.MPI.Serialize: instance GHC.Exception.Type.Exception Control.Distributed.MPI.Serialize.MPIException
+ Control.Distributed.MPI.Serialize: instance GHC.Read.Read Control.Distributed.MPI.Serialize.MPIException
+ Control.Distributed.MPI.Serialize: instance GHC.Read.Read Control.Distributed.MPI.Serialize.Status
+ Control.Distributed.MPI.Serialize: instance GHC.Show.Show Control.Distributed.MPI.Serialize.MPIException
+ Control.Distributed.MPI.Serialize: instance GHC.Show.Show Control.Distributed.MPI.Serialize.Status
+ Control.Distributed.MPI.Serialize: irecv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Request a)
+ Control.Distributed.MPI.Serialize: isend :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO (Request ())
+ Control.Distributed.MPI.Serialize: mainMPI :: IO () -> IO ()
+ Control.Distributed.MPI.Serialize: newtype Comm
+ Control.Distributed.MPI.Serialize: newtype Count
+ Control.Distributed.MPI.Serialize: newtype MPIException
+ Control.Distributed.MPI.Serialize: newtype Rank
+ Control.Distributed.MPI.Serialize: newtype Tag
+ Control.Distributed.MPI.Serialize: recv :: CanSerialize a => Rank -> Tag -> Comm -> IO (Status, a)
+ Control.Distributed.MPI.Serialize: recv_ :: CanSerialize a => Rank -> Tag -> Comm -> IO a
+ Control.Distributed.MPI.Serialize: rootRank :: Rank
+ Control.Distributed.MPI.Serialize: send :: CanSerialize a => a -> Rank -> Tag -> Comm -> IO ()
+ Control.Distributed.MPI.Serialize: sendrecv :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO (Status, b)
+ Control.Distributed.MPI.Serialize: sendrecv_ :: (CanSerialize a, CanSerialize b) => a -> Rank -> Tag -> Rank -> Tag -> Comm -> IO b
+ Control.Distributed.MPI.Serialize: test :: Request a -> IO (Maybe (Status, a))
+ Control.Distributed.MPI.Serialize: test_ :: Request a -> IO (Maybe a)
+ Control.Distributed.MPI.Serialize: toCount :: Integral i => i -> Count
+ Control.Distributed.MPI.Serialize: toRank :: Enum e => e -> Rank
+ Control.Distributed.MPI.Serialize: toTag :: Enum e => e -> Tag
+ Control.Distributed.MPI.Serialize: unitTag :: Tag
+ Control.Distributed.MPI.Serialize: wait :: Request a -> IO (Status, a)
+ Control.Distributed.MPI.Serialize: wait_ :: Request a -> IO a
+ Control.Distributed.MPI.Store: instance GHC.Exception.Type.Exception Control.Distributed.MPI.Store.MPIException
- Control.Distributed.MPI: Comm :: (ForeignPtr (Comm)) -> Comm
+ Control.Distributed.MPI: Comm :: ForeignPtr Comm -> Comm
- Control.Distributed.MPI: Datatype :: (ForeignPtr (Datatype)) -> Datatype
+ Control.Distributed.MPI: Datatype :: ForeignPtr Datatype -> Datatype
- Control.Distributed.MPI: Op :: (ForeignPtr (Op)) -> Op
+ Control.Distributed.MPI: Op :: ForeignPtr Op -> Op
- Control.Distributed.MPI: Request :: (ForeignPtr (Request)) -> Request
+ Control.Distributed.MPI: Request :: ForeignPtr Request -> Request
- Control.Distributed.MPI: Status :: (ForeignPtr (Status)) -> Status
+ Control.Distributed.MPI: Status :: ForeignPtr Status -> Status
- Control.Distributed.MPI: abort :: (Comm) -> (Int) -> IO ()
+ Control.Distributed.MPI: abort :: Comm -> Int -> IO ()
- Control.Distributed.MPI: anySource :: (Rank)
+ Control.Distributed.MPI: anySource :: Rank
- Control.Distributed.MPI: anyTag :: (Tag)
+ Control.Distributed.MPI: anyTag :: Tag
- Control.Distributed.MPI: barrier :: (Comm) -> IO ()
+ Control.Distributed.MPI: barrier :: Comm -> IO ()
- Control.Distributed.MPI: commCompare :: (Comm) -> (Comm) -> IO ((ComparisonResult))
+ Control.Distributed.MPI: commCompare :: Comm -> Comm -> IO ComparisonResult
- Control.Distributed.MPI: commNull :: (Comm)
+ Control.Distributed.MPI: commNull :: Comm
- Control.Distributed.MPI: commRank :: (Comm) -> IO ((Rank))
+ Control.Distributed.MPI: commRank :: Comm -> IO Rank
- Control.Distributed.MPI: commSelf :: (Comm)
+ Control.Distributed.MPI: commSelf :: Comm
- Control.Distributed.MPI: commSize :: (Comm) -> IO ((Rank))
+ Control.Distributed.MPI: commSize :: Comm -> IO Rank
- Control.Distributed.MPI: commWorld :: (Comm)
+ Control.Distributed.MPI: commWorld :: Comm
- Control.Distributed.MPI: countUndefined :: (Count)
+ Control.Distributed.MPI: countUndefined :: Count
- Control.Distributed.MPI: datatypeByte :: (Datatype)
+ Control.Distributed.MPI: datatypeByte :: Datatype
- Control.Distributed.MPI: datatypeChar :: (Datatype)
+ Control.Distributed.MPI: datatypeChar :: Datatype
- Control.Distributed.MPI: datatypeDouble :: (Datatype)
+ Control.Distributed.MPI: datatypeDouble :: Datatype
- Control.Distributed.MPI: datatypeFloat :: (Datatype)
+ Control.Distributed.MPI: datatypeFloat :: Datatype
- Control.Distributed.MPI: datatypeInt :: (Datatype)
+ Control.Distributed.MPI: datatypeInt :: Datatype
- Control.Distributed.MPI: datatypeLong :: (Datatype)
+ Control.Distributed.MPI: datatypeLong :: Datatype
- Control.Distributed.MPI: datatypeLongDouble :: (Datatype)
+ Control.Distributed.MPI: datatypeLongDouble :: Datatype
- Control.Distributed.MPI: datatypeLongLongInt :: (Datatype)
+ Control.Distributed.MPI: datatypeLongLongInt :: Datatype
- Control.Distributed.MPI: datatypeNull :: (Datatype)
+ Control.Distributed.MPI: datatypeNull :: Datatype
- Control.Distributed.MPI: datatypeShort :: (Datatype)
+ Control.Distributed.MPI: datatypeShort :: Datatype
- Control.Distributed.MPI: datatypeUnsigned :: (Datatype)
+ Control.Distributed.MPI: datatypeUnsigned :: Datatype
- Control.Distributed.MPI: datatypeUnsignedChar :: (Datatype)
+ Control.Distributed.MPI: datatypeUnsignedChar :: Datatype
- Control.Distributed.MPI: datatypeUnsignedLong :: (Datatype)
+ Control.Distributed.MPI: datatypeUnsignedLong :: Datatype
- Control.Distributed.MPI: datatypeUnsignedShort :: (Datatype)
+ Control.Distributed.MPI: datatypeUnsignedShort :: Datatype
- Control.Distributed.MPI: finalized :: IO ((Bool))
+ Control.Distributed.MPI: finalized :: IO Bool
- Control.Distributed.MPI: getCount :: (Status) -> (Datatype) -> IO ((Count))
+ Control.Distributed.MPI: getCount :: Status -> Datatype -> IO Count
- Control.Distributed.MPI: getElements :: (Status) -> (Datatype) -> IO ((Int))
+ Control.Distributed.MPI: getElements :: Status -> Datatype -> IO Int
- Control.Distributed.MPI: ibarrier :: (Comm) -> IO ((Request))
+ Control.Distributed.MPI: ibarrier :: Comm -> IO Request
- Control.Distributed.MPI: initialized :: IO ((Bool))
+ Control.Distributed.MPI: initialized :: IO Bool
- Control.Distributed.MPI: opBand :: (Op)
+ Control.Distributed.MPI: opBand :: Op
- Control.Distributed.MPI: opBor :: (Op)
+ Control.Distributed.MPI: opBor :: Op
- Control.Distributed.MPI: opBxor :: (Op)
+ Control.Distributed.MPI: opBxor :: Op
- Control.Distributed.MPI: opLand :: (Op)
+ Control.Distributed.MPI: opLand :: Op
- Control.Distributed.MPI: opLor :: (Op)
+ Control.Distributed.MPI: opLor :: Op
- Control.Distributed.MPI: opLxor :: (Op)
+ Control.Distributed.MPI: opLxor :: Op
- Control.Distributed.MPI: opMax :: (Op)
+ Control.Distributed.MPI: opMax :: Op
- Control.Distributed.MPI: opMaxloc :: (Op)
+ Control.Distributed.MPI: opMaxloc :: Op
- Control.Distributed.MPI: opMin :: (Op)
+ Control.Distributed.MPI: opMin :: Op
- Control.Distributed.MPI: opMinloc :: (Op)
+ Control.Distributed.MPI: opMinloc :: Op
- Control.Distributed.MPI: opNull :: (Op)
+ Control.Distributed.MPI: opNull :: Op
- Control.Distributed.MPI: opProd :: (Op)
+ Control.Distributed.MPI: opProd :: Op
- Control.Distributed.MPI: opSum :: (Op)
+ Control.Distributed.MPI: opSum :: Op
- Control.Distributed.MPI: probe :: (Rank) -> (Tag) -> (Comm) -> IO ((Status))
+ Control.Distributed.MPI: probe :: Rank -> Tag -> Comm -> IO Status
- Control.Distributed.MPI: probe_ :: (Rank) -> (Tag) -> (Comm) -> IO ()
+ Control.Distributed.MPI: probe_ :: Rank -> Tag -> Comm -> IO ()
- Control.Distributed.MPI: requestNull :: (Request)
+ Control.Distributed.MPI: requestNull :: Request
- Control.Distributed.MPI: wait :: (Request) -> IO ((Status))
+ Control.Distributed.MPI: wait :: Request -> IO Status
- Control.Distributed.MPI: wait_ :: (Request) -> IO ()
+ Control.Distributed.MPI: wait_ :: Request -> IO ()
- Control.Distributed.MPI: wtick :: IO ((Double))
+ Control.Distributed.MPI: wtick :: IO Double
- Control.Distributed.MPI: wtime :: IO ((Double))
+ Control.Distributed.MPI: wtime :: IO Double
- Control.Distributed.MPI.Store: Comm :: (ForeignPtr (Comm)) -> Comm
+ Control.Distributed.MPI.Store: Comm :: ForeignPtr Comm -> Comm
- Control.Distributed.MPI.Store: abort :: (Comm) -> (Int) -> IO ()
+ Control.Distributed.MPI.Store: abort :: Comm -> Int -> IO ()
- Control.Distributed.MPI.Store: anySource :: (Rank)
+ Control.Distributed.MPI.Store: anySource :: Rank
- Control.Distributed.MPI.Store: anyTag :: (Tag)
+ Control.Distributed.MPI.Store: anyTag :: Tag
- Control.Distributed.MPI.Store: barrier :: (Comm) -> IO ()
+ Control.Distributed.MPI.Store: barrier :: Comm -> IO ()
- Control.Distributed.MPI.Store: commRank :: (Comm) -> IO ((Rank))
+ Control.Distributed.MPI.Store: commRank :: Comm -> IO Rank
- Control.Distributed.MPI.Store: commSelf :: (Comm)
+ Control.Distributed.MPI.Store: commSelf :: Comm
- Control.Distributed.MPI.Store: commSize :: (Comm) -> IO ((Rank))
+ Control.Distributed.MPI.Store: commSize :: Comm -> IO Rank
- Control.Distributed.MPI.Store: commWorld :: (Comm)
+ Control.Distributed.MPI.Store: commWorld :: Comm

Files

README.md view
@@ -179,11 +179,12 @@  ### Running the tests -There are three test cases provided in `tests`:+There are four test cases provided in `tests`:  ``` stack build --test --no-run-tests-mpirun -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test/mpi-test && echo SUCCESS || echo FAILURE-mpirun -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test-packing/mpi-test-packing && echo SUCCESS || echo FAILURE-mpirun -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test-store/mpi-test-store && echo SUCCESS || echo FAILURE+mpirun-openmpi-mp -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test/mpi-test && echo SUCCESS || echo FAILURE+mpirun-openmpi-mp -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test-binary/mpi-test-binary && echo SUCCESS || echo FAILURE+mpirun-openmpi-mp -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test-serialize/mpi-test-serialize && echo SUCCESS || echo FAILURE+mpirun-openmpi-mp -np 3 --mca btl self,vader --oversubscribe stack exec $(stack path --dist-dir)/build/mpi-test-store/mpi-test-store && echo SUCCESS || echo FAILURE ```
+ lib/Control/Distributed/MPI/Binary.hs view
@@ -0,0 +1,403 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeApplications #-}++-- | Module: Control.Distributed.MPI.Binary+-- Description: Simplified MPI bindings with automatic serialization+--              based on Data.Binary+-- Copyright: (C) 2018 Erik Schnetter+-- License: Apache-2.0+-- Maintainer: Erik Schnetter <schnetter@gmail.com>+-- Stability: experimental+-- Portability: Requires an externally installed MPI library++module Control.Distributed.MPI.Binary+  ( -- * Types, and associated functions and constants+    MPIException(..)++    -- ** Communicators+  , Comm(..)+  , commSelf+  , commWorld++    -- ** Message sizes+  , Count(..)+  , fromCount+  , toCount++    -- ** Process ranks+  , Rank(..)+  , anySource+  , commRank+  , commSize+  , fromRank+  , rootRank+  , toRank++    -- ** Message status+  , Status(..)++    -- ** Message tags+  , Tag(..)+  , anyTag+  , fromTag+  , toTag+  , unitTag++  , Request++    -- * Functions++    -- ** Initialization and shutdown+  , abort+  , mainMPI++    -- ** Point-to-point (blocking)+  , recv+  , recv_+  , send+  , sendrecv+  , sendrecv_++    -- ** Point-to-point (non-blocking)+  , irecv+  , isend+  , test+  , test_+  , wait+  , wait_++    -- ** Collective (blocking)+  , barrier+  , bcastRecv+  , bcastSend++    -- ** Collective (non-blocking)+  , ibarrier+  , ibcastRecv+  , ibcastSend+  ) where++import Prelude hiding (init)++import Control.Concurrent+import Control.Exception+import Control.Monad+import Control.Monad.Loops+import qualified Data.Binary as Binary+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Unsafe as B+import Data.Coerce+import Data.Typeable+import Foreign+import Foreign.C.Types++import qualified Control.Distributed.MPI as MPI+import Control.Distributed.MPI+  ( Comm(..)+  , commSelf+  , commWorld+  , Count(..)+  , fromCount+  , toCount+  , Rank(..)+  , anySource+  , commRank+  , commSize+  , fromRank+  , rootRank+  , toRank+  , Tag(..)+  , anyTag+  , fromTag+  , toTag+  , unitTag+  , abort+  , barrier+  )++++-- Serialization, based on Data.Binary+type CanSerialize a = Binary.Binary a+serialize :: CanSerialize a => a -> IO B.ByteString+serialize = return . BL.toStrict . Binary.encode+deserialize :: CanSerialize a => B.ByteString -> IO a+deserialize = return . Binary.decode . BL.fromStrict++-- Why is this necessary? Shouldn't 'Data.Binary' already contain+-- this?+instance Binary.Binary CInt where+  put x = Binary.put @Int32 (coerce x)+  get = coerce <$> (Binary.get @Int32)+instance Binary.Binary Rank++++-- | Run the supplied Maybe computation repeatedly while it returns+-- Nothing. If it returns a value, then returns that value.+whileNothing :: Monad m => m (Maybe a) -> m () -> m a+whileNothing cond loop = go+  where go = do mx <- cond+                case mx of+                  Nothing -> do loop+                                go+                  Just x -> return x++++-- | Exception type indicating an error in a call to MPI+newtype MPIException = MPIException String+  deriving (Eq, Ord, Read, Show, Typeable)+instance Exception MPIException++mpiAssert :: Bool -> String -> IO ()+mpiAssert cond msg =+  do when (not cond) $ throw (MPIException msg)+     return ()++++data DidInit = DidInit | DidNotInit++initMPI :: IO DidInit+initMPI =+  do isInit <- MPI.initialized+     if isInit+       then return DidNotInit+       else do ts <- MPI.initThread MPI.ThreadMultiple+               mpiAssert (ts >= MPI.ThreadMultiple)+                 ("MPI.init: Insufficient thread support: requiring " +++                  show MPI.ThreadMultiple +++                  ", but MPI library provided only " ++ show ts)+               return DidInit++finalizeMPI :: DidInit -> IO ()+finalizeMPI DidInit =+  do isFinalized <- MPI.finalized+     if isFinalized+       then return ()+       else do MPI.finalize+finalizeMPI DidNotInit = return ()++-- | Convenience function to initialize and finalize MPI. This+-- initializes MPI with 'ThreadMultiple' thread support.+mainMPI :: IO () -- ^ action to run with MPI, typically the whole program+        -> IO ()+mainMPI action = bracket initMPI finalizeMPI (\_ -> action)++++-- | A communication request, usually created by a non-blocking+-- communication function.+newtype Request a = Request (MVar (Status, a))++-- | The status of a finished communication, indicating rank and tag+-- of the other communication end point.+data Status = Status { msgRank :: !Rank+                     , msgTag :: !Tag+                     }+  deriving (Eq, Ord, Read, Show)++++-- | Receive an object.+recv :: CanSerialize a+     => Rank                    -- ^ Source rank+     -> Tag                     -- ^ Source tag+     -> Comm                    -- ^ Communicator+     -> IO (Status, a)          -- ^ Message status and received object+recv recvrank recvtag comm =+  do status <- whileNothing (MPI.iprobe recvrank recvtag comm) yield+     source <- MPI.getSource status+     tag <- MPI.getTag status+     count <- MPI.getCount status MPI.datatypeByte+     let len = MPI.fromCount count+     ptr <- mallocBytes len+     buffer <- B.unsafePackMallocCStringLen (ptr, len)+     req <- MPI.irecv buffer source tag comm+     whileM_ (not <$> MPI.test_ req) yield+     recvobj <- deserialize buffer+     return (Status source tag, recvobj)++-- | Receive an object without returning a status.+recv_ :: CanSerialize a+      => Rank                   -- ^ Source rank+      -> Tag                    -- ^ Source tag+      -> Comm                   -- ^ Communicator+      -> IO a                   -- ^ Received object+recv_ recvrank recvtag comm =+  snd <$> recv recvrank recvtag comm++-- | Send an object.+send :: CanSerialize a+     => a                     -- ^ Object to send+     -> Rank                  -- ^ Destination rank+     -> Tag                   -- ^ Message tag+     -> Comm                  -- ^ Communicator+     -> IO ()+send sendobj sendrank sendtag comm =+  do sendbuf <- serialize sendobj+     -- Use 'unsafeUseAsCStringLen' to ensure 'sendbuf' is not freed+     -- too early+     B.unsafeUseAsCStringLen sendbuf $ \_ ->+       do req <- MPI.isend sendbuf sendrank sendtag comm+          whileM_ (not <$> MPI.test_ req) yield++-- | Send and receive objects simultaneously.+sendrecv :: (CanSerialize a, CanSerialize b)+         => a                   -- ^ Object to send+         -> Rank                -- ^ Destination rank+         -> Tag                 -- ^ Send message tag+         -> Rank                -- ^ Source rank+         -> Tag                 -- ^ Receive message tag+         -> Comm                -- ^ Communicator+         -> IO (Status, b)      -- ^ Message status and received object+sendrecv sendobj sendrank sendtag recvrank recvtag comm =+  do recvreq <- irecv recvrank recvtag comm+     send sendobj sendrank sendtag comm+     wait recvreq++-- | Send and receive objects simultaneously, without returning a+-- status for the received message.+sendrecv_ :: (CanSerialize a, CanSerialize b)+          => a                  -- ^ Object to send+          -> Rank               -- ^ Destination rank+          -> Tag                -- ^ Send message tag+          -> Rank               -- ^ Source rank+          -> Tag                -- ^ Receive message tag+          -> Comm               -- ^ Communicator+          -> IO b               -- ^ Received object+sendrecv_ sendobj sendrank sendtag recvrank recvtag comm =+  snd <$> sendrecv sendobj sendrank sendtag recvrank recvtag comm++-- | Begin to receive an object. Call `test` or `wait` to finish the+-- communication, and to obtain the received object.+irecv :: CanSerialize a+      => Rank                   -- ^ Source rank+      -> Tag                    -- ^ Source tag+      -> Comm                   -- ^ Communicator+      -> IO (Request a)         -- ^ Communication request+irecv recvrank recvtag comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do res <- recv recvrank recvtag comm+          putMVar result res+     return (Request result)++-- | Begin to send an object. Call 'test' or 'wait' to finish the+-- communication.+isend :: CanSerialize a+      => a                     -- ^ Object to send+      -> Rank                  -- ^ Destination rank+      -> Tag                   -- ^ Message tag+      -> Comm                  -- ^ Communicator+      -> IO (Request ())       -- ^ Communication request+isend sendobj sendrank sendtag comm =+  do result <- newEmptyMVar+     _ <- forkIO $ do send sendobj sendrank sendtag comm+                      putMVar result (Status sendrank sendtag, ())+     return (Request result)++-- | Check whether a communication has finished, and return the+-- communication result if so.+test :: Request a               -- ^ Communication request+     -> IO (Maybe (Status, a))  -- ^ 'Just' communication result, if+                                -- communication has finished, else 'Nothing'+test (Request result) = tryTakeMVar result++-- | Check whether a communication has finished, and return the+-- communication result if so, without returning a message status.+test_ :: Request a       -- ^ Communication request+      -> IO (Maybe a)    -- ^ 'Just' communication result, if+                         -- communication has finished, else 'Nothing'+test_ req = fmap snd <$> test req++-- | Wait for a communication to finish and return the communication+-- result.+wait :: Request a               -- ^ Communication request+     -> IO (Status, a)          -- ^ Message status and communication result+wait (Request result) = takeMVar result++-- | Wait for a communication to finish and return the communication+-- result, without returning a message status.+wait_ :: Request a              -- ^ Communication request+      -> IO a                   -- ^ Communication result+wait_ req = snd <$> wait req++++-- | Broadcast a message from one process (the "root") to all other+-- processes in the communicator. Call this function on all non-root+-- processes. Call 'bcastSend' instead on the root process.+bcastRecv :: CanSerialize a+          => Rank+          -> Comm+          -> IO a+bcastRecv root comm =+  do rank <- MPI.commRank comm+     mpiAssert (rank /= root) "bcastRecv: expected rank /= root"+     lenbuf <- mallocForeignPtr @CLong+     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm+     whileM_ (not <$> MPI.test_ lenreq) yield+     len <- withForeignPtr lenbuf peek+     ptr <- mallocBytes (fromIntegral len)+     recvbuf <- B.unsafePackMallocCStringLen (ptr, fromIntegral len)+     req <- MPI.ibcast recvbuf root comm               +     whileM_ (not <$> MPI.test_ req) yield+     recvobj <- deserialize recvbuf+     return recvobj++-- | Broadcast a message from one process (the "root") to all other+-- processes in the communicator. Call this function on the root+-- process. Call 'bcastRecv' instead on all non-root processes.+bcastSend :: CanSerialize a+          => a+          -> Rank+          -> Comm+          -> IO ()+bcastSend sendobj root comm =+  do rank <- MPI.commRank comm+     mpiAssert (rank == root) "bcastSend: expected rank == root"+     sendbuf <- serialize sendobj+     lenbuf <- mallocForeignPtr @CLong+     withForeignPtr lenbuf $ \ptr -> poke ptr (fromIntegral (B.length sendbuf))+     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm+     whileM_ (not <$> MPI.test_ lenreq) yield+     req <- MPI.ibcast sendbuf root comm+     whileM_ (not <$> MPI.test_ req) yield++ibcastRecv :: CanSerialize a+           => Rank+           -> Comm+           -> IO (Request a)+ibcastRecv root comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do recvobj <- bcastRecv root comm+          putMVar result (Status root MPI.anyTag, recvobj)+     return (Request result)++ibcastSend :: CanSerialize a+           => a+           -> Rank+           -> Comm+           -> IO (Request ())+ibcastSend sendobj root comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do bcastSend sendobj root comm+          putMVar result (Status root MPI.anyTag, ())+     return (Request result)++-- | Begin a barrier. Call 'test' or 'wait' to finish the+-- communication.+ibarrier :: Comm+         -> IO (Request ())+ibarrier comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do req <- MPI.ibarrier comm+          whileM_ (not <$> MPI.test_ req) yield+          putMVar result (Status MPI.anySource MPI.anyTag, ())+     return (Request result)
− lib/Control/Distributed/MPI/Packing.hs
@@ -1,396 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE TypeApplications #-}---- | Module: Control.Distributed.MPI.Packing--- Description: Simplified MPI bindings with automatic serialization---              based on GHC.Packing--- Copyright: (C) 2018 Erik Schnetter--- License: Apache-2.0--- Maintainer: Erik Schnetter <schnetter@gmail.com>--- Stability: experimental--- Portability: Requires an externally installed MPI library--module Control.Distributed.MPI.Packing-  ( -- * Types, and associated functions and constants-    MPIException(..)--    -- ** Communicators-  , Comm(..)-  , commSelf-  , commWorld--    -- ** Message sizes-  , Count(..)-  , fromCount-  , toCount--    -- ** Process ranks-  , Rank(..)-  , anySource-  , commRank-  , commSize-  , fromRank-  , rootRank-  , toRank--    -- ** Message status-  , Status(..)--    -- ** Message tags-  , Tag(..)-  , anyTag-  , fromTag-  , toTag-  , unitTag--  , Request--    -- * Functions--    -- ** Initialization and shutdown-  , abort-  , mainMPI--    -- ** Point-to-point (blocking)-  , recv-  , recv_-  , send-  , sendrecv-  , sendrecv_--    -- ** Point-to-point (non-blocking)-  , irecv-  , isend-  , test-  , test_-  , wait-  , wait_--    -- ** Collective (blocking)-  , barrier-  , bcastRecv-  , bcastSend--    -- ** Collective (non-blocking)-  , ibarrier-  , ibcastRecv-  , ibcastSend-  ) where--import Prelude hiding (init)--import Control.Concurrent-import Control.Exception-import Control.Monad-import Control.Monad.Loops-import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString as B-import qualified Data.ByteString.Unsafe as B-import qualified Data.Binary as Binary-import Data.Typeable-import Foreign-import Foreign.C.Types-import qualified GHC.Packing as Packing--import qualified Control.Distributed.MPI as MPI-import Control.Distributed.MPI-  ( Comm(..)-  , commSelf-  , commWorld-  , Count(..)-  , fromCount-  , toCount-  , Rank(..)-  , anySource-  , commRank-  , commSize-  , fromRank-  , rootRank-  , toRank-  , Tag(..)-  , anyTag-  , fromTag-  , toTag-  , unitTag-  , abort-  , barrier-  )------ Serialization, based on GHC.Packing-type CanSerialize a = Typeable a-serialize :: CanSerialize a => a -> IO B.ByteString-serialize = fmap (BL.toStrict . Binary.encode) . Packing.trySerialize-deserialize :: CanSerialize a => B.ByteString -> IO a-deserialize = Packing.deserialize . Binary.decode . BL.fromStrict------ | Run the supplied Maybe computation repeatedly while it returns--- Nothing. If it returns a value, then returns that value.-whileNothing :: Monad m => m (Maybe a) -> m () -> m a-whileNothing cond loop = go-  where go = do mx <- cond-                case mx of-                  Nothing -> do loop-                                go-                  Just x -> return x------ | Exception type indicating an error in a call to MPI-newtype MPIException = MPIException String-  deriving (Eq, Ord, Read, Show, Typeable)-instance Exception MPIException--mpiAssert :: Bool -> String -> IO ()-mpiAssert cond msg =-  do when (not cond) $ throw (MPIException msg)-     return ()----data DidInit = DidInit | DidNotInit--initMPI :: IO DidInit-initMPI =-  do isInit <- MPI.initialized-     if isInit-       then return DidNotInit-       else do ts <- MPI.initThread MPI.ThreadMultiple-               mpiAssert (ts >= MPI.ThreadMultiple)-                 ("MPI.init: Insufficient thread support: requiring " ++-                  show MPI.ThreadMultiple ++-                  ", but MPI library provided only " ++ show ts)-               return DidInit--finalizeMPI :: DidInit -> IO ()-finalizeMPI DidInit =-  do isFinalized <- MPI.finalized-     if isFinalized-       then return ()-       else do MPI.finalize-finalizeMPI DidNotInit = return ()---- | Convenience function to initialize and finalize MPI. This--- initializes MPI with 'ThreadMultiple' thread support.-mainMPI :: IO () -- ^ action to run with MPI, typically the whole program-        -> IO ()-mainMPI action = bracket initMPI finalizeMPI (\_ -> action)------ | A communication request, usually created by a non-blocking--- communication function.-newtype Request a = Request (MVar (Status, a))---- | The status of a finished communication, indicating rank and tag--- of the other communication end point.-data Status = Status { msgRank :: !Rank-                     , msgTag :: !Tag-                     }-  deriving (Eq, Ord, Read, Show)------ | Receive an object.-recv :: CanSerialize a-     => Rank                    -- ^ Source rank-     -> Tag                     -- ^ Source tag-     -> Comm                    -- ^ Communicator-     -> IO (Status, a)          -- ^ Message status and received object-recv recvrank recvtag comm =-  do status <- whileNothing (MPI.iprobe recvrank recvtag comm) yield-     source <- MPI.getSource status-     tag <- MPI.getTag status-     count <- MPI.getCount status MPI.datatypeByte-     let len = MPI.fromCount count-     ptr <- mallocBytes len-     buffer <- B.unsafePackMallocCStringLen (ptr, len)-     req <- MPI.irecv buffer source tag comm-     whileM_ (not <$> MPI.test_ req) yield-     recvobj <- deserialize buffer-     return (Status source tag, recvobj)---- | Receive an object without returning a status.-recv_ :: CanSerialize a-      => Rank                   -- ^ Source rank-      -> Tag                    -- ^ Source tag-      -> Comm                   -- ^ Communicator-      -> IO a                   -- ^ Received object-recv_ recvrank recvtag comm =-  snd <$> recv recvrank recvtag comm---- | Send an object.-send :: CanSerialize a-     => a                     -- ^ Object to send-     -> Rank                  -- ^ Destination rank-     -> Tag                   -- ^ Message tag-     -> Comm                  -- ^ Communicator-     -> IO ()-send sendobj sendrank sendtag comm =-  do sendbuf <- serialize sendobj-     -- Use 'unsafeUseAsCStringLen' to ensure 'sendbuf' is not freed-     -- too early-     B.unsafeUseAsCStringLen sendbuf $ \_ ->-       do req <- MPI.isend sendbuf sendrank sendtag comm-          whileM_ (not <$> MPI.test_ req) yield---- | Send and receive objects simultaneously.-sendrecv :: (CanSerialize a, CanSerialize b)-         => a                   -- ^ Object to send-         -> Rank                -- ^ Destination rank-         -> Tag                 -- ^ Send message tag-         -> Rank                -- ^ Source rank-         -> Tag                 -- ^ Receive message tag-         -> Comm                -- ^ Communicator-         -> IO (Status, b)      -- ^ Message status and received object-sendrecv sendobj sendrank sendtag recvrank recvtag comm =-  do recvreq <- irecv recvrank recvtag comm-     send sendobj sendrank sendtag comm-     wait recvreq---- | Send and receive objects simultaneously, without returning a--- status for the received message.-sendrecv_ :: (CanSerialize a, CanSerialize b)-          => a                  -- ^ Object to send-          -> Rank               -- ^ Destination rank-          -> Tag                -- ^ Send message tag-          -> Rank               -- ^ Source rank-          -> Tag                -- ^ Receive message tag-          -> Comm               -- ^ Communicator-          -> IO b               -- ^ Received object-sendrecv_ sendobj sendrank sendtag recvrank recvtag comm =-  snd <$> sendrecv sendobj sendrank sendtag recvrank recvtag comm---- | Begin to receive an object. Call `test` or `wait` to finish the--- communication, and to obtain the received object.-irecv :: CanSerialize a-      => Rank                   -- ^ Source rank-      -> Tag                    -- ^ Source tag-      -> Comm                   -- ^ Communicator-      -> IO (Request a)         -- ^ Communication request-irecv recvrank recvtag comm =-  do result <- newEmptyMVar-     _ <- forkIO $-       do res <- recv recvrank recvtag comm-          putMVar result res-     return (Request result)---- | Begin to send an object. Call 'test' or 'wait' to finish the--- communication.-isend :: CanSerialize a-      => a                     -- ^ Object to send-      -> Rank                  -- ^ Destination rank-      -> Tag                   -- ^ Message tag-      -> Comm                  -- ^ Communicator-      -> IO (Request ())       -- ^ Communication request-isend sendobj sendrank sendtag comm =-  do result <- newEmptyMVar-     _ <- forkIO $ do send sendobj sendrank sendtag comm-                      putMVar result (Status sendrank sendtag, ())-     return (Request result)---- | Check whether a communication has finished, and return the--- communication result if so.-test :: Request a               -- ^ Communication request-     -> IO (Maybe (Status, a))  -- ^ 'Just' communication result, if-                                -- communication has finished, else 'Nothing'-test (Request result) = tryTakeMVar result---- | Check whether a communication has finished, and return the--- communication result if so, without returning a message status.-test_ :: Request a       -- ^ Communication request-      -> IO (Maybe a)    -- ^ 'Just' communication result, if-                         -- communication has finished, else 'Nothing'-test_ req = fmap snd <$> test req---- | Wait for a communication to finish and return the communication--- result.-wait :: Request a               -- ^ Communication request-     -> IO (Status, a)          -- ^ Message status and communication result-wait (Request result) = takeMVar result---- | Wait for a communication to finish and return the communication--- result, without returning a message status.-wait_ :: Request a              -- ^ Communication request-      -> IO a                   -- ^ Communication result-wait_ req = snd <$> wait req------ | Broadcast a message from one process (the "root") to all other--- processes in the communicator. Call this function on all non-root--- processes. Call 'bcastSend' instead on the root process.-bcastRecv :: CanSerialize a-          => Rank-          -> Comm-          -> IO a-bcastRecv root comm =-  do rank <- MPI.commRank comm-     mpiAssert (rank /= root) "bcastRecv: expected rank /= root"-     lenbuf <- mallocForeignPtr @CLong-     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm-     whileM_ (not <$> MPI.test_ lenreq) yield-     len <- withForeignPtr lenbuf peek-     ptr <- mallocBytes (fromIntegral len)-     recvbuf <- B.unsafePackMallocCStringLen (ptr, fromIntegral len)-     req <- MPI.ibcast recvbuf root comm               -     whileM_ (not <$> MPI.test_ req) yield-     recvobj <- deserialize recvbuf-     return recvobj---- | Broadcast a message from one process (the "root") to all other--- processes in the communicator. Call this function on the root--- process. Call 'bcastRecv' instead on all non-root processes.-bcastSend :: CanSerialize a-          => a-          -> Rank-          -> Comm-          -> IO ()-bcastSend sendobj root comm =-  do rank <- MPI.commRank comm-     mpiAssert (rank == root) "bcastSend: expected rank == root"-     sendbuf <- serialize sendobj-     lenbuf <- mallocForeignPtr @CLong-     withForeignPtr lenbuf $ \ptr -> poke ptr (fromIntegral (B.length sendbuf))-     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm-     whileM_ (not <$> MPI.test_ lenreq) yield-     req <- MPI.ibcast sendbuf root comm-     whileM_ (not <$> MPI.test_ req) yield--ibcastRecv :: CanSerialize a-           => Rank-           -> Comm-           -> IO (Request a)-ibcastRecv root comm =-  do result <- newEmptyMVar-     _ <- forkIO $-       do recvobj <- bcastRecv root comm-          putMVar result (Status root MPI.anyTag, recvobj)-     return (Request result)--ibcastSend :: CanSerialize a-           => a-           -> Rank-           -> Comm-           -> IO (Request ())-ibcastSend sendobj root comm =-  do result <- newEmptyMVar-     _ <- forkIO $-       do bcastSend sendobj root comm-          putMVar result (Status root MPI.anyTag, ())-     return (Request result)---- | Begin a barrier. Call 'test' or 'wait' to finish the--- communication.-ibarrier :: Comm-         -> IO (Request ())-ibarrier comm =-  do result <- newEmptyMVar-     _ <- forkIO $-       do req <- MPI.ibarrier comm-          whileM_ (not <$> MPI.test_ req) yield-          putMVar result (Status MPI.anySource MPI.anyTag, ())-     return (Request result)
+ lib/Control/Distributed/MPI/Serialize.hs view
@@ -0,0 +1,399 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeApplications #-}++-- | Module: Control.Distributed.MPI.Serialize+-- Description: Simplified MPI bindings with automatic serialization+--              based on Data.Serialize+-- Copyright: (C) 2018 Erik Schnetter+-- License: Apache-2.0+-- Maintainer: Erik Schnetter <schnetter@gmail.com>+-- Stability: experimental+-- Portability: Requires an externally installed MPI library++module Control.Distributed.MPI.Serialize+  ( -- * Types, and associated functions and constants+    MPIException(..)++    -- ** Communicators+  , Comm(..)+  , commSelf+  , commWorld++    -- ** Message sizes+  , Count(..)+  , fromCount+  , toCount++    -- ** Process ranks+  , Rank(..)+  , anySource+  , commRank+  , commSize+  , fromRank+  , rootRank+  , toRank++    -- ** Message status+  , Status(..)++    -- ** Message tags+  , Tag(..)+  , anyTag+  , fromTag+  , toTag+  , unitTag++  , Request++    -- * Functions++    -- ** Initialization and shutdown+  , abort+  , mainMPI++    -- ** Point-to-point (blocking)+  , recv+  , recv_+  , send+  , sendrecv+  , sendrecv_++    -- ** Point-to-point (non-blocking)+  , irecv+  , isend+  , test+  , test_+  , wait+  , wait_++    -- ** Collective (blocking)+  , barrier+  , bcastRecv+  , bcastSend++    -- ** Collective (non-blocking)+  , ibarrier+  , ibcastRecv+  , ibcastSend+  ) where++import Prelude hiding (init)++import Control.Concurrent+import Control.Exception+import Control.Monad+import Control.Monad.Loops+import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as B+import qualified Data.Serialize as Serialize+import Data.Typeable+import Foreign+import Foreign.C.Types++import qualified Control.Distributed.MPI as MPI+import Control.Distributed.MPI+  ( Comm(..)+  , commSelf+  , commWorld+  , Count(..)+  , fromCount+  , toCount+  , Rank(..)+  , anySource+  , commRank+  , commSize+  , fromRank+  , rootRank+  , toRank+  , Tag(..)+  , anyTag+  , fromTag+  , toTag+  , unitTag+  , abort+  , barrier+  )++++-- Serialization, based on Data.Store+type CanSerialize a = Serialize.Serialize a+serialize :: CanSerialize a => a -> IO B.ByteString+serialize = return . Serialize.encode+deserialize :: CanSerialize a => B.ByteString -> IO a+deserialize buf =+  do let obj = Serialize.decode buf+     case obj of+       Left str -> throwIO $+         MPIException ("Data.Serialize.decode failed: " ++ str)+       Right x -> return x++++-- | Run the supplied Maybe computation repeatedly while it returns+-- Nothing. If it returns a value, then returns that value.+whileNothing :: Monad m => m (Maybe a) -> m () -> m a+whileNothing cond loop = go+  where go = do mx <- cond+                case mx of+                  Nothing -> do loop+                                go+                  Just x -> return x++++-- | Exception type indicating an error in a call to MPI+newtype MPIException = MPIException String+  deriving (Eq, Ord, Read, Show, Typeable)+instance Exception MPIException++mpiAssert :: Bool -> String -> IO ()+mpiAssert cond msg =+  do when (not cond) $ throw (MPIException msg)+     return ()++++data DidInit = DidInit | DidNotInit++initMPI :: IO DidInit+initMPI =+  do isInit <- MPI.initialized+     if isInit+       then return DidNotInit+       else do ts <- MPI.initThread MPI.ThreadMultiple+               mpiAssert (ts >= MPI.ThreadMultiple)+                 ("MPI.init: Insufficient thread support: requiring " +++                  show MPI.ThreadMultiple +++                  ", but MPI library provided only " ++ show ts)+               return DidInit++finalizeMPI :: DidInit -> IO ()+finalizeMPI DidInit =+  do isFinalized <- MPI.finalized+     if isFinalized+       then return ()+       else do MPI.finalize+finalizeMPI DidNotInit = return ()++-- | Convenience function to initialize and finalize MPI. This+-- initializes MPI with 'ThreadMultiple' thread support.+mainMPI :: IO () -- ^ action to run with MPI, typically the whole program+        -> IO ()+mainMPI action = bracket initMPI finalizeMPI (\_ -> action)++++-- | A communication request, usually created by a non-blocking+-- communication function.+newtype Request a = Request (MVar (Status, a))++-- | The status of a finished communication, indicating rank and tag+-- of the other communication end point.+data Status = Status { msgRank :: !Rank+                     , msgTag :: !Tag+                     }+  deriving (Eq, Ord, Read, Show)++++-- | Receive an object.+recv :: CanSerialize a+     => Rank                    -- ^ Source rank+     -> Tag                     -- ^ Source tag+     -> Comm                    -- ^ Communicator+     -> IO (Status, a)          -- ^ Message status and received object+recv recvrank recvtag comm =+  do status <- whileNothing (MPI.iprobe recvrank recvtag comm) yield+     source <- MPI.getSource status+     tag <- MPI.getTag status+     count <- MPI.getCount status MPI.datatypeByte+     let len = MPI.fromCount count+     ptr <- mallocBytes len+     buffer <- B.unsafePackMallocCStringLen (ptr, len)+     req <- MPI.irecv buffer source tag comm+     whileM_ (not <$> MPI.test_ req) yield+     recvobj <- deserialize buffer+     return (Status source tag, recvobj)++-- | Receive an object without returning a status.+recv_ :: CanSerialize a+      => Rank                   -- ^ Source rank+      -> Tag                    -- ^ Source tag+      -> Comm                   -- ^ Communicator+      -> IO a                   -- ^ Received object+recv_ recvrank recvtag comm =+  snd <$> recv recvrank recvtag comm++-- | Send an object.+send :: CanSerialize a+     => a                     -- ^ Object to send+     -> Rank                  -- ^ Destination rank+     -> Tag                   -- ^ Message tag+     -> Comm                  -- ^ Communicator+     -> IO ()+send sendobj sendrank sendtag comm =+  do sendbuf <- serialize sendobj+     -- Use 'unsafeUseAsCStringLen' to ensure 'sendbuf' is not freed+     -- too early+     B.unsafeUseAsCStringLen sendbuf $ \_ ->+       do req <- MPI.isend sendbuf sendrank sendtag comm+          whileM_ (not <$> MPI.test_ req) yield++-- | Send and receive objects simultaneously.+sendrecv :: (CanSerialize a, CanSerialize b)+         => a                   -- ^ Object to send+         -> Rank                -- ^ Destination rank+         -> Tag                 -- ^ Send message tag+         -> Rank                -- ^ Source rank+         -> Tag                 -- ^ Receive message tag+         -> Comm                -- ^ Communicator+         -> IO (Status, b)      -- ^ Message status and received object+sendrecv sendobj sendrank sendtag recvrank recvtag comm =+  do recvreq <- irecv recvrank recvtag comm+     send sendobj sendrank sendtag comm+     wait recvreq++-- | Send and receive objects simultaneously, without returning a+-- status for the received message.+sendrecv_ :: (CanSerialize a, CanSerialize b)+          => a                  -- ^ Object to send+          -> Rank               -- ^ Destination rank+          -> Tag                -- ^ Send message tag+          -> Rank               -- ^ Source rank+          -> Tag                -- ^ Receive message tag+          -> Comm               -- ^ Communicator+          -> IO b               -- ^ Received object+sendrecv_ sendobj sendrank sendtag recvrank recvtag comm =+  snd <$> sendrecv sendobj sendrank sendtag recvrank recvtag comm++-- | Begin to receive an object. Call `test` or `wait` to finish the+-- communication, and to obtain the received object.+irecv :: CanSerialize a+      => Rank                   -- ^ Source rank+      -> Tag                    -- ^ Source tag+      -> Comm                   -- ^ Communicator+      -> IO (Request a)         -- ^ Communication request+irecv recvrank recvtag comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do res <- recv recvrank recvtag comm+          putMVar result res+     return (Request result)++-- | Begin to send an object. Call 'test' or 'wait' to finish the+-- communication.+isend :: CanSerialize a+      => a                     -- ^ Object to send+      -> Rank                  -- ^ Destination rank+      -> Tag                   -- ^ Message tag+      -> Comm                  -- ^ Communicator+      -> IO (Request ())       -- ^ Communication request+isend sendobj sendrank sendtag comm =+  do result <- newEmptyMVar+     _ <- forkIO $ do send sendobj sendrank sendtag comm+                      putMVar result (Status sendrank sendtag, ())+     return (Request result)++-- | Check whether a communication has finished, and return the+-- communication result if so.+test :: Request a               -- ^ Communication request+     -> IO (Maybe (Status, a))  -- ^ 'Just' communication result, if+                                -- communication has finished, else 'Nothing'+test (Request result) = tryTakeMVar result++-- | Check whether a communication has finished, and return the+-- communication result if so, without returning a message status.+test_ :: Request a       -- ^ Communication request+      -> IO (Maybe a)    -- ^ 'Just' communication result, if+                         -- communication has finished, else 'Nothing'+test_ req = fmap snd <$> test req++-- | Wait for a communication to finish and return the communication+-- result.+wait :: Request a               -- ^ Communication request+     -> IO (Status, a)          -- ^ Message status and communication result+wait (Request result) = takeMVar result++-- | Wait for a communication to finish and return the communication+-- result, without returning a message status.+wait_ :: Request a              -- ^ Communication request+      -> IO a                   -- ^ Communication result+wait_ req = snd <$> wait req++++-- | Broadcast a message from one process (the "root") to all other+-- processes in the communicator. Call this function on all non-root+-- processes. Call 'bcastSend' instead on the root process.+bcastRecv :: CanSerialize a+          => Rank+          -> Comm+          -> IO a+bcastRecv root comm =+  do rank <- MPI.commRank comm+     mpiAssert (rank /= root) "bcastRecv: expected rank /= root"+     lenbuf <- mallocForeignPtr @CLong+     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm+     whileM_ (not <$> MPI.test_ lenreq) yield+     len <- withForeignPtr lenbuf peek+     ptr <- mallocBytes (fromIntegral len)+     recvbuf <- B.unsafePackMallocCStringLen (ptr, fromIntegral len)+     req <- MPI.ibcast recvbuf root comm               +     whileM_ (not <$> MPI.test_ req) yield+     recvobj <- deserialize recvbuf+     return recvobj++-- | Broadcast a message from one process (the "root") to all other+-- processes in the communicator. Call this function on the root+-- process. Call 'bcastRecv' instead on all non-root processes.+bcastSend :: CanSerialize a+          => a+          -> Rank+          -> Comm+          -> IO ()+bcastSend sendobj root comm =+  do rank <- MPI.commRank comm+     mpiAssert (rank == root) "bcastSend: expected rank == root"+     sendbuf <- serialize sendobj+     lenbuf <- mallocForeignPtr @CLong+     withForeignPtr lenbuf $ \ptr -> poke ptr (fromIntegral (B.length sendbuf))+     lenreq <- MPI.ibcast (lenbuf, 1::Int) root comm+     whileM_ (not <$> MPI.test_ lenreq) yield+     req <- MPI.ibcast sendbuf root comm+     whileM_ (not <$> MPI.test_ req) yield++ibcastRecv :: CanSerialize a+           => Rank+           -> Comm+           -> IO (Request a)+ibcastRecv root comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do recvobj <- bcastRecv root comm+          putMVar result (Status root MPI.anyTag, recvobj)+     return (Request result)++ibcastSend :: CanSerialize a+           => a+           -> Rank+           -> Comm+           -> IO (Request ())+ibcastSend sendobj root comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do bcastSend sendobj root comm+          putMVar result (Status root MPI.anyTag, ())+     return (Request result)++-- | Begin a barrier. Call 'test' or 'wait' to finish the+-- communication.+ibarrier :: Comm+         -> IO (Request ())+ibarrier comm =+  do result <- newEmptyMVar+     _ <- forkIO $+       do req <- MPI.ibarrier comm+          whileM_ (not <$> MPI.test_ req) yield+          putMVar result (Status MPI.anySource MPI.anyTag, ())+     return (Request result)
mpi-hs.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.0.+-- This file has been generated from package.yaml by hpack version 0.31.1. -- -- see: https://github.com/sol/hpack ----- hash: 78a9591a1cd036f2ecd9afed2b5c9b1a094791c057255536650d00de3174f23c+-- hash: 51db71059fcdd89fa4df2f6b20866b5abb0c7a517f8fe02a9d9687bb1139aa86  name:           mpi-hs-version:        0.4.1.0+version:        0.5.1.1 synopsis:       MPI bindings for Haskell description:    MPI (the [Message Passing Interface](https://www.mpi-forum.org)) is                 widely used standard for distributed-memory programming on HPC (High@@ -59,7 +59,8 @@ library   exposed-modules:       Control.Distributed.MPI-      Control.Distributed.MPI.Packing+      Control.Distributed.MPI.Binary+      Control.Distributed.MPI.Serialize       Control.Distributed.MPI.Store   other-modules:       Paths_mpi_hs@@ -76,8 +77,8 @@       base >=4 && <5     , binary     , bytestring+    , cereal     , monad-loops-    , packman     , store   build-tools:       c2hs@@ -92,6 +93,7 @@   ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N   build-depends:       base+    , binary     , mpi-hs   default-language: Haskell2010 @@ -109,13 +111,26 @@     , mpi-hs   default-language: Haskell2010 -test-suite mpi-test-packing+test-suite mpi-test-binary   type: exitcode-stdio-1.0   main-is: Main.hs   other-modules:       Paths_mpi_hs   hs-source-dirs:-      tests/packing+      tests/binary+  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N+  build-depends:+      base+    , mpi-hs+  default-language: Haskell2010++test-suite mpi-test-serialize+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_mpi_hs+  hs-source-dirs:+      tests/serialize   ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N   build-depends:       base
package.yaml view
@@ -1,5 +1,5 @@ name: mpi-hs-version: '0.4.1.0'+version: '0.5.1.1' github: "eschnett/mpi-hs" license: Apache-2.0 author: "Erik Schnetter <schnetter@gmail.com>"@@ -51,8 +51,8 @@     - base >=4 && <5            # tested with 4.11 and 4.12     - binary     - bytestring+    - cereal     - monad-loops-    - packman     - store   build-tools:     - c2hs@@ -70,6 +70,7 @@     main: Main.hs     dependencies:       - base+      - binary       - mpi-hs     ghc-options:       - -rtsopts@@ -105,8 +106,22 @@       - -rtsopts       - -threaded       - -with-rtsopts=-N-  mpi-test-packing:-    source-dirs: tests/packing+  mpi-test-binary:+    source-dirs: tests/binary+    main: Main.hs+    dependencies:+      - base+      - mpi-hs+      # - tasty+      # - tasty-hunit+      # - tasty-hspec+      # - unix+    ghc-options:+      - -rtsopts+      - -threaded+      - -with-rtsopts=-N+  mpi-test-serialize:+    source-dirs: tests/serialize     main: Main.hs     dependencies:       - base
stack.yaml view
@@ -1,12 +1,12 @@ # Resolver to choose a 'specific' stackage snapshot or a compiler version.-resolver: lts-12.16+resolver: lts-13.4  # User packages to be built. packages:   - . -extra-deps:-  - packman-0.5.0+# extra-deps:+#   - packman-0.5.0  # Extra directories used by stack for building extra-include-dirs:
+ tests/binary/Main.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE ScopedTypeVariables #-}++import System.IO+import System.Exit++import qualified Control.Distributed.MPI.Binary as MPI++default (Int)++++--------------------------------------------------------------------------------++infix 1 @?+(@?) :: Bool -> String -> IO ()+x @? msg = if not x then die msg else return ()++infix 1 @?=+(@?=) :: Eq a => a -> a -> IO ()+x @?= y = x == y @? "test failed"++++type TestTree = IO ()++testCase :: String -> IO () -> TestTree+testCase name test =+  do rank <- MPI.commRank MPI.commWorld+     if rank == 0+       then do putStrLn $ "  " ++ name ++ "..."+               hFlush stdout+       else return ()+     MPI.barrier MPI.commWorld+     test+     MPI.barrier MPI.commWorld++++testGroup :: String -> [TestTree] -> TestTree+testGroup name cases =+  do rank <- MPI.commRank MPI.commWorld+     if rank == 0+       then do putStrLn $ name ++ ":"+               hFlush stdout+       else return ()+     sequence_ cases++++defaultMain :: TestTree -> IO ()+defaultMain tree =+  do rank <- MPI.commRank MPI.commWorld+     size <- MPI.commSize MPI.commWorld+     if rank == 0+       then do putStrLn $ "MPI Tests: running on " ++ show size ++ " processes"+               hFlush stdout+       else return ()+     tree++++--------------------------------------------------------------------------------++++main :: IO ()+main = MPI.mainMPI $ defaultMain tests++tests :: TestTree+tests = testGroup "MPI"+  [ rankSize+  , pointToPoint+  , pointToPointNonBlocking+  , collective+  , collectiveNonBlocking+  ]++++rankSize :: TestTree+rankSize = testGroup "rank and size"+  [ testCase "commSelf" $+    do rank <- MPI.commRank MPI.commSelf+       size <- MPI.commSize MPI.commSelf+       rank == 0 && size == 1 @? ""+  , testCase "commWorld" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       rank >= 0 && rank < size @? ""+  ]++++pointToPoint :: TestTree+pointToPoint = testGroup "point-to-point"+  [ testCase "sendrecv" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       let sendrank = (rank + 1) `mod` size+       let recvrank = (rank - 1) `mod` size+       (status, recvmsg :: String) <-+         MPI.sendrecv sendmsg sendrank MPI.unitTag recvrank MPI.unitTag+         MPI.commWorld+       (recvmsg == sendmsg &&+        MPI.msgRank status == recvrank &&+        MPI.msgTag status == MPI.unitTag) @? ""+  ]++++pointToPointNonBlocking :: TestTree+pointToPointNonBlocking = testGroup "point-to-point non-blocking"+  [ testCase "send and recv" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       let sendrank = (rank + 1) `mod` size+       sendreq <- MPI.isend sendmsg sendrank MPI.unitTag MPI.commWorld+       let recvrank = (rank - 1) `mod` size+       recvreq <- MPI.irecv recvrank MPI.unitTag MPI.commWorld+       (sendstatus, ()) <- MPI.wait sendreq+       (recvstatus, recvmsg :: String) <- MPI.wait recvreq+       (recvmsg == sendmsg &&+        MPI.msgRank sendstatus == sendrank &&+        MPI.msgTag sendstatus == MPI.unitTag &&+        MPI.msgRank recvstatus == recvrank &&+        MPI.msgTag recvstatus == MPI.unitTag) @? ""+  ]++++collective :: TestTree+collective = testGroup "collective"+  [ testCase "barrier" $+    do MPI.barrier MPI.commWorld+  , testCase "bcast" $+    do rank <- MPI.commRank MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       recvmsg :: String <-+         if rank == MPI.rootRank+         then do MPI.bcastSend sendmsg MPI.rootRank MPI.commWorld+                 return sendmsg+         else do MPI.bcastRecv MPI.rootRank MPI.commWorld+       recvmsg == sendmsg @? ""+  ]++++collectiveNonBlocking :: TestTree+collectiveNonBlocking = testGroup "collective non-blocking"+  [ testCase "barrier" $+    do req <- MPI.ibarrier MPI.commWorld+       MPI.wait_ req+  , testCase "bcast" $+    do rank <- MPI.commRank MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       recvmsg :: String <-+         if rank == MPI.rootRank+         then do req <- MPI.ibcastSend sendmsg MPI.rootRank MPI.commWorld+                 MPI.wait_ req+                 return sendmsg+         else do req <- MPI.ibcastRecv MPI.rootRank MPI.commWorld+                 MPI.wait_ req+       recvmsg == sendmsg @? ""+  ]
− tests/packing/Main.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}--import System.IO-import System.Exit--import qualified Control.Distributed.MPI.Packing as MPI--default (Int)--------------------------------------------------------------------------------------infix 1 @?-(@?) :: Bool -> String -> IO ()-x @? msg = if not x then die msg else return ()--infix 1 @?=-(@?=) :: Eq a => a -> a -> IO ()-x @?= y = x == y @? "test failed"----type TestTree = IO ()--testCase :: String -> IO () -> TestTree-testCase name test =-  do rank <- MPI.commRank MPI.commWorld-     if rank == 0-       then do putStrLn $ "  " ++ name ++ "..."-               hFlush stdout-       else return ()-     MPI.barrier MPI.commWorld-     test-     MPI.barrier MPI.commWorld----testGroup :: String -> [TestTree] -> TestTree-testGroup name cases =-  do rank <- MPI.commRank MPI.commWorld-     if rank == 0-       then do putStrLn $ name ++ ":"-               hFlush stdout-       else return ()-     sequence_ cases----defaultMain :: TestTree -> IO ()-defaultMain tree =-  do rank <- MPI.commRank MPI.commWorld-     size <- MPI.commSize MPI.commWorld-     if rank == 0-       then do putStrLn $ "MPI Tests: running on " ++ show size ++ " processes"-               hFlush stdout-       else return ()-     tree----------------------------------------------------------------------------------------main :: IO ()-main = MPI.mainMPI $ defaultMain tests--tests :: TestTree-tests = testGroup "MPI"-  [ rankSize-  , pointToPoint-  , pointToPointNonBlocking-  , collective-  , collectiveNonBlocking-  ]----rankSize :: TestTree-rankSize = testGroup "rank and size"-  [ testCase "commSelf" $-    do rank <- MPI.commRank MPI.commSelf-       size <- MPI.commSize MPI.commSelf-       rank == 0 && size == 1 @? ""-  , testCase "commWorld" $-    do rank <- MPI.commRank MPI.commWorld-       size <- MPI.commSize MPI.commWorld-       rank >= 0 && rank < size @? ""-  ]----pointToPoint :: TestTree-pointToPoint = testGroup "point-to-point"-  [ testCase "sendrecv" $-    do rank <- MPI.commRank MPI.commWorld-       size <- MPI.commSize MPI.commWorld-       let sendmsg :: String = "Hello, World!"-       let sendrank = (rank + 1) `mod` size-       let recvrank = (rank - 1) `mod` size-       (status, recvmsg :: String) <--         MPI.sendrecv sendmsg sendrank MPI.unitTag recvrank MPI.unitTag-         MPI.commWorld-       (recvmsg == sendmsg &&-        MPI.msgRank status == recvrank &&-        MPI.msgTag status == MPI.unitTag) @? ""-  ]----pointToPointNonBlocking :: TestTree-pointToPointNonBlocking = testGroup "point-to-point non-blocking"-  [ testCase "send and recv" $-    do rank <- MPI.commRank MPI.commWorld-       size <- MPI.commSize MPI.commWorld-       let sendmsg :: String = "Hello, World!"-       let sendrank = (rank + 1) `mod` size-       sendreq <- MPI.isend sendmsg sendrank MPI.unitTag MPI.commWorld-       let recvrank = (rank - 1) `mod` size-       recvreq <- MPI.irecv recvrank MPI.unitTag MPI.commWorld-       (sendstatus, ()) <- MPI.wait sendreq-       (recvstatus, recvmsg :: String) <- MPI.wait recvreq-       (recvmsg == sendmsg &&-        MPI.msgRank sendstatus == sendrank &&-        MPI.msgTag sendstatus == MPI.unitTag &&-        MPI.msgRank recvstatus == recvrank &&-        MPI.msgTag recvstatus == MPI.unitTag) @? ""-  ]----collective :: TestTree-collective = testGroup "collective"-  [ testCase "barrier" $-    do MPI.barrier MPI.commWorld-  , testCase "bcast" $-    do rank <- MPI.commRank MPI.commWorld-       let sendmsg :: String = "Hello, World!"-       recvmsg :: String <--         if rank == MPI.rootRank-         then do MPI.bcastSend sendmsg MPI.rootRank MPI.commWorld-                 return sendmsg-         else do MPI.bcastRecv MPI.rootRank MPI.commWorld-       recvmsg == sendmsg @? ""-  ]----collectiveNonBlocking :: TestTree-collectiveNonBlocking = testGroup "collective non-blocking"-  [ testCase "barrier" $-    do req <- MPI.ibarrier MPI.commWorld-       MPI.wait_ req-  , testCase "bcast" $-    do rank <- MPI.commRank MPI.commWorld-       let sendmsg :: String = "Hello, World!"-       recvmsg :: String <--         if rank == MPI.rootRank-         then do req <- MPI.ibcastSend sendmsg MPI.rootRank MPI.commWorld-                 MPI.wait_ req-                 return sendmsg-         else do req <- MPI.ibcastRecv MPI.rootRank MPI.commWorld-                 MPI.wait_ req-       recvmsg == sendmsg @? ""-  ]
+ tests/serialize/Main.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE ScopedTypeVariables #-}++import System.IO+import System.Exit++import qualified Control.Distributed.MPI.Serialize as MPI++default (Int)++++--------------------------------------------------------------------------------++infix 1 @?+(@?) :: Bool -> String -> IO ()+x @? msg = if not x then die msg else return ()++infix 1 @?=+(@?=) :: Eq a => a -> a -> IO ()+x @?= y = x == y @? "test failed"++++type TestTree = IO ()++testCase :: String -> IO () -> TestTree+testCase name test =+  do rank <- MPI.commRank MPI.commWorld+     if rank == 0+       then do putStrLn $ "  " ++ name ++ "..."+               hFlush stdout+       else return ()+     MPI.barrier MPI.commWorld+     test+     MPI.barrier MPI.commWorld++++testGroup :: String -> [TestTree] -> TestTree+testGroup name cases =+  do rank <- MPI.commRank MPI.commWorld+     if rank == 0+       then do putStrLn $ name ++ ":"+               hFlush stdout+       else return ()+     sequence_ cases++++defaultMain :: TestTree -> IO ()+defaultMain tree =+  do rank <- MPI.commRank MPI.commWorld+     size <- MPI.commSize MPI.commWorld+     if rank == 0+       then do putStrLn $ "MPI Tests: running on " ++ show size ++ " processes"+               hFlush stdout+       else return ()+     tree++++--------------------------------------------------------------------------------++++main :: IO ()+main = MPI.mainMPI $ defaultMain tests++tests :: TestTree+tests = testGroup "MPI"+  [ rankSize+  , pointToPoint+  , pointToPointNonBlocking+  , collective+  , collectiveNonBlocking+  ]++++rankSize :: TestTree+rankSize = testGroup "rank and size"+  [ testCase "commSelf" $+    do rank <- MPI.commRank MPI.commSelf+       size <- MPI.commSize MPI.commSelf+       rank == 0 && size == 1 @? ""+  , testCase "commWorld" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       rank >= 0 && rank < size @? ""+  ]++++pointToPoint :: TestTree+pointToPoint = testGroup "point-to-point"+  [ testCase "sendrecv" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       let sendrank = (rank + 1) `mod` size+       let recvrank = (rank - 1) `mod` size+       (status, recvmsg :: String) <-+         MPI.sendrecv sendmsg sendrank MPI.unitTag recvrank MPI.unitTag+         MPI.commWorld+       (recvmsg == sendmsg &&+        MPI.msgRank status == recvrank &&+        MPI.msgTag status == MPI.unitTag) @? ""+  ]++++pointToPointNonBlocking :: TestTree+pointToPointNonBlocking = testGroup "point-to-point non-blocking"+  [ testCase "send and recv" $+    do rank <- MPI.commRank MPI.commWorld+       size <- MPI.commSize MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       let sendrank = (rank + 1) `mod` size+       sendreq <- MPI.isend sendmsg sendrank MPI.unitTag MPI.commWorld+       let recvrank = (rank - 1) `mod` size+       recvreq <- MPI.irecv recvrank MPI.unitTag MPI.commWorld+       (sendstatus, ()) <- MPI.wait sendreq+       (recvstatus, recvmsg :: String) <- MPI.wait recvreq+       (recvmsg == sendmsg &&+        MPI.msgRank sendstatus == sendrank &&+        MPI.msgTag sendstatus == MPI.unitTag &&+        MPI.msgRank recvstatus == recvrank &&+        MPI.msgTag recvstatus == MPI.unitTag) @? ""+  ]++++collective :: TestTree+collective = testGroup "collective"+  [ testCase "barrier" $+    do MPI.barrier MPI.commWorld+  , testCase "bcast" $+    do rank <- MPI.commRank MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       recvmsg :: String <-+         if rank == MPI.rootRank+         then do MPI.bcastSend sendmsg MPI.rootRank MPI.commWorld+                 return sendmsg+         else do MPI.bcastRecv MPI.rootRank MPI.commWorld+       recvmsg == sendmsg @? ""+  ]++++collectiveNonBlocking :: TestTree+collectiveNonBlocking = testGroup "collective non-blocking"+  [ testCase "barrier" $+    do req <- MPI.ibarrier MPI.commWorld+       MPI.wait_ req+  , testCase "bcast" $+    do rank <- MPI.commRank MPI.commWorld+       let sendmsg :: String = "Hello, World!"+       recvmsg :: String <-+         if rank == MPI.rootRank+         then do req <- MPI.ibcastSend sendmsg MPI.rootRank MPI.commWorld+                 MPI.wait_ req+                 return sendmsg+         else do req <- MPI.ibcastRecv MPI.rootRank MPI.commWorld+                 MPI.wait_ req+       recvmsg == sendmsg @? ""+  ]