Diamond inheritance demonstration¶
This notebook demonstrates creating a hybrid acceleration engine from two engines. This is a necessary step in order to compose the functionality of multiple acceleration engines, because coheriq allows at most a single engine to be active per domain.
This example is contrived in the sense that the intended behavior of the function changes when acceleration is enabled. This is used to demonstrate the general workings of code replacement, even though the general goal of coheriq is not to change the end-user results, but rather to accelerate a calculation with the goal of obtaining the same results.
Domain (addon) code¶
In the case of this example, there are two functions that are marked as candidates for acceleration, along with their default implementations.
In production, a domain’s name should be the __name__ of the module it belongs to, so that users can activate an engine by passing that module: coheriq.enable_engine(mylib, "hybrid"). This notebook defines the domain, both engines, and the user code in a single file, which no module name can describe — so it names the domain "mylib-foo" and refers to it by that string throughout. Coheriq warns about the name for this reason; the warning is expected here and is the signal that this
arrangement is a demo rather than a template.
[ ]:
from coheriq import AccelerationDomain
_domain = AccelerationDomain("mylib-foo")
_acceleration_candidate = _domain.acceleration_candidate
@_acceleration_candidate
def approximate_pi():
return 3.14
@_acceleration_candidate
def approximate_e():
return 2.72
_domain.materialize()
Acceleration engine 1 code¶
[2]:
from coheriq import AccelerationEngine
_engine = AccelerationEngine("mylib-foo", "bar")
_override = _engine.override
@_override(name="approximate_pi")
def approximate_pi_hpc():
from math import pi
return pi
_engine.materialize()
Acceleration engine 2 code¶
[3]:
_engine = AccelerationEngine("mylib-foo", "baz")
_override = _engine.override
@_override(name="approximate_e")
def approximate_e_hpc():
from math import e
return e
_engine.materialize()
Define a hybrid engine¶
Because only a single engine can be activated …
[4]:
_engine3 = AccelerationEngine(
"mylib-foo", # Domain
"hybrid", # Name of engine being declared
["bar", "baz"], # Base engines (in MRO order)
)
_engine3.materialize()
End-user code¶
[ ]:
import coheriq
coheriq.enable_engine("mylib-foo", "hybrid")
[6]:
approximate_pi()
[6]:
3.141592653589793
[7]:
approximate_e()
[7]:
2.718281828459045