@@ -57,21 +57,40 @@ def run(self, graph, config, updatehash=False):
57
57
58
58
59
59
class DistributedPluginBase (PluginBase ):
60
- """Execute workflow with a distribution engine
60
+ """
61
+ Execute workflow with a distribution engine
62
+
63
+ Relevant class attributes
64
+ -------------------------
65
+
66
+ procs: list (N) of underlying interface elements to be processed
67
+ proc_done: a boolean numpy array (N,) signifying whether a process has been
68
+ submitted for execution
69
+ proc_pending: a boolean numpy array (N,) signifying whether a
70
+ process is currently running.
71
+ depidx: a boolean matrix (NxN) storing the dependency structure accross
72
+ processes. Process dependencies are derived from each column.
73
+
74
+ Combinations of ``proc_done`` and ``proc_pending``
75
+ --------------------------------------------------
76
+
77
+ +------------+---------------+--------------------------------+
78
+ | proc_done | proc_pending | outcome |
79
+ +============+===============+================================+
80
+ | True | False | Process is finished |
81
+ +------------+---------------+--------------------------------+
82
+ | True | True | Process is currently being run |
83
+ +------------+---------------+--------------------------------+
84
+ | False | False | Process is queued |
85
+ +------------+---------------+--------------------------------+
86
+ | False | True | INVALID COMBINATION |
87
+ +------------+---------------+--------------------------------+
61
88
"""
62
89
63
90
def __init__ (self , plugin_args = None ):
64
- """Initialize runtime attributes to none
65
-
66
- procs: list (N) of underlying interface elements to be processed
67
- proc_done: a boolean numpy array (N,) signifying whether a process has been
68
- executed
69
- proc_pending: a boolean numpy array (N,) signifying whether a
70
- process is currently running. Note: A process is finished only when
71
- both proc_done==True and
72
- proc_pending==False
73
- depidx: a boolean matrix (NxN) storing the dependency structure accross
74
- processes. Process dependencies are derived from each column.
91
+ """
92
+ Initialize runtime attributes to none
93
+
75
94
"""
76
95
super (DistributedPluginBase , self ).__init__ (plugin_args = plugin_args )
77
96
self .procs = None
@@ -87,12 +106,16 @@ def __init__(self, plugin_args=None):
87
106
def _prerun_check (self , graph ):
88
107
"""Stub method to validate/massage graph and nodes before running"""
89
108
109
+ def _postrun_check (self ):
110
+ """Stub method to close any open resources"""
111
+
90
112
def run (self , graph , config , updatehash = False ):
91
113
"""
92
114
Executes a pre-defined pipeline using distributed approaches
93
115
"""
94
116
logger .info ("Running in parallel." )
95
117
self ._config = config
118
+ poll_sleep_secs = float (config ['execution' ]['poll_sleep_duration' ])
96
119
97
120
self ._prerun_check (graph )
98
121
# Generate appropriate structures for worker-manager model
@@ -107,12 +130,14 @@ def run(self, graph, config, updatehash=False):
107
130
# See https://github.com/nipy/nipype/pull/2200#discussion_r141605722
108
131
jobs_ready = np .nonzero (~ self .proc_done & (self .depidx .sum (0 ) == 0 ))[1 ]
109
132
110
- logger .info ('Progress: %d jobs, %d/%d/%d/%d (done/running/pending/ready).' ,
133
+ logger .info ('Progress: %d jobs, %d/%d/%d (done/running/ready),'
134
+ ' %d/%d (pending_tasks/waiting).' ,
111
135
len (self .proc_done ),
112
- np .sum (self .proc_done & ~ self .proc_pending ),
136
+ np .sum (self .proc_done ^ self .proc_pending ),
113
137
np .sum (self .proc_done & self .proc_pending ),
138
+ len (jobs_ready ),
114
139
len (self .pending_tasks ),
115
- len ( jobs_ready ))
140
+ np . sum ( ~ self . proc_done & ~ self . proc_pending ))
116
141
toappend = []
117
142
# trigger callbacks for any pending results
118
143
while self .pending_tasks :
@@ -139,27 +164,21 @@ def run(self, graph, config, updatehash=False):
139
164
if toappend :
140
165
self .pending_tasks .extend (toappend )
141
166
num_jobs = len (self .pending_tasks )
142
- logger .debug ('Tasks currently running (%d).' , num_jobs )
167
+ logger .debug ('Tasks currently running: %d. Pending: %d.' , num_jobs ,
168
+ np .sum (self .proc_done & self .proc_pending ))
143
169
if num_jobs < self .max_jobs :
144
170
self ._send_procs_to_workers (updatehash = updatehash ,
145
171
graph = graph )
146
172
else :
147
173
logger .debug ('Not submitting (max jobs reached)' )
148
- self ._wait ()
174
+
175
+ sleep (poll_sleep_secs )
149
176
150
177
self ._remove_node_dirs ()
151
178
report_nodes_not_run (notrun )
152
179
153
180
# close any open resources
154
- self ._close ()
155
-
156
- def _wait (self ):
157
- sleep (float (self ._config ['execution' ]['poll_sleep_duration' ]))
158
-
159
- def _close (self ):
160
- # close any open resources, this could raise NotImplementedError
161
- # but I didn't want to break other plugins
162
- return True
181
+ self ._postrun_check ()
163
182
164
183
def _get_result (self , taskid ):
165
184
raise NotImplementedError
0 commit comments