Commit a08e1db9 authored by Valentin Reis's avatar Valentin Reis
Browse files

[fix] sensor and configuration file fixes

- adding minimum sensor window
- fixing sensor trapezoidal calculation bug
- renaming RAPL correctly as "passive" sensor
- removing useless fixed power argument, replaced by NoControl
parent 1e515576
Pipeline #11588 failed with stages
in 3 minutes and 41 seconds
......@@ -48,7 +48,7 @@ foreign export ccall verbosityExport :: Ex
foreign export ccall logfileExport :: Ex
foreign export ccall activeSensorFrequencyExport :: Ex
foreign export ccall passiveSensorFrequencyExport :: Ex
foreign export ccall upstreamRpcAddressExport :: Ex
......@@ -88,7 +88,7 @@ verbosityExport = exportIO E.verbosity
logfileExport = exportIO E.logfile
activeSensorFrequencyExport = exportIO E.activeSensorFrequency
passiveSensorFrequencyExport = exportIO E.passiveSensorFrequency
upstreamRpcAddressExport = exportIO E.upstreamRpcAddress
......
......@@ -9,12 +9,12 @@
-- Maintainer : fre@freux.fr
module CPD.Integrated
( Integrator (..),
IntegratorMeta (..),
IntegratorAction (..),
MeasurementState (..),
M (..),
trapezoidArea,
initIntegrator,
throughTuple,
measureValue,
squeeze,
averageArea,
......@@ -25,6 +25,7 @@ import CPD.Core
import Control.Lens
import qualified Data.Aeson as A
import Data.Data
import Data.Functor (($>))
import Data.Generics.Labels ()
import Data.JSON.Schema
import qualified Data.Map as M
......@@ -36,9 +37,16 @@ import Protolude
data Integrator
= Integrator
{ tLast :: Time,
minimumControlInterval :: Time,
measured :: Map SensorID (MeasurementState M)
{ meta :: IntegratorMeta,
measured :: Map SensorID (MeasurementState M) -- measurement states
}
deriving (Generic)
data IntegratorMeta
= IntegratorMeta
{ tLast :: Time, -- time the last control loop was finished (init time)
minimumWaitInterval :: Time, -- wait period between measurement periods
minimumControlInterval :: Time -- delta min for measurement period
}
deriving (Generic)
......@@ -84,13 +92,20 @@ trapezoidArea (t1, v1) (t2, v2) =
where
deltaT = fromuS (t2 - t1)
measureValue :: Time -> (Time, Double) -> MeasurementState M -> MeasurementState M
measureValue delta (newTime, newValue) = \case
Never -> Discarded
measureValue ::
IntegratorMeta ->
(Time, Double) ->
MeasurementState M ->
MeasurementState M
measureValue meta (newTime, newValue) = \case
Never ->
if minimumWaitInterval meta + tLast meta <= newTime
then Discarded
else Never
Discarded -> Running initial
Done m -> Done $ measure m
Running m ->
( if newTime >= delta + firstTime m
( if newTime >= minimumControlInterval meta + firstTime m
then Done
else Running
)
......@@ -114,26 +129,23 @@ averageArea M {firstTime, lastTime, lastValue, area} =
where
deltaT = fromuS (lastTime - firstTime)
-- | Tries to 'squeeze' the sensors for values. A squeeze is only successfull
-- if all sensors are in the Done state.
squeeze ::
Time ->
Map SensorID (MeasurementState M) ->
Maybe (Map SensorID Double, Map SensorID (MeasurementState M))
squeeze _t mstM =
case traverse throughTuple (M.toList mstM) of
Done (M.fromList -> m) -> Just (m <&> averageArea, m <&> const Never)
case traverse sequenceA (M.toList mstM) of
Done (M.fromList -> m) -> Just (m <&> averageArea, m $> Never)
_ -> Nothing
throughTuple :: Functor f => (a, f b) -> f (a, b)
throughTuple (id, m) = (id,) <$> m
initIntegrator ::
Time ->
Time ->
IntegratorMeta ->
[SensorID] ->
Integrator
initIntegrator t tmin sensorIDs =
initIntegrator meta sensorIDs =
Integrator
{ tLast = t,
minimumControlInterval = tmin,
{ meta = meta,
measured = M.fromList (sensorIDs <&> (,Never))
}
......@@ -212,7 +212,7 @@ nrm _callTime (ChildDied pid exitcode) = do
put $
st
& #slices
. at sliceID
. at sliceID
?~ (slice & #cmds . at cmdID ?~ cmd {processState = newPstate})
nrm callTime (DownstreamEvent clientid msg) =
nrmDownstreamEvent callTime clientid msg
......@@ -253,7 +253,7 @@ doControl input = do
zoom (#controller . _Just) $ do
logInfo ("Control input:" <> show input)
mccfg & \case
FixedCommand _ -> pass
NoControl -> pass
ccfg@ControlCfg {} ->
let cpd = NRMCPD.toCPD ccfg st
mRefActions =
......@@ -262,10 +262,11 @@ doControl input = do
( M.toList (lenses st) ::
[(ActuatorKey, ScopedLens NRMState A.Actuator)]
)
<&> \(k, ScopedLens l) -> CPD.Action
{ actuatorID = toS k,
actuatorValue = CPD.DiscreteDouble $ st ^. l . #referenceAction
}
<&> \(k, ScopedLens l) ->
CPD.Action
{ actuatorID = toS k,
actuatorValue = CPD.DiscreteDouble $ st ^. l . #referenceAction
}
else Nothing
in banditCartesianProductControl ccfg cpd input mRefActions >>= \case
DoNothing -> pass
......@@ -388,8 +389,9 @@ nrmDownstreamEvent callTime clientid = \case
Just c -> do
put $
Just
( c & #downstreamCmds
. at downstreamCmdID
( c
& #downstreamCmds
. at downstreamCmdID
.~ Nothing
)
log "downstream cmd un-registered."
......@@ -407,8 +409,9 @@ nrmDownstreamEvent callTime clientid = \case
Just c -> do
put $
Just
( c & #downstreamThreads
. at downstreamThreadID
( c
& #downstreamThreads
. at downstreamThreadID
.~ Nothing
)
log "downstream thread un-registered."
......
......@@ -33,12 +33,15 @@ toCPD cfg st = Problem {..}
where
sensors = cpdSensors st
actuators = cpdActuators st
(objectives, constraints) = fromMaybe ([], []) (throughputConstrained <$> mcfg cfg <*> Just st)
(objectives, constraints) =
fromMaybe
([], [])
(throughputConstrained <$> mcfg cfg <*> Just st)
mcfg jc@ControlCfg {} = Just jc
mcfg _ = Nothing
-- | This problem generator produces a global energy minimization problem under a
-- throughput constraint.
-- | This problem generator produces a global energy minimization problem under
-- a throughput constraint.
throughputConstrained ::
-- | Control configuration
ControlCfg ->
......@@ -54,7 +57,10 @@ throughputConstrained cfg st =
let powerTerm =
coerce (foldMap (OExprSum . sID) ids)
\+ scalar (fromWatts $ staticPower cfg)
in [(Bandit.Types.one, maybe powerTerm (powerTerm \/) normalizedSumSlowdown)],
in [ ( Bandit.Types.one,
maybe powerTerm (powerTerm \/) normalizedSumSlowdown
)
],
normalizedSumSlowdown & \case
Nothing -> []
Just expr -> [(speedThreshold cfg, expr)]
......@@ -63,13 +69,21 @@ throughputConstrained cfg st =
normalizedSumSlowdown :: Maybe OExpr
normalizedSumSlowdown =
nonEmpty (M.toList constrained) <&> \(fmap fst -> ids) ->
thresholded 0.5 1.5 (coerce (foldMap (OExprSum . sID) ids) \/ (coerce (foldMap (OExprSum . sRef) ids) \+ scalar 1))
thresholded
0.5
1.5
( coerce (foldMap (OExprSum . sRef) ids)
\/ (coerce (foldMap (OExprSum . sID) ids) \+ scalar 1)
)
idsToMinimize :: Maybe (NonEmpty SensorID)
idsToMinimize = nonEmpty (fst <$> M.toList toMinimize)
toMinimize :: Map SensorID SensorMeta
toMinimize = M.filterWithKey (\_ m -> Power `elem` S.tags m) allSensorMeta
constrained :: Map SensorID SensorMeta
constrained = M.filterWithKey (\_ m -> DownstreamCmdSignal `elem` S.tags m) allSensorMeta
constrained =
M.filterWithKey
(\_ m -> DownstreamCmdSignal `elem` S.tags m)
allSensorMeta
allSensorMeta :: Map SensorID S.SensorMeta
allSensorMeta =
M.fromList
......@@ -81,7 +95,9 @@ throughputConstrained cfg st =
-- | produces a sum objective normalized by #sensors
addAll :: NonEmpty SensorID -> OExpr
addAll ss = coerce (foldMap (OExprSum . sID) ss) \/ (scalar . fromIntegral $ length ss)
addAll ss =
coerce (foldMap (OExprSum . sID) ss)
\/ (scalar . fromIntegral $ length ss)
-- | Subtract two objectives, defaulting to either of them
-- if one is absent.
......
......@@ -52,8 +52,8 @@ banditCartesianProductControl ::
ControlM Decision
banditCartesianProductControl ccfg cpd (Reconfigure t) _ = do
pub (UPub.PubCPD t cpd)
minTime <- use $ #integrator . #minimumControlInterval
#integrator .= initIntegrator t minTime (M.keys $ sensors cpd)
meta <- use $ #integrator . #meta
#integrator .= initIntegrator meta (M.keys $ sensors cpd)
case (CPD.Core.objectives cpd, M.toList (actuators cpd)) of
([], _) -> reset
(_, l) ->
......@@ -129,13 +129,12 @@ banditCartesianProductControl ccfg cpd (NoEvent t) mRefActions =
banditCartesianProductControl ccfg cpd (Event t ms) mRefActions = do
forM_ ms $ \m@(Measurement sensorID sensorValue sensorTime) -> do
log $ "Processing measurement " <> show m
#integrator %= \(Integrator tlast delta measuredM) ->
Integrator
tlast
delta
( measuredM
& ix sensorID
%~ measureValue delta (sensorTime, sensorValue)
#integrator
%= execState
( do
meta <- use #meta
#measured . ix sensorID
%= measureValue meta (sensorTime, sensorValue)
)
tryControlStep ccfg cpd t mRefActions
......@@ -196,6 +195,7 @@ wrappedCStep cc stepObjectives stepConstraints sensorRanges t mRefActions = do
Just (measurements, newMeasured) -> do
-- squeeze was successfull: setting the new integrator state
logInfo "control: integrator squeeze success"
#integrator . #meta . #tLast .= t
#integrator . #measured .= newMeasured
-- acquiring fields
counter <- use #referenceMeasurementCounter
......
......@@ -11,7 +11,7 @@ module NRM.Export
verbosity,
showConfiguration,
C.logfile,
activeSensorFrequency,
passiveSensorFrequency,
upstreamPubAddress,
upstreamRpcAddress,
downstreamEventAddress,
......@@ -46,8 +46,8 @@ import qualified NRM.Types.Configuration as C
DaemonVerbosity (..),
DownstreamCfg (..),
UpstreamCfg (..),
activeSensorFrequency,
logfile,
passiveSensorFrequency,
verbose,
)
import qualified NRM.Types.Messaging.UpstreamRep as URep
......@@ -64,8 +64,8 @@ parseDaemon :: [Text] -> IO C.Cfg
parseDaemon = O.parseArgDaemonCli
-- | Parses Daemon CLI arguments
activeSensorFrequency :: C.Cfg -> Double
activeSensorFrequency = fromHz . C.activeSensorFrequency
passiveSensorFrequency :: C.Cfg -> Double
passiveSensorFrequency = fromHz . C.passiveSensorFrequency
-- | Queries configuration for 'verbose' verbosity
verbosity :: C.Cfg -> Int
......
......@@ -11,7 +11,7 @@ module NRM.ExportIO
verbosity,
showConfiguration,
logfile,
activeSensorFrequency,
passiveSensorFrequency,
upstreamPubAddress,
upstreamRpcAddress,
downstreamEventAddress,
......@@ -45,8 +45,8 @@ verbosity = return . E.verbosity
logfile :: C.Cfg -> IO Text
logfile = return . E.logfile
activeSensorFrequency :: C.Cfg -> IO Double
activeSensorFrequency = return . E.activeSensorFrequency
passiveSensorFrequency :: C.Cfg -> IO Double
passiveSensorFrequency = return . E.passiveSensorFrequency
upstreamPubAddress :: C.Cfg -> IO Text
upstreamPubAddress = return . E.upstreamPubAddress
......
......@@ -19,6 +19,7 @@ module NRM.State
)
where
import CPD.Integrated as I
import Control.Lens
import Data.Map as M
import Data.Map.Merge.Lazy
......@@ -66,7 +67,7 @@ initialState c time = do
updater _pkgid package (packageRaplConfig, packageRaplDir) =
package
{ rapl = Just Rapl
{ frequency = hz 3,
{ frequency = passiveSensorFrequency c,
raplCfg = packageRaplConfig,
maxEnergyCounterValue = packageRaplDir ^. #maxEnergy,
max = watts 150,
......@@ -86,8 +87,16 @@ initialState c time = do
return newPkgs
return NRMState
{ controller = controlCfg c & \case
FixedCommand _ -> Nothing
ccfg -> Just $ initialController time (minimumControlInterval ccfg) [],
NoControl -> Nothing
ccfg ->
Just $
initialController
IntegratorMeta
{ tLast = time,
I.minimumWaitInterval = Cfg.minimumWaitInterval ccfg,
I.minimumControlInterval = Cfg.minimumControlInterval ccfg
}
[],
slices = M.fromList [],
pus = M.fromList $ (,PU) <$> selectPUIDs hwl,
cores = M.fromList $ (,Core) <$> selectCoreIDs hwl,
......@@ -108,7 +117,7 @@ initialState c time = do
<&> NRMState.ExtraActuator,
extraStaticPassiveSensors =
Cfg.extraStaticPassiveSensors c
<&> concretizeExtraPassiveSensor (activeSensorFrequency c),
<&> concretizeExtraPassiveSensor (passiveSensorFrequency c),
..
}
......@@ -116,12 +125,13 @@ concretizeExtraPassiveSensor ::
Frequency ->
Cfg.ExtraPassiveSensor ->
NRMState.ExtraPassiveSensor
concretizeExtraPassiveSensor f x = NRMState.ExtraPassiveSensor
{ NRMState.extraPassiveSensor = x,
NRMState.history = [],
NRMState.lastRead = Nothing,
NRMState.frequency = f
}
concretizeExtraPassiveSensor f x =
NRMState.ExtraPassiveSensor
{ NRMState.extraPassiveSensor = x,
NRMState.history = [],
NRMState.lastRead = Nothing,
NRMState.frequency = f
}
-- | Removes a slice from the state
removeSlice :: SliceID -> NRMState -> (Maybe Slice, NRMState)
......
......@@ -67,7 +67,7 @@ data Cfg
raplCfg :: Maybe RaplCfg,
hwmonCfg :: HwmonCfg,
controlCfg :: ControlCfg,
activeSensorFrequency :: Frequency,
passiveSensorFrequency :: Frequency,
extraStaticPassiveSensors :: Map Text ExtraPassiveSensor,
extraStaticActuators :: Map Text ExtraActuator
}
......@@ -98,15 +98,14 @@ data ExtraPassiveSensor
data ControlCfg
= ControlCfg
{ minimumControlInterval :: Time,
minimumWaitInterval :: Time,
staticPower :: Power,
learnCfg :: LearnConfig,
speedThreshold :: Double,
referenceMeasurementRoundInterval :: Refined (GreaterThan 5) Int,
hint :: Hint
}
| FixedCommand
{ fixedPower :: Power
}
| NoControl
deriving (Eq, Show, Generic, MessagePack, Interpret, Inject)
deriving (JSONSchema, ToJSON, FromJSON) via GenericJSON ControlCfg
......@@ -145,7 +144,8 @@ data UpstreamCfg
instance Default ControlCfg where
def = ControlCfg
{ minimumControlInterval = 0.1 & seconds,
{ minimumControlInterval = 1 & seconds,
minimumWaitInterval = 1 & seconds,
staticPower = watts 200,
speedThreshold = 1.1,
learnCfg = Contextual (CtxCfg 4000),
......@@ -187,8 +187,8 @@ instance Default Cfg where
raplCfg = Just def,
hwmonCfg = def,
verbose = NRM.Types.Configuration.Error,
controlCfg = FixedCommand (watts 250),
activeSensorFrequency = 1 & hz,
controlCfg = NoControl,
passiveSensorFrequency = 1 & hz,
extraStaticPassiveSensors = [],
extraStaticActuators = []
}
......
......@@ -161,13 +161,12 @@ enqueueAll =
(zipWithMatched $ \_ a abuffer -> enqueue a abuffer)
initialController ::
Time ->
Time ->
IntegratorMeta ->
[SensorID] ->
Controller
initialController time minTime sensorIDs =
initialController integratorMeta sensorIDs =
Controller
{ integrator = initIntegrator time minTime sensorIDs,
{ integrator = initIntegrator integratorMeta sensorIDs,
lastA = Nothing,
bandit = Nothing,
armstats = M.empty,
......@@ -325,6 +324,12 @@ deriving via (GenericJSON Integrator) instance A.ToJSON Integrator
deriving via (GenericJSON Integrator) instance A.FromJSON Integrator
deriving via (GenericJSON IntegratorMeta) instance JSONSchema IntegratorMeta
deriving via (GenericJSON IntegratorMeta) instance A.ToJSON IntegratorMeta
deriving via (GenericJSON IntegratorMeta) instance A.FromJSON IntegratorMeta
deriving instance Show Integrator
deriving instance MessagePack Integrator
......@@ -333,6 +338,14 @@ deriving instance FromDhall Integrator
deriving instance ToDhall Integrator
deriving instance Show IntegratorMeta
deriving instance MessagePack IntegratorMeta
deriving instance FromDhall IntegratorMeta
deriving instance ToDhall IntegratorMeta
deriving via (GenericJSON (Arms [Action])) instance JSONSchema (Arms [Action])
deriving via (GenericJSON (Arms [Action])) instance A.ToJSON (Arms [Action])
......
......@@ -74,6 +74,9 @@ newtype Energy = Energy {fromuJ :: Double}
deriving (Eq, Ord, Generic, Data, Inject, Interpret, MessagePack)
deriving (Show, Num, JSONSchema, ToJSON, FromJSON) via Double
mil :: Double
mil = 1000000
-- | Microjoule value constructor.
progress :: Int -> Progress
progress = Progress
......@@ -84,11 +87,11 @@ uJ = Energy
-- | Joule value accessor.
fromJoules :: Energy -> Double
fromJoules = (/ 1000000) . fromuJ
fromJoules = (/ mil) . fromuJ
-- | Watt value constructor.
joules :: Double -> Energy
joules = Energy . (* 1000000.0)
joules = Energy . (* mil)
-- | Microwatt value constructor.
uW :: Double -> Power
......@@ -96,11 +99,11 @@ uW = Power
-- | Watt value accessor.
fromWatts :: Power -> Double
fromWatts = (/ 1000000) . fromuW
fromWatts = (/ mil) . fromuW
-- | Watt value constructor.
watts :: Double -> Power
watts = Power . (* 1000000.0)
watts = Power . (* mil)
-- | Microsecond value constructor.
uS :: Double -> Time
......@@ -108,10 +111,10 @@ uS = Time
-- | Second value constructor.
seconds :: Double -> Time
seconds = Time . (* 1000000)
seconds = Time . (* mil)
fromSeconds :: Time -> Double
fromSeconds (Time t) = t / 1000000
fromSeconds (Time t) = t / mil
-- | Hertz value constructor.
hz :: Double -> Frequency
......
......@@ -31,6 +31,7 @@
, controlCfg =
< ControlCfg :
{ minimumControlInterval : { fromuS : Double }
, minimumWaitInterval : { fromuS : Double }
, staticPower : { fromuW : Double }
, learnCfg :
< Lagrange : { lagrange : Double }
......@@ -52,10 +53,9 @@
}
>
}
| FixedCommand : { fixedPower : { fromuW : Double } }
>.FixedCommand
{ fixedPower = { fromuW = 2.5e8 } }
, activeSensorFrequency = { fromHz = 1.0 }
| NoControl
>.NoControl
, passiveSensorFrequency = { fromHz = 1.0 }
, extraStaticPassiveSensors =
[] : List
{ mapKey : Text
......
......@@ -5,20 +5,13 @@
"logfile": "/tmp/nrm.log",
"singularity": false,
"argo_nodeos_config": "argo_nodeos_config",
"controlCfg": {
"fixedPower": {
"fromuW": 250000000
}
},
"controlCfg": "NoControl",
"upstreamCfg": {
"upstreamBindAddress": "*",
"rpcPort": 3456,
"pubPort": 2345
},
"libnrmPath": null,
"activeSensorFrequency": {
"fromHz": 1
},
"perf": "perf",
"argo_perf_wrapper": "nrm-perfwrapper",
"downstreamCfg": {
......@@ -46,5 +39,8 @@
"hwmonCfg": {
"hwmonPath": "/sys/class/hwmon",
"hwmonEnabled": true
},
"passiveSensorFrequency": {
"fromHz": 1
}
}
\ No newline at end of file
......@@ -13,16 +13,12 @@ verbose: Error
logfile: /tmp/nrm.log
singularity: false
argo_nodeos_config: argo_nodeos_config
controlCfg:
fixedPower:
fromuW: 2.5e8
controlCfg: NoControl
upstreamCfg:
upstreamBindAddress: '*'
rpcPort: 3456
pubPort: 2345
libnrmPath: null
activeSensorFrequency:
fromHz: 1
perf: perf
argo_perf_wrapper: nrm-perfwrapper
downstreamCfg:
......@@ -42,3 +38,5 @@ slice_runtime: Dummy
hwmonCfg:
hwmonPath: /sys/class/hwmon
hwmonEnabled: true
passiveSensorFrequency:
fromHz: 1