Architecture of PluginPlay
This page describes the overarching architecture of PluginPlay and focuses on how this architecture addresses the considerations raised in the PluginPlay Statement of Need section.
Fig. 3 shows the conceptual architecture of PluginPlay. PluginPlay itself is built on top of the runtime system implemented by ParallelZone. Internally PluginPlay is made up of four components:
Module Manager. Which is the user-facing API for the PluginPlay framework. Loading modules, manipulating the call graph, and inspecting module state all goes through the module manager.
Cache. When a module runs, the inputs/results to/from the module are recorded in the cache.
Module Utilities. A collection of module development tools spanning debugging, profiling, documenting, and much more.
Call Graph. This component contains a runtime representation of the program’s control flow.
Fig. 3 also tries to make the point that PluginPlay is just a framework, i.e., a piece of software designed to facilitate writing other software by serving as a “template” for the program. PluginPlay does not contain any scientific functionality; scientific functionality must be supplied by plugins (and the modules in them). If it helps, you can think of PluginPlay as a meta-package meant to facilitate working with other packages.
The following subsections summarize the PluginPlay components in more detail.
ParallelZone
ParallelZone is a runtime system, i.e., a library meant to provide a software abstraction between the hardware/operating system and a program. In particular, ParallelZone provides abstractions for:
Determining what hardware, including the amount of each component, the software is currently running on.
Message-based distributed parallelism.
Logging.
Task-based scheduling.
PluginPlay uses ParallelZone to make informed cache decisions (vide infra), schedule modules, record progress, and much more.
The NWChemEx organization develops ParallelZone as a separate project, in the hope that it will prove useful for other libraries/frameworks besides PluginPlay. More details pertaining to the design of ParallelZone can be found here.
Module Manager
Implemented by the ModuleManager
class, the module manager component is
responsible for most runtime interactions between the user and ParallelZone.
These interactions include:
Loading modules into PluginPlay
Querying the available modules
Changing how the call graph is wired
Saving/loading call graph execution progress
Indirectly, via the module manager setting module state
The design of the module manager component is discussed in more detail in the Designing the Module Manager section.
Cache
Note
Although we are somewhat “putting the cart before the horse” by introducing the cache component here, the cache is an important design point of PluginPlay and has serious performance considerations. Hence we feel it is worth considering the cache in the top-level architecture.
While perhaps not clear at this point, one downside to encapsulation is that it makes it difficult to discern exactly what intermediates a Module may have computed since Module objects are largely opaque. If recomputing the intermediates is expensive, then it is essential that the recomputation be avoided. PluginPlay’s solution is to rely on Memoization.
In short, PluginPlay saves the inputs/results provided to/by the Module in the cache. Then if the same inputs are again provided to the same module, PluginPlay automatically returns the cached results. In practice, Memoization can also be used as a save/load (or sometimes called checkpoint/restart) mechanism, i.e., start with a cache from a previous run, rerun the program, and allow control to reach parity with the previous run (which because of Memoization should happen quickly).
More design details pertaining to Memoization can be found in the Memoization Design section and more details about the design of the cache can be found in the Cache Design section.
Call Graph
Most user interactions with PluginPlay pertain to modifying the state of the call graph. This includes:
changing what modules can be in the call graph,
modifying how the modules are wired together, and
setting the values of Bound Input.
Users actually do the above through a ModuleManager
object, but under the
hood the ModuleManager
is interacting with the call graph component of
PluginPlay. More detailed design documentation can be found in
Designing the Call Graph Component.
Summary
This design specifically addresses the considerations raised in the PluginPlay Statement of Need section by:
Performance
PluginPlay is built on ParallelZone, which is a performance-centric runtime system.
Cache feature enables memoization to avoid redundant module runs
Module utilities help with performance tuning
Dynamically swapping out modules can enable using hardware-specific versions
Plugins make it easy to add hardware-specific modules after the fact
Modular/Component-Based Architecture
Program’s call graph assembled by wiring modules together.
Plugins allow distributing related modules together.
Module manager allows interacting with the modules.
Dynamic Module Interfaces
Dynamically changes how modules in the call graph communicate
Falls under the call graph component