[add][fix] added output that can be run parallel to the simulation

- the output sleep waits for a full tick result
 - [fix] fixed the simulation to pass the correct gt parent if exists
This commit is contained in:
2020-01-29 01:19:10 -06:00
parent fee44785d4
commit 1e61253b3b
3 changed files with 26 additions and 13 deletions

View File

@@ -1,13 +1,15 @@
package scim.components package scim.components
import scim.datastruct.SharedMemory import scim.datastruct.{Cell, Group, SensorResult, SharedMemory}
class Output(sharedMemory: SharedMemory) extends Runnable { class Output(sharedMemory: SharedMemory) extends Runnable {
def run(): Unit = { def run(): Unit = {
outputData() val output = sharedMemory.output
(0 until output.size, output).zipped.foreach((time, result) => outputData(time, result.watch()))
} }
def outputData(): Unit = { def outputData(time: Int, output: Map[Cell, Map[Group, Vector[SensorResult]]]): Unit = {
println("TICK: " + time)
println(output)
} }
} }

View File

@@ -7,6 +7,7 @@ class Simulation(config: Configuration) {
private val sharedMemory = config.sharedMemory private val sharedMemory = config.sharedMemory
private val sharedConfig = sharedMemory.config private val sharedConfig = sharedMemory.config
private val cells = config.cells private val cells = config.cells
val output = sharedMemory.output
def start(): Unit = { def start(): Unit = {
@@ -38,6 +39,8 @@ class Simulation(config: Configuration) {
} else { } else {
cells.foreach(simCell) cells.foreach(simCell)
} }
// broadcast the results
output(time.time).broadcast(sensorResults)
} }
private def simGroups(time: Time, cell: Cell, groups: Map[Group, List[(Group, Sensor, Option[GroundTruth])]], prevTruths: Map[Group, Truth], resultTruths: Map[Group, Truth], resultSensors: Map[Group, Vector[SensorResult]]): Unit = { private def simGroups(time: Time, cell: Cell, groups: Map[Group, List[(Group, Sensor, Option[GroundTruth])]], prevTruths: Map[Group, Truth], resultTruths: Map[Group, Truth], resultSensors: Map[Group, Vector[SensorResult]]): Unit = {
@@ -46,12 +49,14 @@ class Simulation(config: Configuration) {
// at the same time as the parent in a different thread. This would allow the child to start running as soon // at the same time as the parent in a different thread. This would allow the child to start running as soon
// as the ground truth is calculated in the parent and doesn't have have to wait for the sensors to finish. // as the ground truth is calculated in the parent and doesn't have have to wait for the sensors to finish.
// Any subsequent children can start in the same manner, when their parent is done with the ground truth. // Any subsequent children can start in the same manner, when their parent is done with the ground truth.
// this would require sharedConfig.cellThreadPool * 2 additional threads
// : // :
// only run ground truth in list, have sensors in their respective groups // another option would be to calculate all ground truths within a list first and than parellize the sensor list
// requires groups to be split into two elements: sensor and ground truth def simGroup(input: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = {
// Tuple2(Map[Group, list[(Group, Option[GroundTruth])]], Map[Group, Sensor]) val group = input._1
def simGroup(group: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = { val truthGroup = group.getParentOrGroup // make sure the correct ground truth gets passed
group._2.foreach(element => simulate(time, cell, prevTruths(group._1), resultTruths(group._1), resultSensors(group._1), element)) val groupList = input._2
groupList.foreach(element => simulate(time, cell, prevTruths(truthGroup), resultTruths(group), resultSensors(group), element))
} }
if(sharedConfig.parGroup != 0 && cells.size >= sharedConfig.parGroup ) { if(sharedConfig.parGroup != 0 && cells.size >= sharedConfig.parGroup ) {
val groupList = groups.par val groupList = groups.par

View File

@@ -15,9 +15,13 @@ case class Time(time: Int, duration: Int){
def get: Int = { time } def get: Int = { time }
} }
case class SharedMemory( sensor: Map[Time, Map[Cell, Map[Group, Vector[SensorResult]]]], // while it would seem convinient to just throw the sensors/behaviours as value into these
// and have them just hold their value, this would get messy with dependencies:
// Map[Time, Map[Cell, Map[Group, List(Group, Truth)]]] and getting the result for the sensor
case class SharedMemory(sensor: Map[Time, Map[Cell, Map[Group, Vector[SensorResult]]]],
groundTruth: Map[Time, Map[Cell, Map[Group, Truth]]], groundTruth: Map[Time, Map[Cell, Map[Group, Truth]]],
config: SimulationConfig, cache: Boolean = true) { config: SimulationConfig,
output: Vector[BroadcastObject[Map[Cell, Map[Group, Vector[SensorResult]]]]]) {
// This could be spatially optimized to have a function to invoke a new simulation tick // This could be spatially optimized to have a function to invoke a new simulation tick
// a template of Map[SensorID, SensorResult] would have to be kept and deep copied when // a template of Map[SensorID, SensorResult] would have to be kept and deep copied when
// another tick is simulated. this won't work for ground truth, as it may already be defined // another tick is simulated. this won't work for ground truth, as it may already be defined
@@ -99,6 +103,8 @@ case class Behaviour(behaviour: BehaviourVector){
} }
} }
// while the gt depends on the cell, the object itself does not
// unlike the sensor which is unique due to its count for each cell
case class GroundTruth(group: Group, behaviour: Option[Behaviour]) { case class GroundTruth(group: Group, behaviour: Option[Behaviour]) {
def simulate(cell: Cell, time: Time, prevTruth: Truth, result: Truth): Unit = { def simulate(cell: Cell, time: Time, prevTruth: Truth, result: Truth): Unit = {
// don't need a truth, if the sensor uses another, but this should not happen // don't need a truth, if the sensor uses another, but this should not happen
@@ -136,6 +142,6 @@ case class SensorCount(count: Int) {
} }
} }
// NOTE: The Group is actually obsolete in the Tuple3 as Sensor and GroundTruth hold theirs (unless removed from their case class)
case class Configuration(cells: Map[Cell, Map[Group, List[(Group, Sensor, Option[GroundTruth])]]], sharedMemory: SharedMemory) case class Configuration(cells: Map[Cell, Map[Group, List[(Group, Sensor, Option[GroundTruth])]]], sharedMemory: SharedMemory)