/Client/Benchmark.hs
Haskell | 624 lines | 369 code | 140 blank | 115 comment | 8 complexity | c929015d221a2d8420711012801681d5 MD5 | raw file
Possible License(s): BSD-3-Clause
1{-# LANGUAGE EmptyDataDecls,FlexibleInstances, TypeSynonymInstances, TypeSynonymInstances, ExistentialQuantification, CPP #-} 2----------------------------------------------------------------------------- 3-- | 4-- Module : Benchmark 5-- Copyright : (c)2011, Texas Instruments France 6-- License : BSD-style (see the file LICENSE) 7-- 8-- Maintainer : c-favergeon-borgialli@ti.com 9-- Stability : provisional 10-- Portability : portable 11-- 12-- Benchmark module to create and control the OpenCL kernels on the board 13 14module Benchmark( 15 -- * Benchmark types 16 ArrayLength(..) 17 -- ** Type of a generic Benchmark 18 , Benchmark 19 -- ** Type of kernel arguments 20 , Float4(..) 21 , CLFloat(..) 22 , CLFloat4(..) 23 , CLInt(..) 24 , CLIntArray(..) 25 , CLFloatArray(..) 26 , CLFloat4Array(..) 27 , CLIntArrayOO(..) 28 , CLFloatArrayOO(..) 29 , CLFloat4ArrayOO(..) 30 -- ** Tag for a kernel argument 31 , In 32 , InOut 33 -- * Benchmark control 34 -- ** Rounding control 35 , gpuRoundingMode 36 -- ** For connection to the server and control of the test to run 37 , Options(..) 38 , defaultOptions 39 -- ** NDRange specification 40 , WorkSize 41 , OneD 42 , TwoD 43 , ThreeD 44 , NDRange 45 , size1D 46 , size2D 47 , size3D 48 , ndRange 49 , simpleNDRange 50 , defaultLocalWs 51 -- ** Benchmark results 52 , BenchResult(..) 53 , DataResults(..) 54 , DataResult(..) 55 , TimingResult(..) 56 -- * Benchmark functions 57 -- ** Benchmark creations 58 , bench 59 , clFloatArrayOO 60 , clFloat4ArrayOO 61 , clIntArrayOO 62 , clConstIntArray 63 , clConstFloatArray 64 , clConstFloat4Array 65 -- ** Benchmark control 66 , endSimu 67 , onBoard 68 , onBoardOnlyTiming 69 , onBoardOnlyData 70 , Clocks(..) 71 , defaultClocks 72#ifdef OMAP4 73 , CPUClock(..) 74 , MemClock(..) 75 , GPUClock(..) 76#endif 77 -- ** Benchmark results 78 , fromFloatResult 79 , fromFloat4Result 80 , fromIntResult 81 ) where 82 83import System.IO 84import Network.Socket 85import Data.Int 86 87 88import Data.List(intercalate) 89 90import Test.QuickCheck.Monadic(run) 91import Rounding 92import Text.Printf 93 94-- ----------------------------------------------------------------------------- 95-- Benchmark options 96 97-- | Options controling a benchmark 98data Options = Options 99 { port :: String -- ^ The IP port 100 , addr :: String -- ^ The server IP address 101 , validation :: Bool -- ^ True is validation tests must be executed 102 , performance :: Bool -- ^ True if performance tests must be executed 103 , roundingMode :: RoundingMode -- ^ Rounding mode used by the GPU 104 } deriving Show 105 106-- | Default values for the options 107defaultOptions = Options 108 { port = "2000" 109 , addr = "128.247.79.158" 110 , validation = False 111 , performance = True 112 , roundingMode = TowardZero 113 } 114 115class Dimension s 116 117instance Dimension OneD 118 119instance Dimension TwoD 120 121instance Dimension ThreeD 122 123-- | Phantom type to constraint a list to one element 124data OneD 125 126-- | Phantom type to constraint a list to two elements 127data TwoD 128 129-- | Phantom type to constraint a list to three elements 130data ThreeD 131 132-- | Index space dimension with a constrained dimension s 133data WorkSize s = WorkSize [Int] 134 deriving(Eq) 135 136-- | NDRange : the global and local worksize are constrained to have the same dimension 137data NDRange s = NDRange (WorkSize s) (WorkSize s) 138 139-- | Force the rounding mode 140gpuRoundingMode :: Options -> IO () 141gpuRoundingMode opts = setRoundingMode (roundingMode opts) 142 143 144a `isMultipleOf` b = a `rem` b == 0 145 146class DetailedShow a where 147 detailedShow :: a -> String 148 149instance DetailedShow Int32 where 150 detailedShow a = printf "%d" a 151 152instance DetailedShow Float where 153 detailedShow a = printf "%.20f" a 154 155instance DetailedShow Float4 where 156 detailedShow (x,y,z,t) = printf "(%.20f,%.20f,%.20f,%.20f)" x y z t 157 158instance DetailedShow [Float] where 159 detailedShow l = ("[" ++) . ((intercalate "," (map detailedShow l)) ++) . ("]" ++) $ "" 160 161instance DetailedShow [Float4] where 162 detailedShow l = ("[" ++) . ((intercalate "," (map detailedShow l)) ++) . ("]" ++) $ "" 163 164 165-- | Create the NDRange from the global and local worksize 166ndRange :: WorkSize s -> WorkSize s -> Maybe (NDRange s) 167ndRange a@(WorkSize la) b@(WorkSize lb) = if all (uncurry isMultipleOf) (zip la lb) then Just (NDRange a b) else Nothing 168 169-- | Creatre an ND range with a worksize of 1 in each dimension 170simpleNDRange :: WorkSize s -> NDRange s 171simpleNDRange w = NDRange w (defaultLocalWs w) 172 173instance (Show (NDRange OneD)) where 174 show (NDRange wa wb) = show wa ++ " " ++ show wb 175 176instance (Show (NDRange TwoD)) where 177 show (NDRange wa wb) = show wa ++ " " ++ show wb 178 179instance (Show (NDRange ThreeD)) where 180 show (NDRange wa wb) = show wa ++ " " ++ show wb 181 182#ifdef OMAP4 183 184data Clocks = Clocks { 185 cpuClock :: CPUClock 186 , memClock :: MemClock 187 , gpuClock :: GPUClock 188 } deriving(Eq) 189 190{- 191 192WARNING : Those clock values DO NOT reflect the capabilities of the 193OMAP4 platform and OMAP derivatives. To know the maximum clock values for each 194OMAP4 derivative, please refer to the official Texas Instruments documentation. 195 196-} 197 198data CPUClock = CPU_1008MHz | CPU_800MHz deriving(Eq,Enum,Show) 199data MemClock = MEM_400MHz | MEM_200MHz deriving(Eq,Enum,Show) 200data GPUClock = GPU_307MHz | GPU_192MHz deriving(Eq,Enum,Show) 201 202defaultClocks = Clocks CPU_1008MHz MEM_400MHz GPU_307MHz 203 204instance Show Clocks where 205 show (Clocks a b c) = "(" ++ show (fromEnum a) ++ "," ++ show (fromEnum b) ++ "," ++ show (fromEnum c) ++ ")" 206 207#else 208data Clocks = Clocks 209 210defaultClocks = Clocks 211 212instance Show Clocks where 213 show _ = "(0,0,0)" 214#endif 215 216-- | Create a 1D worksize 217size1D :: Int -> WorkSize OneD 218size1D a = WorkSize [a] 219 220-- | Create a 2D worksize 221size2D :: Int -> Int -> WorkSize TwoD 222size2D a b = WorkSize [a,b] 223 224-- | Create a 3D worksize 225size3D :: Int -> Int -> Int -> WorkSize ThreeD 226size3D a b c = WorkSize [a,b,c] 227 228-- | Create the standard worksize with a size of 1 in each dimension and 229-- with a number of number given by the argument worksize 230defaultLocalWs :: WorkSize s -> WorkSize s 231defaultLocalWs (WorkSize l) = WorkSize $ replicate (length l) 1 232 233 234 235instance Show (WorkSize OneD) where 236 show (WorkSize (a:_)) = show a 237 show _ = error "Wrong number of elements for the worksize dimension" 238 239instance Show (WorkSize TwoD) where 240 show (WorkSize (a:b:_)) = "(" ++ show a ++ "," ++ show b ++ ")" 241 show _ = error "Wrong number of elements for the worksize dimension" 242 243instance Show (WorkSize ThreeD) where 244 show (WorkSize (a:b:c:_)) = "(" ++ show a ++ "," ++ show b ++ "," ++ show c ++ ")" 245 show _ = error "Wrong number of elements for the worksize dimension" 246 247-- | Data transfer mode for an argument 248data Mode a = Input a -- ^ The argument is an input 249 | InputOutput a -- ^ The argument is used as an input/output 250 deriving(Eq,Show) 251 252-- | Internal type for the argument 253-- used to generate the commands for the server 254data OCLARG = OCLInt (Mode Int32) 255 | OCLFloat (Mode Float) 256 | OCLFloat4 (Mode Float4) 257 | OCLIntList (Mode [Int32]) 258 | OCLFloatList (Mode [Float]) 259 | OCLFloat4List (Mode [Float4]) 260 | OCLConstantIntList (Mode (ArrayLength,Int32)) 261 | OCLConstantFloatList (Mode (ArrayLength,Float)) 262 | OCLConstantFloat4List (Mode (ArrayLength,Float)) 263 | OCLIntListOO ArrayLength 264 | OCLFloatListOO ArrayLength 265 | OCLFloat4ListOO ArrayLength 266 | OCLEnd 267 | OCLCommand String 268 deriving(Eq, Show) 269 270type ArrayLength = Int32 271 272-- | Create an output only float array 273clFloatArrayOO x = CLFloatArrayOO (fromIntegral x) 274 275-- | Create an output only float4 array 276clFloat4ArrayOO x = CLFloat4ArrayOO (fromIntegral x) 277 278-- | Create an output only int array 279clIntArrayOO x = CLIntArrayOO (fromIntegral x) 280 281-- | Create a constan int array 282clConstIntArray i f = CLConstIntArray (fromIntegral i) f 283 284-- | Create a constant float array 285clConstFloatArray i f = CLConstFloatArray (fromIntegral i) f 286 287-- | Create a constant float4 array 288clConstFloat4Array i f = CLConstFloat4Array (fromIntegral i) f 289 290-- | OpenCL Float value. 's' is used to identify if it is an input or an input /output 291data CLFloat s = CLFloat Float deriving(Eq,Show) 292 293-- | OpenCL Float value. 's' is used to identify if it is an input or an input /output 294data CLFloat4 s = CLFloat4 Float4 deriving(Eq,Show) 295 296-- | OpenCL int value. Warning : is is encoded as an Haskell Int which may be bigger 297data CLInt s = CLInt Int32 deriving(Eq,Show) 298 299-- | OpenCL array of int 300data CLIntArray s = CLIntArray [Int32] 301 | CLConstIntArray ArrayLength Int32 -- ^ Constant data generator used by the board to generate the data 302 deriving(Eq,Show) 303 304-- | OpenCL array of float 305data CLFloatArray s = CLFloatArray [Float] -- ^ The data is generated from the host 306 | CLConstFloatArray ArrayLength Float -- ^ Constant data generator used by the board to generate the data 307 deriving(Eq,Show) 308 309-- | A Float4 type 310type Float4 = (Float,Float,Float,Float) 311 312-- | OpenCL array of float4 313data CLFloat4Array s = CLFloat4Array [Float4] -- ^ The data is generated from the host 314 | CLConstFloat4Array ArrayLength Float -- ^ Constant data generator used by the board to generate the data 315 deriving(Eq,Show) 316 317-- | Output only OpenCL array of ints. The host is not transferring any data before running the kernel. 318-- The board is allocating the memory required to contain the output. 319data CLIntArrayOO = CLIntArrayOO ArrayLength deriving(Eq,Show) 320 321-- | Output only OpenCL array of float. The host is not transferring any data before running the kernel. 322-- The board is allocating the memory required to contain the output. 323data CLFloatArrayOO = CLFloatArrayOO ArrayLength deriving(Eq,Show) 324 325-- | Output only OpenCL array of float4. The host is not transferring any data before running the kernel. 326-- The board is allocating the memory required to contain the output. 327data CLFloat4ArrayOO = CLFloat4ArrayOO ArrayLength deriving(Eq,Show) 328 329-- | Used to tag an argument as input only 330data In 331 332-- | Used to tag an argument as input/output 333data InOut 334 335-- | Generate the part of the server command corresponding to a given argument type 336generateMsgElement (OCLInt (Input a)) = "IN INT:" ++ (show a) ++ ";" 337generateMsgElement (OCLInt (InputOutput a)) = "BOTH INT:" ++ (show a) ++ ";" 338 339generateMsgElement (OCLFloat (Input a)) = "IN FLOAT:" ++ (detailedShow a) ++ ";" 340generateMsgElement (OCLFloat (InputOutput a)) = "BOTH FLOAT:" ++ (detailedShow a) ++ ";" 341 342generateMsgElement (OCLFloat4 (Input a)) = "IN FLOAT4:" ++ (detailedShow a) ++ ";" 343generateMsgElement (OCLFloat4 (InputOutput a)) = "BOTH FLOAT4:" ++ (detailedShow a) ++ ";" 344 345generateMsgElement (OCLIntList (Input a)) = "IN INTLIST:" ++ (show a) ++ ";" 346generateMsgElement (OCLIntList (InputOutput a)) = "BOTH INTLIST:" ++ (show a) ++ ";" 347generateMsgElement (OCLIntListOO n) = "OUT INTLIST " ++ (show n) ++ ";" 348 349generateMsgElement (OCLFloatList (Input a)) = "IN FLOATLIST:" ++ (detailedShow a) ++ ";" 350generateMsgElement (OCLFloatList (InputOutput a)) = "BOTH FLOATLIST:" ++ (detailedShow a) ++ ";" 351 352generateMsgElement (OCLFloat4List (Input a)) = "IN FLOAT4LIST:" ++ (detailedShow a) ++ ";" 353generateMsgElement (OCLFloat4List (InputOutput a)) = "BOTH FLOAT4LIST:" ++ (detailedShow a) ++ ";" 354 355generateMsgElement (OCLConstantIntList (Input (nb,v))) = "IN INTLIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 356generateMsgElement (OCLConstantIntList (InputOutput (nb,v))) = "BOTH INTLIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 357 358 359generateMsgElement (OCLConstantFloatList (Input (nb,v))) = "IN FLOATLIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 360generateMsgElement (OCLConstantFloatList (InputOutput (nb,v))) = "BOTH FLOATLIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 361 362generateMsgElement (OCLConstantFloat4List (Input (nb,v))) = "IN FLOAT4LIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 363generateMsgElement (OCLConstantFloat4List (InputOutput (nb,v))) = "BOTH FLOAT4LIST: CONSTARRAY " ++ (show nb) ++ " " ++ detailedShow v ++ ";" 364 365generateMsgElement (OCLFloatListOO n) = "OUT FLOATLIST " ++ (show n) ++ ";" 366generateMsgElement (OCLFloat4ListOO n) = "OUT FLOAT4LIST " ++ (show n) ++ ";" 367 368generateMsgElement OCLEnd = "ENDMESSAGE" 369generateMsgElement (OCLCommand s) = s 370 371-- | Generate the final server command using the kernel name, global work size and kind of 372-- output wanted : data only or with data 373benchCommand s clock nb ignore | ignore = OCLCommand $ "KERNEL " ++ (show s) ++ " " ++ show clock ++ " " ++ (show nb) ++ " IGNORE ;" 374 | otherwise = OCLCommand $ "KERNEL " ++ (show s) ++ " " ++ show clock ++ " " ++ (show nb) ++ ";" 375 376-- | Data type to described the wanted output from the server 377data ResultMode = TimingOnly -- ^ The server is only returning the timing 378 | AllData -- ^ The server is also returning the data 379 deriving(Eq,Show) 380 381-- | Generate a Benchmark 382bench :: Benchmark r 383 => String -- ^ Kernel name 384 -> r 385bench s = generateCmd s [] 386 387 388-- | Each type which can be used as an argument of a kernel is an instance of this class 389class BenchmarkArg a where 390 toOCLARG :: String -> a -> OCLARG 391 392instance BenchmarkArg Float where 393 toOCLARG _ a = OCLFloat (Input a) 394 395instance BenchmarkArg Float4 where 396 toOCLARG _ a = OCLFloat4 (Input a) 397 398instance BenchmarkArg Int32 where 399 toOCLARG _ a = OCLInt (Input a) 400 401instance BenchmarkArg Int where 402 toOCLARG _ a = OCLInt (Input . fromIntegral $ a) 403 404instance BenchmarkArg (CLFloat In) where 405 toOCLARG _ (CLFloat a) = OCLFloat (Input a) 406 407instance BenchmarkArg (CLFloat InOut) where 408 toOCLARG _ (CLFloat a) = OCLFloat (InputOutput a) 409 410instance BenchmarkArg (CLFloat4 In) where 411 toOCLARG _ (CLFloat4 a) = OCLFloat4 (Input a) 412 413instance BenchmarkArg (CLFloat4 InOut) where 414 toOCLARG _ (CLFloat4 a) = OCLFloat4 (InputOutput a) 415 416instance BenchmarkArg (CLInt In) where 417 toOCLARG _ (CLInt a) = OCLInt (Input a) 418 419instance BenchmarkArg (CLInt InOut) where 420 toOCLARG _ (CLInt a) = OCLInt (InputOutput a) 421 422instance BenchmarkArg (CLIntArray In) where 423 toOCLARG _ (CLIntArray a) = OCLIntList (Input a) 424 toOCLARG _ (CLConstIntArray nb v) = OCLConstantIntList (Input (nb,v)) 425 426instance BenchmarkArg (CLIntArray InOut) where 427 toOCLARG _ (CLIntArray a) = OCLIntList (InputOutput a) 428 toOCLARG _ (CLConstIntArray nb v) = OCLConstantIntList (Input (nb,v)) 429 430instance BenchmarkArg (CLFloatArray In) where 431 toOCLARG _ (CLFloatArray a) = OCLFloatList (Input a) 432 toOCLARG _ (CLConstFloatArray nb v) = OCLConstantFloatList (Input (nb,v)) 433 434instance BenchmarkArg (CLFloatArray InOut) where 435 toOCLARG _ (CLFloatArray a) = OCLFloatList (InputOutput a) 436 toOCLARG _ (CLConstFloatArray nb v) = OCLConstantFloatList (InputOutput (nb,v)) 437 438instance BenchmarkArg (CLFloat4Array In) where 439 toOCLARG _ (CLFloat4Array a) = OCLFloat4List (Input a) 440 toOCLARG _ (CLConstFloat4Array nb v) = OCLConstantFloat4List (Input (nb,v)) 441 442instance BenchmarkArg (CLFloat4Array InOut) where 443 toOCLARG _ (CLFloat4Array a) = OCLFloat4List (InputOutput a) 444 toOCLARG _ (CLConstFloat4Array nb v) = OCLConstantFloat4List (InputOutput (nb,v)) 445 446 447 448instance BenchmarkArg (CLIntArrayOO) where 449 toOCLARG _ (CLIntArrayOO n) = OCLIntListOO n 450 451instance BenchmarkArg (CLFloatArrayOO) where 452 toOCLARG _ (CLFloatArrayOO n) = OCLFloatListOO n 453 454instance BenchmarkArg (CLFloat4ArrayOO) where 455 toOCLARG _ (CLFloat4ArrayOO n) = OCLFloat4ListOO n 456 457instance BenchmarkArg [Float] where 458 toOCLARG _ a = OCLFloatList (Input a) 459 460instance BenchmarkArg [Float4] where 461 toOCLARG _ a = OCLFloat4List (Input a) 462 463instance BenchmarkArg (Clocks, NDRange OneD,ResultMode) where 464 toOCLARG c (clocks,nb,TimingOnly) = benchCommand c clocks nb True 465 toOCLARG c (clocks,nb,_) = benchCommand c clocks nb False 466 467instance BenchmarkArg (Clocks, NDRange TwoD,ResultMode) where 468 toOCLARG c (clocks,nb,TimingOnly) = benchCommand c clocks nb True 469 toOCLARG c (clocks,nb,_) = benchCommand c clocks nb False 470 471instance BenchmarkArg (Clocks, NDRange ThreeD,ResultMode) where 472 toOCLARG c (clocks,nb,TimingOnly) = benchCommand c clocks nb True 473 toOCLARG c (clocks,nb,_) = benchCommand c clocks nb False 474 475 476-- | Magic class used to implement a function with a varying number 477-- of argument using different types. 478class Benchmark r where 479 generateCmd :: String -> [OCLARG] -> r 480 481-- | String is of benchmark kind since we want to be able to generate 482-- a string of command from a Benchmark 483instance Benchmark String where 484 generateCmd s (kernel:args) = let cmds = kernel:reverse (OCLEnd:args) 485 in 486 concatMap generateMsgElement cmds 487 488-- | A benchmark taking one argument is equivalent to a new argument command for the server 489-- plus a benchmark without this argument 490instance (BenchmarkArg a,Benchmark r) => Benchmark (a -> r) where 491 generateCmd c args = \a -> generateCmd c (toOCLARG c a:args) 492 493-- | Send command to the server and read the timing and data returned by the server 494onBoard :: Options -> Clocks -> NDRange s -> ((Clocks, NDRange s, ResultMode) -> String) -> IO BenchResult 495onBoard opts clocks global_ws a = runCmd opts $ \h -> executeBench h (a (clocks,global_ws,AllData)) 496 497-- | Send command to the server and read the timing returned by the server. 498-- The server is not returning any data to minimize the communication costs. 499onBoardOnlyTiming :: Options -> Clocks -> NDRange s -> ((Clocks, NDRange s, ResultMode) -> String) -> IO TimingResult 500onBoardOnlyTiming opts clocks global_ws a = do 501 BenchResult (t,_) <- runCmd opts $ \h -> executeBench h (a (clocks,global_ws,TimingOnly)) 502 return t 503 504-- | Send command to the server and read the data returned by the server. 505-- Timing data are just dropped and not returned. But timing data (small) are nevertheless returned from 506-- the server 507onBoardOnlyData :: Options -> NDRange s -> ((Clocks,NDRange s, ResultMode) -> String) -> IO DataResults 508onBoardOnlyData opts global_ws a = do 509 BenchResult (_,v) <- runCmd opts $ \h -> executeBench h (a (defaultClocks, global_ws,AllData)) 510 return v 511 512-- | Send the end of simulation command 513endSimu :: Options -> IO () 514endSimu opts = runCmd opts $ \h -> do 515 hPutStrLn h $ "END" 516 hFlush h 517 518-- | Send a command to the server socket 519runCmd :: Options -> (Handle -> IO a) -> IO a 520runCmd opts a = do 521 addrinfos <- getAddrInfo Nothing (Just (addr opts)) (Just (port opts)) 522 let serveraddr = head addrinfos 523 sock <- socket (addrFamily serveraddr) Stream defaultProtocol 524 setSocketOption sock KeepAlive 1 525 connect sock (addrAddress serveraddr) 526 527 -- Make a Handle out of it for convenience 528 h <- socketToHandle sock ReadWriteMode 529 hSetBuffering h (BlockBuffering Nothing) 530 r <- a h 531 hClose h 532 return r 533 534data DataResult = FloatResult [Float] | Float4Result [Float4] | IntResult [Int32] deriving(Eq,Show) 535 536-- | Extract the float result 537fromFloatResult :: DataResult -> [Float] 538fromFloatResult (FloatResult l) = l 539fromFloatResult _ = error "Can't get a float result" 540 541-- | Extract the float4 result 542fromFloat4Result :: DataResult -> [Float4] 543fromFloat4Result (Float4Result l) = l 544fromFloat4Result _ = error "Can't get a float result" 545 546-- | Extract the int result 547fromIntResult :: DataResult -> [Int32] 548fromIntResult (IntResult l) = l 549fromIntResult _ = error "Can't get a int result" 550 551 552-- | Result of a benchmark : timing and list of OpenCL arrays 553newtype BenchResult = BenchResult (TimingResult,DataResults) deriving(Eq,Show) 554 555-- | Data only result : list of OpenCL arrays 556type DataResults = [DataResult] 557 558 559type CLBufferCreationTime = Double 560type CLBufferWriteTime = Double 561type CLExecutionTime = Double 562type CLReadingResultTime = Double 563 564-- | Timing only result 565-- Creation time, execution time, result time and execution time measured by the HLOS (see DESIGN doc) 566type TimingResult = (CLBufferCreationTime,CLBufferWriteTime,CLExecutionTime,CLReadingResultTime) 567 568-- | Write the command to the server socket and read the results 569executeBench :: Handle -> String -> IO BenchResult 570executeBench h command = do 571 --putStrLn command 572 hPutStrLn h command 573 hFlush h 574 getResult h 575 --return $ BenchResult ((0.0,0.0,0.0),[[1.0]]) 576 577{- 578 579Reading result 580 581-} 582 583-- | Read an array of float 584getArray h l = do 585 nb <- hGetLine h 586 if (nb == ".") 587 then 588 return (reverse l) 589 else 590 getArray h (read nb:l) 591 592-- | Read a result from the socket. 593-- * is end of result transmissions 594-- t is timing result 595-- rl is array of float 596readResult h t l = do 597 c <- hGetLine h 598 case c of 599 "*" -> return $ BenchResult (t,l) 600 "t" -> do 601 c <- hGetLine h 602 w <- hGetLine h 603 e <- hGetLine h 604 r <- hGetLine h 605 let createTime = read c :: Double 606 writeTime = read w :: Double 607 executeTime = read e :: Double 608 readTime = read r :: Double 609 readResult h (createTime,writeTime,executeTime,readTime) l 610 "rl" -> do 611 nl <- getArray h [] :: IO [Float] 612 readResult h t (FloatResult nl:l) 613 "zl" -> do 614 nl <- getArray h [] :: IO [Float4] 615 readResult h t (Float4Result nl:l) 616 "nl" -> do 617 nl <- getArray h [] :: IO [Int32] 618 readResult h t (IntResult nl:l) 619 _ -> return $ BenchResult (t,reverse l) 620 621-- | Parse a result from the socket 622getResult :: Handle -> IO BenchResult 623getResult h = readResult h (0.0,0.0,0.0,0.0) [] 624