[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:
@@ -1,13 +1,15 @@
|
||||
package scim.components
|
||||
|
||||
import scim.datastruct.SharedMemory
|
||||
import scim.datastruct.{Cell, Group, SensorResult, SharedMemory}
|
||||
|
||||
class Output(sharedMemory: SharedMemory) extends Runnable {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ class Simulation(config: Configuration) {
|
||||
private val sharedMemory = config.sharedMemory
|
||||
private val sharedConfig = sharedMemory.config
|
||||
private val cells = config.cells
|
||||
val output = sharedMemory.output
|
||||
|
||||
|
||||
def start(): Unit = {
|
||||
@@ -38,6 +39,8 @@ class Simulation(config: Configuration) {
|
||||
} else {
|
||||
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 = {
|
||||
@@ -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
|
||||
// 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.
|
||||
// this would require sharedConfig.cellThreadPool * 2 additional threads
|
||||
// :
|
||||
// only run ground truth in list, have sensors in their respective groups
|
||||
// requires groups to be split into two elements: sensor and ground truth
|
||||
// Tuple2(Map[Group, list[(Group, Option[GroundTruth])]], Map[Group, Sensor])
|
||||
def simGroup(group: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = {
|
||||
group._2.foreach(element => simulate(time, cell, prevTruths(group._1), resultTruths(group._1), resultSensors(group._1), element))
|
||||
// another option would be to calculate all ground truths within a list first and than parellize the sensor list
|
||||
def simGroup(input: (Group, List[(Group, Sensor, Option[GroundTruth])])): Unit = {
|
||||
val group = input._1
|
||||
val truthGroup = group.getParentOrGroup // make sure the correct ground truth gets passed
|
||||
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 ) {
|
||||
val groupList = groups.par
|
||||
|
||||
@@ -15,9 +15,13 @@ case class Time(time: Int, duration: Int){
|
||||
def get: Int = { time }
|
||||
}
|
||||
|
||||
// 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]]],
|
||||
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
|
||||
// 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
|
||||
@@ -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]) {
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user