forked from pytorch/pytorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lazy_dyndep.py
84 lines (65 loc) · 2.64 KB
/
lazy_dyndep.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
## @package lazy_dyndep
# Module caffe2.python.lazy_dyndep
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import os
from caffe2.python import dyndep, lazy
def RegisterOpsLibrary(name):
"""Registers a dynamic library that contains custom operators into Caffe2.
Since Caffe2 uses static variable registration, you can optionally load a
separate .so file that contains custom operators and registers that into
the caffe2 core binary. In C++, this is usually done by either declaring
dependency during compilation time, or via dynload. This allows us to do
registration similarly on the Python side.
Unlike dyndep.InitOpsLibrary, this does not actually parse the c++ file
and refresh operators until caffe2 is called in a fashion which requires
operators. In some large codebases this saves a large amount of time
during import.
It is safe to use within a program that also uses dyndep.InitOpsLibrary
Args:
name: a name that ends in .so, such as "my_custom_op.so". Otherwise,
the command will simply be ignored.
Returns:
None
"""
if not os.path.exists(name):
# Note(jiayq): if the name does not exist, instead of immediately
# failing we will simply print a warning, deferring failure to the
# time when an actual call is made.
print('Ignoring {} as it is not a valid file.'.format(name))
return
global _LAZY_IMPORTED_DYNDEPS
_LAZY_IMPORTED_DYNDEPS.add(name)
_LAZY_IMPORTED_DYNDEPS = set()
_error_handler = None
def SetErrorHandler(handler):
"""Registers an error handler for errors from registering operators
Since the lazy registration may happen at a much later time, having a dedicated
error handler allows for custom error handling logic. It is highly
recomended to set this to prevent errors from bubbling up in weird parts of the
code.
Args:
handler: a function that takes an exception as a single handler.
Returns:
None
"""
global _error_handler
_error_handler = handler
def GetImportedOpsLibraries():
_import_lazy()
return dyndep.GetImportedOpsLibraries()
def _import_lazy():
global _LAZY_IMPORTED_DYNDEPS
if not _LAZY_IMPORTED_DYNDEPS:
return
for name in list(_LAZY_IMPORTED_DYNDEPS):
try:
dyndep.InitOpLibrary(name, trigger_lazy=False)
except BaseException as e:
if _error_handler:
_error_handler(e)
finally:
_LAZY_IMPORTED_DYNDEPS.remove(name)
lazy.RegisterLazyImport(_import_lazy)