|
@@ -15,10 +15,20 @@
|
|
|
|
|
|
from starpu import starpupy
|
|
|
import starpu
|
|
|
+import sys
|
|
|
+try:
|
|
|
+ sys.path.remove('/usr/local/lib/python3.8/site-packages/starpu')
|
|
|
+except:
|
|
|
+ pass
|
|
|
import joblib
|
|
|
import asyncio
|
|
|
import math
|
|
|
import functools
|
|
|
+import numpy as np
|
|
|
+import threading
|
|
|
+
|
|
|
+BACKENDS={}
|
|
|
+_backend = threading.local()
|
|
|
|
|
|
|
|
|
def cpu_count():
|
|
@@ -43,20 +53,11 @@ def partition(ls, n_block):
|
|
|
L=[ls[i:i+1] for i in range (len(ls))]
|
|
|
return L
|
|
|
|
|
|
-def future_generator(g, n_jobs, dict_task):
|
|
|
-
|
|
|
- L=list(g)
|
|
|
-
|
|
|
- def lf(ls):
|
|
|
- L_func=[]
|
|
|
- for i in range(len(ls)):
|
|
|
-
|
|
|
- f=ls[i][0]
|
|
|
-
|
|
|
- L_args=list(ls[i][1])
|
|
|
-
|
|
|
- L_func.append(f(*L_args))
|
|
|
- return L_func
|
|
|
+def future_generator(iterable, n_jobs, dict_task):
|
|
|
+
|
|
|
+ print("iterable type is ", type(iterable))
|
|
|
+ print("iterable is", iterable)
|
|
|
+
|
|
|
|
|
|
if n_jobs<-cpu_count()-1 or n_jobs>cpu_count():
|
|
|
print("Error: n_jobs is out of range, number of CPUs is", cpu_count())
|
|
@@ -64,26 +65,70 @@ def future_generator(g, n_jobs, dict_task):
|
|
|
n_block=cpu_count()+1+n_jobs
|
|
|
else:
|
|
|
n_block=n_jobs
|
|
|
-
|
|
|
- L_split=partition(L,n_block)
|
|
|
-
|
|
|
- L_fut=[]
|
|
|
- for i in range(len(L_split)):
|
|
|
- fut=starpu.task_submit(name=dict_task['name'], synchronous=dict_task['synchronous'], priority=dict_task['priority'],\
|
|
|
- color=dict_task['color'], flops=dict_task['flops'], perfmodel=dict_task['perfmodel'])\
|
|
|
- (lf, L_split[i])
|
|
|
- L_fut.append(fut)
|
|
|
- return L_fut
|
|
|
-
|
|
|
-class Parallel(joblib.Parallel):
|
|
|
+
|
|
|
+
|
|
|
+ if type(iterable) is tuple:
|
|
|
+ L_fut=[]
|
|
|
+ for i in range(n_block):
|
|
|
+ L_args=[]
|
|
|
+ for j in range(len(iterable[1])):
|
|
|
+ if type(iterable[1][j]) is np.ndarray:
|
|
|
+ arr_split=np.array_split(iterable[1][j],n_block)
|
|
|
+ L_args.append(arr_split[i])
|
|
|
+ else:
|
|
|
+ L_args.append(iterable[1][j])
|
|
|
+ print("L_args is", L_args)
|
|
|
+ fut=starpu.task_submit()(iterable[0], *L_args)
|
|
|
+ L_fut.append(fut)
|
|
|
+ return L_fut
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+ L=list(iterable)
|
|
|
+
|
|
|
+
|
|
|
+ def lf(ls):
|
|
|
+ L_func=[]
|
|
|
+ for i in range(len(ls)):
|
|
|
+
|
|
|
+ f=ls[i][0]
|
|
|
+
|
|
|
+ L_args=list(ls[i][1])
|
|
|
+
|
|
|
+ L_func.append(f(*L_args))
|
|
|
+ return L_func
|
|
|
+
|
|
|
+
|
|
|
+ L_split=partition(L,n_block)
|
|
|
+
|
|
|
+ L_fut=[]
|
|
|
+ for i in range(len(L_split)):
|
|
|
+ fut=starpu.task_submit(name=dict_task['name'], synchronous=dict_task['synchronous'], priority=dict_task['priority'],\
|
|
|
+ color=dict_task['color'], flops=dict_task['flops'], perfmodel=dict_task['perfmodel'])\
|
|
|
+ (lf, L_split[i])
|
|
|
+ L_fut.append(fut)
|
|
|
+ return L_fut
|
|
|
+
|
|
|
+class Parallel(object):
|
|
|
def __init__(self, mode="normal", perfmodel=None, end_msg=None,\
|
|
|
name=None, synchronous=0, priority=0, color=None, flops=None,\
|
|
|
n_jobs=None, backend=None, verbose=0, timeout=None, pre_dispatch='2 * n_jobs',\
|
|
|
batch_size='auto', temp_folder=None, max_nbytes='1M',\
|
|
|
mmap_mode='r', prefer=None, require=None):
|
|
|
- super(Parallel, self).__init__(n_jobs=None, backend=None, verbose=0, timeout=None, pre_dispatch='2 * n_jobs',\
|
|
|
- batch_size='auto', temp_folder=None, max_nbytes='1M',\
|
|
|
- mmap_mode='r', prefer=None, require=None)
|
|
|
+ active_backend, context_n_jobs = get_active_backend(prefer=prefer, require=require, verbose=verbose)
|
|
|
+ nesting_level = active_backend.nesting_level
|
|
|
+
|
|
|
+ if backend is None:
|
|
|
+ backend = active_backend
|
|
|
+
|
|
|
+ else:
|
|
|
+ try:
|
|
|
+ backend_factory = BACKENDS[backend]
|
|
|
+ except KeyError as e:
|
|
|
+ raise ValueError("Invalid backend: %s, expected one of %r"
|
|
|
+ % (backend, sorted(BACKENDS.keys()))) from e
|
|
|
+ backend = backend_factory(nesting_level=nesting_level)
|
|
|
|
|
|
self.mode=mode
|
|
|
self.perfmodel=perfmodel
|
|
@@ -94,36 +139,40 @@ class Parallel(joblib.Parallel):
|
|
|
self.color=color
|
|
|
self.flops=flops
|
|
|
self.n_jobs=n_jobs
|
|
|
+ self._backend=backend
|
|
|
+
|
|
|
+ def print_progress(self):
|
|
|
+ pass
|
|
|
|
|
|
def __call__(self,iterable):
|
|
|
|
|
|
dict_task={'name': self.name, 'synchronous': self.synchronous, 'priority': self.priority, 'color': self.color, 'flops': self.flops, 'perfmodel': self.perfmodel}
|
|
|
+ if hasattr(self._backend, 'start_call'):
|
|
|
+ self._backend.start_call()
|
|
|
|
|
|
if self.mode=="normal":
|
|
|
-
|
|
|
async def asy_main():
|
|
|
L_fut=future_generator(iterable, self.n_jobs, dict_task)
|
|
|
res=[]
|
|
|
+ print(L_fut)
|
|
|
for i in range(len(L_fut)):
|
|
|
L_res=await L_fut[i]
|
|
|
+ print(L_res)
|
|
|
res.extend(L_res)
|
|
|
-
|
|
|
+ print(res)
|
|
|
return res
|
|
|
asyncio.run(asy_main())
|
|
|
- return asy_main
|
|
|
-
|
|
|
+ retVal=asy_main
|
|
|
|
|
|
elif self.mode=="future":
|
|
|
-
|
|
|
L_fut=future_generator(iterable, self.n_jobs, dict_task)
|
|
|
fut=asyncio.gather(*L_fut)
|
|
|
- if self.end_msg==None:
|
|
|
- return fut
|
|
|
- else:
|
|
|
+ if self.end_msg!=None:
|
|
|
fut.add_done_callback(functools.partial(print, self.end_msg))
|
|
|
- return fut
|
|
|
-
|
|
|
-
|
|
|
+ retVal=fut
|
|
|
+ if hasattr(self._backend, 'stop_call'):
|
|
|
+ self._backend.stop_call()
|
|
|
+ return retVal
|
|
|
|
|
|
def delayed(f):
|
|
|
def delayed_func(*args):
|
|
@@ -154,13 +203,44 @@ def register_compressor(compressor_name, compressor, force=False):
|
|
|
return joblib.register_compressor(compressor_name, compressor, force)
|
|
|
|
|
|
def effective_n_jobs(n_jobs=-1):
|
|
|
- return joblib.effective_n_jobs(n_jobs)
|
|
|
+ return cpu_count()
|
|
|
|
|
|
-class parallel_backend(joblib.parallel_backend):
|
|
|
+def get_active_backend(prefer=None, require=None, verbose=0):
|
|
|
+ return joblib.parallel.get_active_backend(prefer, require, verbose)
|
|
|
+
|
|
|
+class parallel_backend(object):
|
|
|
def __init__(self, backend, n_jobs=-1, inner_max_num_threads=None,
|
|
|
**backend_params):
|
|
|
- super(parallel_backend, self).__init__(backend, n_jobs=-1, inner_max_num_threads=None,
|
|
|
- **backend_params)
|
|
|
+ if isinstance(backend, str):
|
|
|
+ backend = BACKENDS[backend](**backend_params)
|
|
|
+
|
|
|
+ current_backend_and_jobs = getattr(_backend, 'backend_and_jobs', None)
|
|
|
+ if backend.nesting_level is None:
|
|
|
+ if current_backend_and_jobs is None:
|
|
|
+ nesting_level = 0
|
|
|
+ else:
|
|
|
+ nesting_level = current_backend_and_jobs[0].nesting_level
|
|
|
+
|
|
|
+ backend.nesting_level = nesting_level
|
|
|
+
|
|
|
+
|
|
|
+ self.old_backend_and_jobs = current_backend_and_jobs
|
|
|
+ self.new_backend_and_jobs = (backend, n_jobs)
|
|
|
+
|
|
|
+ _backend.backend_and_jobs = (backend, n_jobs)
|
|
|
+
|
|
|
+ def __enter__(self):
|
|
|
+ return self.new_backend_and_jobs
|
|
|
+
|
|
|
+ def __exit__(self, type, value, traceback):
|
|
|
+ self.unregister()
|
|
|
+
|
|
|
+ def unregister(self):
|
|
|
+ if self.old_backend_and_jobs is None:
|
|
|
+ if getattr(_backend, 'backend_and_jobs', None) is not None:
|
|
|
+ del _backend.backend_and_jobs
|
|
|
+ else:
|
|
|
+ _backend.backend_and_jobs = self.old_backend_and_jobs
|
|
|
|
|
|
-def register_parallel_backend(name, factory, make_default=False):
|
|
|
- return joblib.register_parallel_backend(name, factory, make_default)
|
|
|
+def register_parallel_backend(name, factory):
|
|
|
+ BACKENDS[name] = factory
|