Compilation¤
Circuit Compilation Algorithm (TorchCompiler._compile_circuit)¤
Data structures:
compiled_layers_map: dictionary storing mapping between symbolic layers and compiled layers.in_layers: dictionary storing the links between layers (adjacency list). That is, for each layer, store a list of input nodes.
Algorithm :
- For every layer in topological order:
- Call the
compile_layermethod. - Store the mapping between the compiled and symbolic layers in
compiled_layers_map. - Store the mapping between the new compiled layer and its compiled inputs
in the
in_layersdictionary. Due to the topological order, the inputs are guaranteed to be already stored incompiled_layers_map - Once all the layers are compiled, create the sequence
outputswhich stores the compiled output layers. To do so, you just retrieve the compiled layers corresponding to the symbolic circuit's output layers. - Create the fully compiled circuit, a
TorchCircuitobject, using the mappings and sequence previously built. - Run the circuit post processing function
TorchCompiler._post_process_circuit(optimization and folding). - Initialize all the parameters of the circuit (
TorchCircuit.reset_parameters). It's a function that recursively calls the compiled initializer of all the circuit's parameters. - Register the compiled circuit in the
CompiledCircuitsMap.
Layer Compilation Process (TorchCompiler.compile_layer)¤
The function, in itself, only retrieves the layer rule corresponding to the
input type from the CompilerLayerRegistry and applies it.
Here is a flowchart describing the process of compiling a single layer:
flowchart TD
A["Symbolic Layer"] -- Layer Type --> LReg("LayerRegistry")
LReg -- Call Layer Rule --> hasP{"Has Parameters"}
hasP -- No --> CL["Compiled Layer"]
hasP -- Yes --> PComp("Compile TorchParameter Graph")
subgraph Compile Parameter
PComp --> nextPara("Next parameter node")
nextPara -- Parameter Type --> PReg("ParameterRegistry")
PReg -- Call Parameter Rule --> hasI{"Has Initializer"}
hasI -- No --> CL
hasI -- Yes --> IComp("Compile Initializer")
IComp -- Initializer Type --> IReg("InitializerRegistry")
IReg -- Call Initializer Rule --> ILParam{"Is last Parameter Node ?"}
ILParam -- Yes --> CL
ILParam -- No --> nextPara
end
As we can see, the compilation rule of a layer might call the compilation rule
of a parameter which might itself call the compilation rule of an initializer.
Furthermore, as TorchParameter objects are graphs themselves, we need to iterate
through all parameter nodes to compile them.
Compile a Parameter Graph (TorchCompiler.compile_parameter)¤
Data structures:
compiled_nodes_map: dictionary storing mapping between symbolic parameter nodes and compiled parameter nodes.in_nodes: dictionary storing the links between nodes. That is, for each nodes, store a list of input nodes.nodes: list of compiled nodes.
Algorithm:
- For every parameter node in topological order:
- Call the
_compile_parameter_nodemethod. - Store the mapping between the compiled and symbolic node in
compiled_nodes_map. - Store the mapping between the new compiled node and its compiled inputs
in
in_nodes. Due to the topological order, the inputs are guaranteed to be already stored incompiled_nodes_map - Store the compiled node in
nodes. - Once all the nodes are compiled, create the sequence
outputswhich stores the compiled output nodes. To do so, you simply retrieve the compiled nodes corresponding to the parameter graph output nodes. - Create the fully compiled graph, a
TorchParameterobject, using the mappings and sequence previously built.