Skip to content

Message Speedup #2

Description

@Robadob

I haven't implemented any of these changes, they are purely observations.

Message Classes

There are several classes of message:

Assignment

  • tb_assignment : A message declaring that a person has active TB. Only emitted by people with TB, only holds their id.

Membership

Primary: This links a personid, houseid, church id/freq/duration

  • household_membership: A message declaring that a person is a member of a household

Secondary: These all link personId, eventId (and duration)

  • church_membership: A message declaring that a person is a member of a household
  • transport_membership:A message declaring that a person uses a transport`
  • workplace_membership:A message declaring that a person is employed at a workplace
  • school_membership:A message declaring that a person studies at a school

Location

  • location: A message declaring that a person is in a given location at a given time

Infection

These messages are all:

A message containing the lambda value for a given location at a given time'

With a lambda value and location index.

  • household_infection
  • church_infection
  • transport_infection
  • clinic_infection
  • workplace_infection
  • bar_infection
  • school_infection

Improvements

Membership

I haven't looked at household membership, but presumably it's the same, just more properties.

Msg Output
Each iteration <location>_membership agent has a <abbreviated location>init() which outputs these messages.

Msg Input
Person has a membership function person<abbreviated location>init() for each location type, which iterates all messages, to decide whether that person is a member of the location. From this it stores the location's id under the corresponding agent variable e.g. person->school = school_membership_message->school_id

Solution
I can't really tell the purpose of these agents/messages. The agents are created in the init function, and they never change, similarly the message's mirror the agent's directly and our output continuously.

Unless I'm missing something, this looks alot like a hack for their initialisation:

  • They create the people
  • They create the associations
  • They create association agents to represent the associations
  • Each iteration:
    • associations output message
    • person reads messages to set their internal associations

Restructuring init, to create people, but not commit them to device until associations have been decided should allow all of these messages/agents to be removed.

Benefit

  • Removal of ~7 spurious agents/messages
  • Removal of 14 redundant device functions (7x message input and output)

Assignment

Msg Output
TBAssignment agent tbinit() fn

Msg Input
Person agent persontbinit() fn

Solution
This looks like another init hack, membership by another name.
TBAssignment are created in the init function, hold a person Id, and they only output a message with that id.
People then iterate messages, to find if they have TB and perform some maths to set some other values.

Similar fix to membership, probably some arguments in favour of moving init where possible to GPU however (e.g. one time Person agent function that slurps up all this data to properly init people).

Benefit
~

Location

Msg Output
Each iteration, person all run update() which updates their location and TB status. Those with TB output a location message.

Msg Input
For each location type, there is an agent function which counts how many location messages have the required location ID and applys it to some formula to calculate the locations infection level, which is then output as an infection message.

Each location type has it's own formula.

Solution

  • Bin all of the location messages
  • Allocate an array of int where we can atomically build a histogram of infection count at each location. (An alternative would be to output to an array/agent variable and use cub:histogram)
  • Locations can then directly access the count, rather than having to iterate loads of messages.
  • In combination with Infection message fix, move all of the existing message input functions into a single layer (Can't combine kernel launches (without major rewrite) due to different agents/infection formulae)

Benefits:

  • Saves redundant iteration to count.
  • Attempts to use some concurrency

Infection

All of these messages are simply set to identify the delta of a location, and are output by that location in the schupdate hhupdate style functions.

Msg Output
All <location> output a message saying <my infection level is> (e.g. schupdate())

Msg Input
Person iterates all infection messages, looking for the one which corresponds with their current location, and takes the 'lambda' value from it. (e.g. updatelambdasch())

Solution

  • Bin all of the infection messages.
  • Allocate an array of float, where location's instead write their lambda value (It appears location id is globally imposed, rather than per event type).
  • Rewrite message output functions to instead write to this array.
  • Merge all of the infection message input functions, where a person simply calls me->lambda = location_lambdas[me->locationId]

Benefits

  • Reduces 7(?) kernel launches to 1 (possibly 0, if logic allows that single line to go elsewhere).
  • Allows persons to directly access their message, rather than having to iterate several thousand, across multiple kernel launches.
  • Probably removes a few hundred LoC from functions.c and XMLModelFile.xml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions