提交 8ff0484a authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Update documentation following code review.

上级 7e84537f
...@@ -813,7 +813,10 @@ class CLinker(link.Linker): ...@@ -813,7 +813,10 @@ class CLinker(link.Linker):
The signature is a tuple, some elements of which are sub-tuples. The signature is a tuple, some elements of which are sub-tuples.
The outer tuple has a brief header, followed by elements for every node in the The outer tuple has a brief header, containing the compilation options
passed to the compiler, the libraries to link against, an md5 hash
of theano.config (for all config options where "in_c_key" is True).
It is followed by elements for every node in the
topological ordering of `self.env`. topological ordering of `self.env`.
If the Op of any Apply in the Env does not have c_code_cache_ok()==True, then this If the Op of any Apply in the Env does not have c_code_cache_ok()==True, then this
......
...@@ -402,24 +402,36 @@ class ModuleCache(object): ...@@ -402,24 +402,36 @@ class ModuleCache(object):
The cache works on the basis of keys. Each key is mapped to only one The cache works on the basis of keys. Each key is mapped to only one
dynamic module, but multiple keys may be mapped to the same module (see dynamic module, but multiple keys may be mapped to the same module (see
below for details). below for details). Each module is a dynamic library file, that Python
can import.
Keys should be tuples of length 2: (version, rest)
The ``rest`` can be anything hashable and picklable, that uniquely identifies the The cache contains one directory for each module, containing:
computation in the module. - the dynamic library file itself (.so/.pyd),
- an empty __init__.py file, so Python can import it,
- a file containing the source code for the module (mod.cpp/mod.cu),
- a key.pkl file, containing a KeyData object with all the keys
associated with that module,
- possibly a delete.me file, meaning this directory has been marked
for deletion.
Keys should be tuples of length 2: (version, rest). The
``rest`` can be anything hashable and picklable, that uniquely
identifies the computation in the module. The key is returned by
``CLinker.cmodule_key_``.
The ``version`` should be a hierarchy of tuples of integers. The ``version`` should be a hierarchy of tuples of integers.
If the ``version`` is either 0 or (), then the key is unversioned, and its If the ``version`` is either 0 or (), then the key is unversioned, and its
corresponding module will be deleted in an atexit() handler if it is not corresponding module will be marked for deletion in an atexit() handler.
associated to another versioned key.
If the ``version`` is neither 0 nor (), then the module will be kept in the If the ``version`` is neither 0 nor (), then the module will be kept in the
cache between processes. cache between processes.
An unversioned module is not deleted by the process that creates it. Deleting such modules An unversioned module is not always deleted by the process that
does not work on NFS filesystems because the tmpdir in which the library resides is in use creates it. Deleting such modules may not work on NFS filesystems
until the end of the process' lifetime. Instead, unversioned modules are left in their because the tmpdir in which the library resides is in use until the
tmpdirs without corresponding .pkl files. These modules and their directories are erased end of the process' lifetime. In this case, unversioned modules
by subsequent processes' refresh() functions. are left in their tmpdirs without corresponding .pkl files. These
modules and their directories are erased by subsequent processes'
refresh() functions.
Two different keys are mapped to the same module when all conditions below Two different keys are mapped to the same module when all conditions below
are met: are met:
...@@ -427,6 +439,8 @@ class ModuleCache(object): ...@@ -427,6 +439,8 @@ class ModuleCache(object):
- They share the same compilation options in their ``rest`` part (see - They share the same compilation options in their ``rest`` part (see
``CLinker.cmodule_key_`` for how this part is built). ``CLinker.cmodule_key_`` for how this part is built).
- They share the same C code. - They share the same C code.
These three elements uniquely identify a module, and are summarized
in a single "module hash".
""" """
dirname = "" dirname = ""
...@@ -443,7 +457,7 @@ class ModuleCache(object): ...@@ -443,7 +457,7 @@ class ModuleCache(object):
"""Maps a part-of-key to all keys that share this same part.""" """Maps a part-of-key to all keys that share this same part."""
module_hash_to_key_data = {} module_hash_to_key_data = {}
"""Maps hash of a module's code to its corresponding KeyData object.""" """Maps a module hash to its corresponding KeyData object."""
stats = [] stats = []
"""A list with counters for the number of hits, loads, compiles issued by module_from_key() """A list with counters for the number of hits, loads, compiles issued by module_from_key()
...@@ -483,20 +497,19 @@ class ModuleCache(object): ...@@ -483,20 +497,19 @@ class ModuleCache(object):
""" """
def refresh(self, delete_if_problem=False): def refresh(self, delete_if_problem=False):
"""Update self.entry_from_key by walking the cache directory structure. """Update cache data by walking the cache directory structure.
Add entries that are not in the entry_from_key dictionary.
Load key.pkl files that have not been loaded yet.
Remove entries which have been removed from the filesystem. Remove entries which have been removed from the filesystem.
Also, remove malformed cache directories. Also, remove malformed cache directories.
:param delete_if_problem: If True, cache entries that do not seem :param delete_if_problem: If True, cache entries that meet one of those
correct are deleted without taking additional precautions. This two conditions are deleted:
includes:
- Those for which unpickling the KeyData file fails with an - Those for which unpickling the KeyData file fails with an
unknown exception. unknown exception.
- Duplicated modules, regardless of their age. - Duplicated modules, regardless of their age.
:returns: a list of modules of age higher than self.age_thresh_use.
""" """
start_time = time.time() start_time = time.time()
too_old_to_use = [] too_old_to_use = []
...@@ -602,7 +615,8 @@ class ModuleCache(object): ...@@ -602,7 +615,8 @@ class ModuleCache(object):
level='info') level='info')
continue continue
# Find unversioned keys. # Find unversioned keys from other processes.
# TODO: check if this can happen at all
to_del = [key for key in key_data.keys if not key[0]] to_del = [key for key in key_data.keys if not key[0]]
if to_del: if to_del:
warning("ModuleCache.refresh() Found unversioned " warning("ModuleCache.refresh() Found unversioned "
...@@ -666,6 +680,9 @@ class ModuleCache(object): ...@@ -666,6 +680,9 @@ class ModuleCache(object):
else: else:
too_old_to_use.append(entry) too_old_to_use.append(entry)
# If the compilation failed, no key.pkl is in that
# directory, but a mod.* should be there.
# We do nothing here.
# Remove entries that are not in the filesystem. # Remove entries that are not in the filesystem.
items_copy = list(self.module_hash_to_key_data.iteritems()) items_copy = list(self.module_hash_to_key_data.iteritems())
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论