Compiler
Build complex compilation pipelines
Compiler
Sometimes AGGREGATES may require complex initialization and be built from multiple sources, like database queries, API calls, or other external resources are required to build it. Each one with it's own lifecycle that may require some initialization method or cleanup after they are no longer needed.
In the context of neural networks, AGGREGATES not only should be built but also compiled. Compilation is the process of converting a high-level neural network model into a low-level representation that can be executed on a specific hardware platform, and can be seen as an integral part of the process of building the AGGREGATE. This process get even more complex when performing distributed training.
A Compiler
is a class that compiles a pipeline of functions to be executed in sequence in order
to build an a low-level representation of the AGGREGATE. Since some compilation steps sometimes
requires runtime information, the Compiler
provides a mechanism to inject dependencies into
the pipeline.
Attributes:
Name | Type | Description |
---|---|---|
steps |
list[Callable[..., Any]]
|
A list of functions to be executed in sequence. |
Methods:
Name | Description |
---|---|
compile |
Execute the pipeline of functions in sequence. The output of each function is passed as input to the next function. The compiled AGGREGATE should be returned as a result of the execution of the pipeline. |
step |
A decorator that adds a function to the pipeline. The function should take as input the output of the previous function in the pipeline and return the input of the next function in the pipeline. |
Example
from logging import getLogger
from torch import cuda
from torch.nn import Module
from torchsystem.compiler import Compiler
from torchsystem.compiler import Depends
from torchsystem.compiler import compile
compiler = Compiler()
logger = getLogger(__name__)
def device():
return 'cuda' if cuda.is_available() else 'cpu'
def epoch():
raise NotImplementedError('Override this function with a concrete implementation')
@compiler.step
def build_classifier(model: Module, criterion: Module, optimizer: Module):
logger.info(f'Building classifier')
logger.info(f'- model: {model.__class__.__name__}')
logger.info(f'- criterion: {criterion.__class__.__name__}')
logger.info(f'- optimizer: {optimizer.__class__.__name__}')
return Classifier(model, criterion, optimizer)
@compiler.step
def move_to_device(classifier: Classifier, device = Depends(device)):
logger.info(f'Moving classifier to device: {device}')
return classifier.to(device)
@compiler.step
def compile_classifier(classifier: Classifier):
logger.info(f'Compiling classifier')
return compile(classifier)
@compiler.step
def set_epoch(classifier: Classifier, epoch: int = Depends(epoch)):
logger.info(f'Setting classifier epoch: {epoch}')
classifier.epoch = epoch
return classifier
...
compiler.dependency_overrides[epoch] = lambda: 10
classifier = compiler.compie(model, criterion, optimizer)
assert classifier.epoch == 10
dependency_overrides
property
Get the dependency overrides. Dependency overrides are used to inject dependencies into the pipeline. This is useful for late binding, testing and changing the behavior of the compiler in runtime.
Returns:
Name | Type | Description |
---|---|---|
dict |
dict
|
The dependency map. |
Example
def device():...
...
compiler.dependency_overrides[device] = lambda: 'cuda' if cuda.is_available() else 'cpu'
__init__(*, provider=None)
Initialize the Compiler.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
provider
|
Provider
|
The dependency provider. Defaults to None. |
None
|
compile(*args, **kwargs)
Execute the pipeline of functions in sequence. The output of each function is passed as input to the next function. The compiled AGGREGATE should be returned by the last function in the pipeline.
Returns:
Name | Type | Description |
---|---|---|
T |
T
|
The compiled AGGREGATE. |
step(callable)
Add a function to the pipeline. The function should take as input the output of the previous function in the pipeline and return the input of the next function in the pipeline.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
callable
|
Callable
|
The function to be added to the pipeline. |
required |
Returns:
Name | Type | Description |
---|---|---|
Any |
Any
|
The requirements for the next step in the pipeline. |