packages feed

dph-examples-0.6.0.1: examples/spectral/SMVM/dph/Main.hs

{-# LANGUAGE ScopedTypeVariables #-}

import Timing
import Vectorised
import System.IO
import Foreign.Storable
import Foreign.Marshal.Alloc
import Data.Array.Parallel.PArray	as P
import Data.Array.Parallel
import qualified Data.Array.Parallel.Unlifted as U
import System.Environment
import Control.Exception (evaluate)

main :: IO ()
main 
 = do	args	<- getArgs
	case args of
	  [fileName] -> run fileName
	  _	     -> usage
	
usage	
 = putStr $ unlines
	[ "usage: smvm <file>" ]

run fileName
 = do	(matrix, vector) <- loadPA fileName

	matrix `seq` return ()
	vector `seq` return ()

	-- Multiply sparse matrix by the dense vector.
	(vResult, tElapsed)
	 <- time $ let result	= smvmPA matrix vector
		   in  P.nf result `seq` return result
					
	-- Print how long it took.
	putStr $ prettyTime tElapsed

	-- Print some info about the test setup.
	putStrLn $ "vector length   = " ++ show (U.length (P.toUArray vector))
--	putStrLn $ "matrix height   = " ++ show (U.length (toUArrPA matrix))
	
	
	-- Print checksum of resulting vector.
	putStrLn $ "result sum      = " ++ show (U.sum (P.toUArray vResult))



-- | Load a test file containing a sparse matrix and dense vector.
loadPA 	:: String 				-- ^ filename.
	-> IO  ( PArray (PArray (Int, Double))	-- sparse matrix
	       , PArray Double)			-- dense vector

loadPA fileName
 = do 	(segd, arrMatrixElems, arrVector) <- loadUArr fileName

    	let paMatrix	= P.nestUSegd segd (P.fromUArray2 arrMatrixElems)
	let paVector	= P.fromUArray arrVector
	return (paMatrix, paVector)


-- | Load a test file containing a sparse matrix and dense vector.
loadUArr :: String				-- ^ filename
	 -> IO ( U.Segd				-- segment descriptor saying what array elements
						--    belong to each row of the matrix.
	       , U.Array (Int, Double)		-- column indices and matrix elements
	       , U.Array Double)		-- the dense vector

loadUArr fname 
 = do	h <- openBinaryFile fname ReadMode

	-- check magic numbers at start of file to guard against word-size screwups.
	alloca $ \ptr -> do
		hGetBuf h ptr (sizeOf (undefined :: Int))
		magic1 :: Int	<- peek ptr
		hGetBuf h ptr (sizeOf (undefined :: Int))
		magic2	:: Int <- peek ptr
		if magic1 == 0xc0ffee00 Prelude.&& magic2 == 0x12345678 
			then return ()
			else error $ "bad magic in " ++ fname

	-- number of elements in each row of the matrix.
	lengths <- U.hGet h

	-- indices of all the elements.
	indices <- U.hGet h

	-- values of the matrix elements.
	values  <- U.hGet h

	-- the dense vector.
	vector  <- U.hGet h

	evaluate lengths
	evaluate indices
	evaluate values
	evaluate vector

	let segd    = U.lengthsToSegd lengths
	    matrix  = U.zip indices values

	return (segd, matrix, vector)