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.

../_images/architecture.png

Fig. 3 Architecture of PluginPlay. The left side shows the contents of PluginPlay (including its major dependency). The right shows how PluginPlay is fed contents, i.e., by ingesting plugins containing modules.

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:

  1. 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.

  2. Cache. When a module runs, the inputs/results to/from the module are recorded in the cache.

  3. Module Utilities. A collection of module development tools spanning debugging, profiling, documenting, and much more.

  4. 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:

  1. 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

  2. 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.

  3. Dynamic Module Interfaces

    • Dynamically changes how modules in the call graph communicate

    • Falls under the call graph component