Patch 1.1.1 #90
Julian-Patzner
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
This patch improves simulation performance with lock-free parallel staging for intervention triggers and fixes to type instability in
present_individuals!and setting activation.Parallel Trigger Dispatch
Symptom and hospitalization triggers fired during the parallel individual-update loop now use a lock-free staging path rather than acquiring the event-queue lock on every event.
EventQueuegains astagingfield — oneVector{Tuple{Event, Int16}}per thread, pre-allocated toThreads.maxthreadid()entries. Events staged into these buffers during a parallel loop are invisible to the queue untilflush_staging!merges them.stage!: Lock-free variant ofenqueue!. Appends the event and its target tick to the calling thread's staging buffer inO(1). Safe to call concurrently fromThreads.@threadsloops without any synchronization.flush_staging!: Merges all staging buffers into the tick buckets in thread-index order and clears them. Must be called single-threaded; takes no lock. Called automatically bystep!after the parallel individual-update loop completes.stagedkeyword ontriggerandtrigger_strategy: Passstaged = trueto route events throughstage!instead ofenqueue!. Set automatically when triggers are fired fromupdate_individual!, which runs insideThreads.@threads :static.empty!updated: Clears staging buffers in addition to tick buckets, so staged-but-unflushed events are also discarded.Type-Stable Setting Traversal
Type instability in
present_individuals!:ContainerSettingstructs previously stored their child setting type in acontains_type::DataTypefield. Lookups via this field returned an abstractly-typedVector, preventing the compiler from specializing the iteration over contained settings inpresent_individuals!(and other hierarchy-traversal functions such asget_contained!,individuals!,open!,close!,size, andgeolocation).contains_typeandcontained_typeare now type-dispatch functions (contains_type(::Type{SchoolYear}) = SchoolClass, etc.), encoding the parent–child relationship as a compile-time constant. TheDataType-typed fields have been removed from allContainerSettingstructs; usecontains_type(setting)/contained_type(setting)in their place.Type instability in setting activation: When an individual was infected, their memberships were activated by iterating
settings_tuple(i)— a tuple of(DataType, id)pairs — and callingsettings(sim, type)[id]with a runtimeDataType. This made everyactivate!call dynamically dispatched.setting_idandsetting_id!are now per-type@inlinedispatch methods rather than a runtime if-else chain, and a newactivate_memberships!helper unrolls the activation loop overmembership_setting_types(Individual)at compile time, making every field access andactivate!call concretely typed. The same fix is applied in all four start-condition initializers (InfectedFraction,PatientZero,PatientZeros,RegionalSeeds) and inprocess_infections!.Other Changes & API Cleanup
settings(sim, type::DataType)removed: The runtime-DataTypeoverload ofsettingshas been removed. Use the typed overloadsettings(sim, Household)for literal types, orget(settingscontainer(sim), type)where a runtimeDataTypevariable is genuinely needed.stage!/flush_staging!staging pipeline (staged events not visible until flushed, double-flush idempotence,empty!clearing unflushed staged events), thesetting_id/setting_id!type-dispatch rewrites, and two previously untestedSettingsContaineredge cases — unmapped container IDs innew_setting_ids!and out-of-bounds contained IDs indelete_dangling_ids!._insert!internal helper: The shared insertion logic betweenenqueue!andflush_staging!has been extracted into a non-exported_insert!function. No behavioral change.Public API Surface Tightened
The export list has been audited and substantially trimmed. A large number of names that were internal helpers (utilities, post-processing intermediates, state-mutating setters on
Individual, and similar implementation details) are no longer exported, and many have been renamed with a leading underscore to mark them as private.This is a tightening of the public surface, not a removal of functionality. Every affected name remains accessible by qualifying it with the module, e.g.
GEMS.functionname. Code that was calling these directly will keep working with that one change; the audit simply makes explicit which names are the supported, stable API and which are internal and may change without a version bump.This discussion was created from the release Patch 1.1.1.
All reactions