2424 'Task01_void' : 'Empty' ,
2525 'Task02_error' : 'Errored' ,
2626 'Task10' : 'Complete' ,
27- 'Task11' : 'Held'
27+ 'Task11' : 'Held' ,
28+ 'TaskIncomplete' : 'Incomplete' ,
29+ 'TaskGpuLock' : 'Waiting'
2830}
2931
3032desired_datasets = ['spikes.times.npy' , 'spikes.amps.npy' , 'spikes.clusters.npy' ]
3739 'Task01_void' : 2 ,
3840 'Task02_error' : 2 ,
3941 'Task10' : 1 ,
40- 'Task11' : None
42+ 'Task11' : None ,
43+ 'TaskIncomplete' : 1 ,
44+ 'TaskGpuLock' : 2
4145}
4246
4347
@@ -89,6 +93,27 @@ def _run(self, overwrite=False):
8993 return out_files
9094
9195
96+ # Job that encounters a GPU lock and is set to Waiting
97+ class TaskGpuLock (ibllib .pipes .tasks .Task ):
98+ gpu = 1
99+
100+ # Overwrite setUp to create a lock file before running the task and remove it after
101+ def setUp (self ):
102+ self .make_lock_file ()
103+ self .data_handler = self .get_data_handler ()
104+ return True
105+
106+ def _run (self , overwrite = False ):
107+ pass
108+
109+
110+ # Job that encounters a GPU lock and is set to Waiting
111+ class TaskIncomplete (ibllib .pipes .tasks .Task ):
112+
113+ def _run (self , overwrite = False ):
114+ self .status = - 3
115+
116+
92117class SomePipeline (ibllib .pipes .tasks .Pipeline ):
93118
94119 def __init__ (self , session_path = None , ** kwargs ):
@@ -99,46 +124,14 @@ def __init__(self, session_path=None, **kwargs):
99124 tasks ['Task00' ] = Task00 (self .session_path )
100125 tasks ['Task01_void' ] = Task01_void (self .session_path )
101126 tasks ['Task02_error' ] = Task02_error (self .session_path )
127+ tasks ['TaskGpuLock' ] = TaskGpuLock (self .session_path )
128+ tasks ['TaskIncomplete' ] = TaskIncomplete (self .session_path )
102129 tasks ['Task10' ] = Task10 (self .session_path , parents = [tasks ['Task00' ]])
103130 tasks ['Task11' ] = Task11 (self .session_path , parents = [tasks ['Task02_error' ],
104131 tasks ['Task00' ]])
105132 self .tasks = tasks
106133
107134
108- # job to output a single file (pathlib.Path)
109- class GpuTask (ibllib .pipes .tasks .Task ):
110- gpu = 1
111-
112- def _run (self , overwrite = False ):
113- out_files = self .session_path .joinpath ('alf' , 'gpu.times.npy' )
114- out_files .touch ()
115- return out_files
116-
117-
118- class TestLocks (unittest .TestCase ):
119-
120- def test_gpu_lock_and_local_data_handler (self ) -> None :
121- with tempfile .TemporaryDirectory () as td :
122- session_path = Path (td ).joinpath ('algernon' , '2021/02/12' , '001' )
123- session_path .joinpath ('alf' ).mkdir (parents = True )
124- task = GpuTask (session_path , one = None , location = 'local' )
125- assert task .is_locked () is False
126- task .run ()
127- assert task .status == 0
128- assert task .is_locked () is False
129- # then make a lock file and make sure it fails and is still locked afterwards
130- task ._make_lock_file ()
131- task .run ()
132- assert task .status == - 2
133- assert task .is_locked ()
134- # test the time out feature
135- task .time_out_secs = - 1
136- task ._make_lock_file ()
137- assert not task .is_locked ()
138- task .run ()
139- assert task .status == 0
140-
141-
142135class TestPipelineAlyx (unittest .TestCase ):
143136
144137 def setUp (self ) -> None :
@@ -213,7 +206,7 @@ def test_pipeline_alyx(self):
213206 self .assertTrue (all (check_logs ))
214207 self .assertTrue (all (check_rerun ))
215208
216- # Rerun without clobber and check that logs are overwritten
209+ # Rerun without clobber and check that logs are not overwritten
217210 task_deck , dsets = pipeline .rerun_failed (machine = 'testmachine' , clobber = False )
218211 check_logs = [t ['log' ].count (desired_logs ) == desired_logs_rerun [t ['name' ]] if t ['log' ]
219212 else t ['log' ] == desired_logs_rerun [t ['name' ]] for t in task_deck ]
@@ -222,6 +215,45 @@ def test_pipeline_alyx(self):
222215 self .assertTrue (all (check_logs ))
223216 self .assertTrue (all (check_rerun ))
224217
218+ # Remove the lock file
219+ Path .home ().joinpath ('.one' , 'gpu.lock' ).unlink ()
220+
221+
222+ class GpuTask (ibllib .pipes .tasks .Task ):
223+ gpu = 1
224+
225+ def _run (self , overwrite = False ):
226+ out_files = self .session_path .joinpath ('alf' , 'gpu.times.npy' )
227+ out_files .touch ()
228+ return out_files
229+
230+
231+ class TestLocks (unittest .TestCase ):
232+
233+ def test_gpu_lock_and_local_data_handler (self ) -> None :
234+ # Remove any existing locks first
235+ if Path .home ().joinpath ('.one' , 'gpu.lock' ).exists ():
236+ Path .home ().joinpath ('.one' , 'gpu.lock' ).unlink ()
237+ with tempfile .TemporaryDirectory () as td :
238+ session_path = Path (td ).joinpath ('algernon' , '2021/02/12' , '001' )
239+ session_path .joinpath ('alf' ).mkdir (parents = True )
240+ task = GpuTask (session_path , one = None , location = 'local' )
241+ assert task .is_locked () is False
242+ task .run ()
243+ assert task .status == 0
244+ assert task .is_locked () is False
245+ # then make a lock file and make sure it fails and is still locked afterwards
246+ task ._make_lock_file ()
247+ task .run ()
248+ assert task .status == - 2
249+ assert task .is_locked ()
250+ # test the time out feature
251+ task .time_out_secs = - 1
252+ task ._make_lock_file ()
253+ assert not task .is_locked ()
254+ task .run ()
255+ assert task .status == 0
256+
225257
226258if __name__ == "__main__" :
227259 unittest .main (exit = False , verbosity = 2 )
0 commit comments