PageRenderTime 60ms CodeModel.GetById 32ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Client/Benchmark.hs

http://github.com/ChristopheF/OpenCLTestFramework
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