提交 9b3e9d8d authored 作者: Brandon T. Willard's avatar Brandon T. Willard 提交者: Brandon T. Willard

Add cache option to CLinker methods and clean up type hints

上级 1380aedb
...@@ -7,7 +7,7 @@ import sys ...@@ -7,7 +7,7 @@ import sys
from collections import defaultdict from collections import defaultdict
from copy import copy from copy import copy
from io import StringIO from io import StringIO
from typing import Dict from typing import TYPE_CHECKING, Any, Dict, Optional
import numpy as np import numpy as np
...@@ -21,6 +21,7 @@ from aesara.graph.basic import ( ...@@ -21,6 +21,7 @@ from aesara.graph.basic import (
vars_between, vars_between,
) )
from aesara.link.basic import Container, Linker, LocalLinker, PerformLinker from aesara.link.basic import Container, Linker, LocalLinker, PerformLinker
from aesara.link.c import cutils
from aesara.link.c.cmodule import ( from aesara.link.c.cmodule import (
METH_VARARGS, METH_VARARGS,
DynamicModule, DynamicModule,
...@@ -34,13 +35,14 @@ from aesara.link.utils import gc_helper, map_storage, raise_with_op, streamline ...@@ -34,13 +35,14 @@ from aesara.link.utils import gc_helper, map_storage, raise_with_op, streamline
from aesara.utils import difference, uniq from aesara.utils import difference, uniq
_logger = logging.getLogger("aesara.link.c.basic") if TYPE_CHECKING:
from aesara.graph.fg import FunctionGraph
from aesara.link.c.cmodule import ModuleCache
run_cthunk = None # Will be imported only when needed. _logger = logging.getLogger("aesara.link.c.basic")
def get_module_cache(init_args=None): def get_module_cache(init_args: Optional[Dict[str, Any]] = None) -> "ModuleCache":
""" """
Parameters Parameters
...@@ -580,7 +582,9 @@ class CLinker(Linker): ...@@ -580,7 +582,9 @@ class CLinker(Linker):
self.fgraph = None self.fgraph = None
super().__init__(scheduler=schedule) super().__init__(scheduler=schedule)
def accept(self, fgraph, no_recycling=None, profile=None): def accept(
self, fgraph: "FunctionGraph", no_recycling=None, profile=None
) -> "CLinker":
r"""Associate this `Linker` with `fgraph`. r"""Associate this `Linker` with `fgraph`.
The `no_recycling` argument can contain a list of `Variable`\s that The `no_recycling` argument can contain a list of `Variable`\s that
...@@ -1080,18 +1084,18 @@ class CLinker(Linker): ...@@ -1080,18 +1084,18 @@ class CLinker(Linker):
input_storage=None, input_storage=None,
output_storage=None, output_storage=None,
storage_map=None, storage_map=None,
cache: Optional["ModuleCache"] = None,
): ):
""" """Compile `self.fgraph`.
Compiles this linker's fgraph.
Parameters Parameters
---------- ----------
input_storage: list or None input_storage: list or None
List of lists of length 1. In order to use the thunk returned List of lists of length 1. In order to use the thunk returned
by __compile__, the inputs must be put in that storage. by this method, the inputs must be put in that storage.
If None, storage will be allocated. If None, storage will be allocated.
output_storage: list of lists of length 1 output_storage: list of lists of length 1
The thunk returned by __compile__ will put the variables of the The thunk returned by this method will put the variables of the
computation in these lists. If None, storage will be allocated. computation in these lists. If None, storage will be allocated.
Returns Returns
...@@ -1121,6 +1125,7 @@ class CLinker(Linker): ...@@ -1121,6 +1125,7 @@ class CLinker(Linker):
input_storage, input_storage,
output_storage, output_storage,
storage_map, storage_map,
cache,
) )
return ( return (
thunk, thunk,
...@@ -1152,37 +1157,51 @@ class CLinker(Linker): ...@@ -1152,37 +1157,51 @@ class CLinker(Linker):
id += 2 id += 2
return init_tasks, tasks return init_tasks, tasks
def make_thunk(self, input_storage=None, output_storage=None, storage_map=None): def make_thunk(
""" self,
Compiles this linker's fgraph and returns a function to perform the input_storage=None,
computations, as well as lists of storage cells for both the inputs output_storage=None,
and outputs. storage_map=None,
cache: Optional["ModuleCache"] = None,
**kwargs,
):
"""Compile this linker's `self.fgraph` and return a function that performs the computations.
The return values can be used as follows:
.. code-block::
f, istor, ostor = clinker.make_thunk()
istor[0].data = first_input
istor[1].data = second_input
f()
first_output = ostor[0].data
Parameters Parameters
---------- ----------
input_storage: list or None input_storage: list or None
List of lists of length 1. In order to use List of lists of length 1. In order to use
the thunk returned by __compile__, the inputs must be put in the thunk returned by `CLinker.__compile__`, the inputs must be put in
that storage. If None, storage will be allocated. that storage. If None, storage will be allocated.
output_storage: list of lists of length 1. output_storage: list of lists of length 1.
The thunk returned by __compile__ will put the variables The thunk returned by `CLinker.__compile__` will put the variables
of the computation in these lists. If None, storage will of the computation in these lists. If None, storage will
be allocated. be allocated.
storage_map: dict that map variables to storages. storage_map: dict that map variables to storages.
This is used when you need to customize the storage of This is used when you need to customize the storage of
this thunk this thunk
Returns: thunk, input_storage, output_storage cache
A cache in which to store the compilation results.
Returns
-------
thunk, input_storage, output_storage
The return values can be used as follows:
f, istor, ostor = clinker.make_thunk()
istor[0].data = first_input
istor[1].data = second_input
f()
first_output = ostor[0].data
""" """
init_tasks, tasks = self.get_init_tasks() init_tasks, tasks = self.get_init_tasks()
cthunk, module, in_storage, out_storage, error_storage = self.__compile__( cthunk, module, in_storage, out_storage, error_storage = self.__compile__(
input_storage, output_storage, storage_map input_storage, output_storage, storage_map, cache
) )
res = _CThunk(cthunk, init_tasks, tasks, error_storage, module) res = _CThunk(cthunk, init_tasks, tasks, error_storage, module)
...@@ -1584,7 +1603,14 @@ class CLinker(Linker): ...@@ -1584,7 +1603,14 @@ class CLinker(Linker):
self._mod = mod self._mod = mod
return self._mod return self._mod
def cthunk_factory(self, error_storage, in_storage, out_storage, storage_map=None): def cthunk_factory(
self,
error_storage,
in_storage,
out_storage,
storage_map=None,
cache: Optional["ModuleCache"] = None,
):
""" """
Returns a thunk that points to an instance of a C struct that Returns a thunk that points to an instance of a C struct that
can carry on the computation of this linker's fgraph can carry on the computation of this linker's fgraph
...@@ -1605,6 +1631,7 @@ class CLinker(Linker): ...@@ -1605,6 +1631,7 @@ class CLinker(Linker):
key = self.cmodule_key() key = self.cmodule_key()
except KeyError: except KeyError:
key = None key = None
if key is None: if key is None:
# If we can't get a key, then forget the cache mechanism. # If we can't get a key, then forget the cache mechanism.
module = self.compile_cmodule() module = self.compile_cmodule()
...@@ -1612,7 +1639,9 @@ class CLinker(Linker): ...@@ -1612,7 +1639,9 @@ class CLinker(Linker):
# Set compute_map as None as clinker do not support lazy evaluation # Set compute_map as None as clinker do not support lazy evaluation
for node in self.node_order: for node in self.node_order:
node.op.prepare_node(node, storage_map, None, "c") node.op.prepare_node(node, storage_map, None, "c")
module = get_module_cache().module_from_key(key=key, lnk=self) if cache is None:
cache = get_module_cache()
module = cache.module_from_key(key=key, lnk=self)
vars = self.inputs + self.outputs + self.orphans vars = self.inputs + self.outputs + self.orphans
# List of indices that should be ignored when passing the arguments # List of indices that should be ignored when passing the arguments
...@@ -1703,15 +1732,12 @@ class _CThunk: ...@@ -1703,15 +1732,12 @@ class _CThunk:
""" """
def __init__(self, cthunk, init_tasks, tasks, error_storage, module): def __init__(self, cthunk, init_tasks, tasks, error_storage, module):
global run_cthunk
if run_cthunk is None:
# Lazy import to avoid compilation when importing aesara.
from aesara.link.c.cutils import run_cthunk # noqa
self.cthunk = cthunk self.cthunk = cthunk
self.init_tasks = init_tasks self.init_tasks = init_tasks
self.tasks = tasks self.tasks = tasks
self.error_storage = error_storage self.error_storage = error_storage
self.module = module self.module = module
self.nodes = None
def find_task(self, failure_code): def find_task(self, failure_code):
""" """
...@@ -1727,7 +1753,7 @@ class _CThunk: ...@@ -1727,7 +1753,7 @@ class _CThunk:
return self.tasks[failure_code - n] return self.tasks[failure_code - n]
def __call__(self): def __call__(self):
failure = run_cthunk(self.cthunk) failure = cutils.run_cthunk(self.cthunk)
if failure: if failure:
task, taskname, id = self.find_task(failure) task, taskname, id = self.find_task(failure)
try: try:
......
...@@ -1612,18 +1612,18 @@ def _rmtree( ...@@ -1612,18 +1612,18 @@ def _rmtree(
) )
_module_cache = None _module_cache: Optional[ModuleCache] = None
def get_module_cache(dirname, init_args=None): def get_module_cache(dirname: str, init_args=None) -> ModuleCache:
""" """Create a new module_cache.
Create a new module_cache with the (k, v) pairs in this dictionary
Parameters Parameters
---------- ----------
dirname
The name of the directory used by the cache.
init_args init_args
If not None, the (k, v) pairs in this dictionary will be forwarded to Keyword arguments passed to the `ModuleCache` constructor.
the ModuleCache constructor as keyword arguments.
""" """
global _module_cache global _module_cache
...@@ -1639,8 +1639,8 @@ def get_module_cache(dirname, init_args=None): ...@@ -1639,8 +1639,8 @@ def get_module_cache(dirname, init_args=None):
) )
if _module_cache.dirname != dirname: if _module_cache.dirname != dirname:
_logger.warning( _logger.warning(
"Returning module cache instance with different " "Returning a module cache instance with a different "
f"dirname ({_module_cache.dirname}) than you requested ({dirname})" f"dirname ({_module_cache.dirname}) than requested ({dirname})"
) )
return _module_cache return _module_cache
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论