def _run_linearity_test(scheduler): import random from time import sleep max_ = 100 original_sequence = list(range(max_)) def orig(x): # print("In act1:", x) return x def app_fn(x): # print("In act2:", x) s = random.randint(1, 30) / 1000.0 sleep(s) return x orig_actor = FuncActor(orig, outports=('x', )) orig_actor.scheduler = scheduler new_actor = FuncActor(app_fn, outports=('x', )) orig_actor.outports["x"].connect(new_actor.inports["x"]) for i in range(max_): scheduler.put_value(orig_actor.inports["x"], i) scheduler.execute() new_sequence = list(new_actor.outports['x'].pop_all()) print("Received: ", new_sequence) print("Expected: ", original_sequence) assert new_sequence == original_sequence
def test_LoopWhileActor(): def condition(x): return x < 10 def func(x): return x + 1 fa = FuncActor(func, outports=('x', )) lw = LoopWhile("a_loop", condition_func=condition) fa.inports['x'] += lw.outports['loop'] lw.inports['loop'] += fa.outports['x'] lw.inports['init'].put(0) NaiveScheduler().run_actor(lw) result = lw.outports['exit'].pop() assert (result == 10) # test with condition actor fa = FuncActor(func, outports=('x', )) ca = FuncActor(condition, outports=('out', )) lw = LoopWhile("a_loop") lw.inports['condition_out'] += ca.outports['out'] ca.inports['x'] += lw.outports['condition_in'] fa.inports['x'] += lw.outports['loop'] lw.inports['loop'] += fa.outports['x'] lw.inports['init'].put(0) NaiveScheduler().run_actor(lw) result = lw.outports['exit'].pop() assert (result == 10)
def test_ignore_PEP_484_annotations(): def func(x, y) -> int: return int(x + y + 2) x, y = 2, 3 fa = FuncActor(func) fa.inports.x.put(x) fa.inports.y.put(y) NaiveScheduler().run_actor(fa) res = func(x, y) assert (fa.outports.out.pop() == res) # test with a given outport name fa = FuncActor(func, outports=('o', )) fa.inports.x.put(x) fa.inports.y.put(y) NaiveScheduler().run_actor(fa) res = func(x, y) assert (fa.outports.o.pop() == res)
def _test_workflow_chain(scheduler, wf_scheduler): from wowp.actors import FuncActor from wowp.actors.mapreduce import PassWID import math import random import six sin = FuncActor(math.sin) asin = FuncActor(math.asin) # first workflow asin.inports['inp'] += sin.outports['out'] wf1 = sin.get_workflow() # second workflow passwid = PassWID() wf2 = passwid.get_workflow() # connect the two workflows wf2.inports['inp'] += wf1.outports['out'] wf1.scheduler = wf_scheduler wf2.scheduler = wf_scheduler inp = random.random() scheduler.run_workflow(wf1, inp=inp) res1 = wf1.outports['out'].pop_all() res2 = wf2.outports['out'].pop_all() # wf1 wmpty output assert not res1 # wf2 has output assert res2 assert len(res2) == 1 if six.PY3: assert math.isclose(res2[0]['inp'], inp) else: assert math.fabs(res2[0]['inp'] - inp) < 1e-10
def test_two_to_one_connected(): """Two converging lines. --func1(.)--+ | +-func2(.,.)-- | --func1(.)--+ """ def func1(x): return x * 2 def func2(x, y): return x + y in_actor1 = FuncActor(func1, outports=('a', )) in_actor2 = FuncActor(func1, outports=('a', )) out_actor = FuncActor(func2, outports=('a', )) out_actor.inports['x'] += in_actor1.outports['a'] out_actor.inports['y'] += in_actor2.outports['a'] in_value1 = 1 in_value2 = 2 in_actor2.inports['x'].put(in_value2) in_actor1.inports['x'].put(in_value1) NaiveScheduler().run_actor(in_actor1) NaiveScheduler().run_actor(in_actor2) assert func2(func1(in_value1), func1(in_value2)) == out_actor.outports['a'].pop()
def _split_and_sum(act, depth): if depth == 0: return act else: child1 = FuncActor(ident, outports=('a',)) child2 = FuncActor(ident, outports=('a',)) act.outports['a'].connect(child1.inports['a']) act.outports['a'].connect(child2.inports['a']) children = [_split_and_sum(child, depth - 1) for child in (child1, child2)] summer = FuncActor(sum, outports=('a',)) summer.inports['a'].connect(children[0].outports['a']) summer.inports['b'].connect(children[1].outports['a']) return summer
def test_map_linear(): ra = FuncActor(range) func = math.sin map_act = Map(FuncActor, args=(func, )) map_act.inports['inp'] += ra.outports['out'] wf = ra.get_workflow() sch = LinearizedScheduler() inp = 5 sch.run_workflow(wf, inp=inp) result = wf.outports.out.pop_all() assert len(result) == 1 assert all((a, b) for a, b in zip_longest(result[0], map(func, range(inp))))
def _run_tree_512_test(scheduler): def sum(a, b): return a + b def ident(a): return a def _split_and_sum(act, depth): if depth == 0: return act else: child1 = FuncActor(ident, outports=('a',)) child2 = FuncActor(ident, outports=('a',)) act.outports['a'].connect(child1.inports['a']) act.outports['a'].connect(child2.inports['a']) children = [_split_and_sum(child, depth - 1) for child in (child1, child2)] summer = FuncActor(sum, outports=('a',)) summer.inports['a'].connect(children[0].outports['a']) summer.inports['b'].connect(children[1].outports['a']) return summer first = FuncActor(ident, outports=('a',)) power = 8 last = _split_and_sum(first, power) scheduler.put_value(first.inports['a'], 1) scheduler.execute() assert (2 ** power == last.outports['a'].pop())
def test_ThrededScheduler_creates_threads_and_executes_all(): """Test whether more threads are being used by the scheduler""" thread_ids = set() jobs_executed = {'count': 0} def func(x): # nonlocal jobs_executed import threading thread_ids.add(threading.current_thread().ident) jobs_executed['count'] += 1 return x branch_count = 40 # times 2 branch_length = 10 thread_count = 8 scheduler = ThreadedScheduler(max_threads=thread_count) for i in range(branch_count): actors = [] for j in range(branch_length): actor = FuncActor(func, outports=('x', )) if j == 0: scheduler.put_value(actor.inports['x'], 0) else: actor.inports["x"].connect(actors[j - 1].outports["x"]) actors.append(actor) scheduler.execute() # How many threads were used assert thread_count >= len(thread_ids) assert 1 < len(thread_ids) assert jobs_executed['count'] == branch_count * branch_length
def _call_workflow(scheduler, wf_scheduler): if (isinstance(scheduler, ThreadedScheduler) or isinstance(wf_scheduler, ThreadedScheduler)): # skip temporarily raise nose.SkipTest import math sin = FuncActor(math.sin) asin = FuncActor(math.asin) asin.inports['inp'] += sin.outports['out'] wf = sin.get_workflow() wf.scheduler = wf_scheduler x = math.pi / 2 res = wf(scheduler=scheduler, inp=x) assert res['out'].pop() == math.asin(math.sin(x))
def test_FuncActor_call(): def func(x, y): return x + 1, y + 2 x, y = 2, 3.1 fa = FuncActor(func, outports=('a', 'b')) assert func(x, y) == fa(x, y)
def _run_workflow(scheduler, wf_scheduler): if (isinstance(scheduler, ThreadedScheduler) or isinstance(wf_scheduler, ThreadedScheduler)): # skip temporarily raise nose.SkipTest import math sin = FuncActor(math.sin) asin = FuncActor(math.asin) asin.inports['inp'] += sin.outports['out'] wf = sin.get_workflow() wf.scheduler = wf_scheduler x = math.pi / 2 scheduler.run_workflow(wf, inp=x) res = {port.name: port.pop_all() for port in wf.outports} assert res['out'].pop() == math.asin(math.sin(x))
def test_FuncActor_return_annotation(): def func(x, y) -> ('a', 'b'): return x + 1, y + 2 x, y = 2, 3.1 f_actors = (FuncActor(func, outports=('a', 'b')), FuncActor(func)) for fa in f_actors: fa.inports.x.put(x) fa.inports.y.put(y) NaiveScheduler().run_actor(fa) a, b = func(x, y) assert (fa.outports.a.pop() == a) assert (fa.outports.b.pop() == b)
def test_two_connected(): """Two connected function actors. --func1(.)--func2(.)-- """ def func1(x): return x * 2 def func2(a): return a + 3 actor1 = FuncActor(func1, outports=('a', )) actor2 = FuncActor(func2, outports=('y', )) actor2.inports['a'] += actor1.outports['a'] for in_value in range(10): actor1.inports['x'].put(in_value) NaiveScheduler().run_actor(actor1) assert func2(func1(in_value)) == actor2.outports['y'].pop()
def test_three_in_line(): """Three linearly connected function actors. --func(.)--func(.)--func(.)-- """ def func(x): return x * 2 actor1 = FuncActor(func, outports=('x', )) actor2 = FuncActor(func, outports=('x', )) actor3 = FuncActor(func, outports=('x', )) actor2.inports['x'] += actor1.outports['x'] actor3.inports['x'] += actor2.outports['x'] in_value = 4 actor1.inports['x'].put(in_value) NaiveScheduler().run_actor(actor1) assert (func(func(func(in_value)))) == actor3.outports['x'].pop()
def _run_linearity_test(scheduler, size=100, ntimes=1): max_ = size original_sequence = list(range(max_)) orig_actor = FuncActor(orig, outports=('x',)) orig_actor.scheduler = scheduler new_actor = FuncActor(app_fn, outports=('x',)) orig_actor.outports["x"].connect(new_actor.inports["x"]) for t in range(ntimes): for i in range(max_): scheduler.put_value(orig_actor.inports["x"], i) scheduler.execute() new_sequence = list(new_actor.outports['x'].pop_all()) try: assert new_sequence == original_sequence except AssertionError: print("Received: ", new_sequence) print("Expected: ", original_sequence) raise
def test_FuncActor_partial_kwargs(): def func(x, y): return x + 1, y + 2 x, y = 2, 3.1 fa = FuncActor(func, kwargs={'y': y}, outports=('a', 'b')) fa.inports.x.put(x) NaiveScheduler().run_actor(fa) a, b = func(x, y) assert (fa.outports.a.pop() == a) assert (fa.outports.b.pop() == b)
def test_LinearizedScheduler_loop1000(scheduler): def condition(x): return x < 1000 def func(x): return x + 1 fa = FuncActor(func, outports=('x', )) lw = LoopWhile("a_loop", condition) fa.inports['x'] += lw.outports['loop'] lw.inports['loop'] += fa.outports['x'] scheduler.put_value(lw.inports['init'], 0) scheduler.execute() result = lw.outports['exit'].pop() assert (result == 1000)
def test_SwitchActor(): for val in (True, False): token = random.randint(0, 100) sw = Switch("switch", lambda x: val) sw.inports['inp'].put(token) pname = 'true' if val else 'false' NaiveScheduler().run_actor(sw) assert sw.outports[pname].pop() == token assert not sw._in_condition for val in (True, False): token = random.randint(0, 100) sw = Switch("switch") ca = FuncActor(lambda x: val) sw.inports['condition_out'] += ca.outports['out'] ca.inports['x'] += sw.outports['condition_in'] sw.inports['inp'].put(token) pname = 'true' if val else 'false' NaiveScheduler().run_actor(sw) assert sw.outports[pname].pop() == token assert not sw._in_condition
from wowp.actors import FuncActor import math sin = FuncActor(math.sin) asin = FuncActor(math.asin) asin.inports['inp'] += sin.outports['out'] WORKFLOW = sin.get_workflow() INPUTS = { 'inp': math.pi / 2 }