def _static_threads_task(name, group, final_outputs, reader, num_threads, output, capacity): node_name = str(Node.current()) profiler_name = "{0}/{1}/{2}/{3}/{4}".format( node_name, "pipe", name, processor_name(input) if input else "NoInput", processor_name(output) if output else "NoOutput") with Task(name=name, group=group, outputs=final_outputs) as task: global_exit_net = core.Net('exit') global_init_net = core.Net('init') reader.setup_ex(global_init_net, global_exit_net) out_queue = None writer = None steps = [] for thread_id in range(num_threads): with NetBuilder(name='t:%d' % thread_id) as nb: init_net = core.Net('init') exit_net = core.Net('exit') read_nets, status, rec = reader.read_record_ex( init_net, exit_net) init_net.ConstantFill([], [status], shape=[], value=False, dtype=core.DataType.BOOL) if rec is not None: if writer is None: # hack so that the out queue gets the right name prefix # (otherwise they would be prefixed with the thread id) with NetBuilder(_fullname=task.name): out_queue, writer = _init_output( output, capacity, global_init_net, global_exit_net) write_nets, _ = writer.write_record_ex( rec, init_net, exit_net, status) else: write_nets = [] timer_start_net = core.Net('timer_start') timer = timer_start_net.TimerBegin([], counter_name=profiler_name) timer_end_net = core.Net('timer_end') timer_end_net.TimerEnd(timer, []) ops.net(init_net) ops.net( core.execution_step('body', [timer_start_net] + list(read_nets) + list(write_nets) + [timer_end_net], should_stop_blob=status)) ops.net(timer_end_net) ops.net(exit_net) steps.append(core.to_execution_step(nb)) ops.net(global_init_net) ops.net(core.execution_step('body', steps, concurrent_substeps=True)) ops.net(global_exit_net) return out_queue, task
def __call__(self, rec): assert not self._frozen prefix = NetBuilder.current().name + '/' blob_remap = {} for net in self.thread_init_nets: new_net, _ = core.clone_and_bind_net(net, str(net) + prefix, prefix, blob_remap) self._cloned_init_nets.append(new_net) new_net, remappings = core.clone_and_bind_net(self.net, str(self.net) + prefix, prefix, blob_remap, rec) if self._stop_signal is None: stop_signal = None elif str(self._stop_signal) in remappings: stop_signal = core.BlobReference(remappings[str( self._stop_signal)], net=new_net) else: stop_signal = self._stop_signal self._blob_maps.append(remappings) return Output([new_net], new_net.output_record(), stop_signal)
def read_ex(self, init_net, exit_net): read_nets, status, rec = self.reader.read_record_ex(init_net, exit_net) # We don't use status as stop_blob of NetBuilder it's not guarantee that # it would end up being the true stob_blob. For example, # ReaderWithLimitBase doesn't pass the status through but rather copy # from it. with NetBuilder() as nb: # Current NetBuilder is optionally used inside the processor, # then its children are retrived inside of # normalize_processor_output. # Once readers and writers also use NetBuilder, # this logic will be more natural. result = normalize_processor_output(self.processor(rec)) read_nets += result.nets if result.should_stop or nb._stop_blob: stop_net = core.Net('stop_net') if result.should_stop: stop_net.Or([status, result.should_stop], [status]) if nb._stop_blob: stop_net.Or([status, nb._stop_blob], [status]) read_nets.append(stop_net) if hasattr(self.processor, 'setup'): init_net.add_attribute(TaskGroup.LOCAL_SETUP, self.processor) self._set_schema(result.record) fields = result.record.field_blobs() if result.record else None return read_nets, status, fields
def __init__(self, nets=None, record=None, should_stop=None): builder_children = NetBuilder.current().get() assert nets is None or len(builder_children) == 0, ( 'Cannot both use `ops` syntax and return a list of nets.') if nets is None: nets = builder_children if isinstance(nets, core.Net): nets = [nets] self.nets = [] if nets is None else list(nets) self.record = None if record is None else as_record(record) self.should_stop = should_stop
def read_ex(self, init_net, exit_net): read_nets, status, rec = self.reader.read_record_ex(init_net, exit_net) with NetBuilder(_stop_blob=status): # Current NetBuilder is optionally used inside the processor, # then its children are retrived inside of # normalize_processor_output. # Once readers and writers also use NetBuilder, # this logic will be more natural. result = normalize_processor_output(self.processor(rec)) read_nets += result.nets if result.should_stop is not None: stop_net = core.Net('stop_net') stop_net.Copy([result.should_stop], [status]) read_nets.append(stop_net) if hasattr(self.processor, 'setup'): init_net.add_attribute(TaskGroup.LOCAL_SETUP, self.processor) self._set_schema(result.record) fields = result.record.field_blobs() if result.record else None return read_nets, status, fields
def test_while_net(self): with NetBuilder() as nb: x = ops.Const(0) y = ops.Const(0) with ops.WhileNet(): with ops.Condition(): ops.Add([x, ops.Const(1)], [x]) ops.LT([x, ops.Const(7)]) ops.Add([x, y], [y]) plan = Plan('while_net_test') plan.AddStep(to_execution_step(nb)) ws = workspace.C.Workspace() ws.run(plan) x_value = ws.blobs[str(x)].fetch() y_value = ws.blobs[str(y)].fetch() self.assertEqual(x_value, 7) self.assertEqual(y_value, 21)
def test_ops(self): with NetBuilder() as nb: y = _test_loop() z, w, a, b = _test_outer() p = _test_if(ops.Const(75)) q = _test_if(ops.Const(25)) plan = Plan('name') plan.AddStep(to_execution_step(nb)) ws = workspace.C.Workspace() ws.run(plan) expected = [ (y, 5), (z, False), (w, True), (a, False), (b, False), (p, 2), (q, 3), ] for b, expected in expected: actual = ws.blobs[str(b)].fetch() self.assertEquals(actual, expected)
def __call__(self, rec): assert not self._frozen prefix = NetBuilder.current().name + '/' blob_remap = {} for net in self.thread_init_nets: new_net, _ = core.clone_and_bind_net( net, str(net) + prefix, prefix, blob_remap) self._cloned_init_nets.append(new_net) new_net, remappings = core.clone_and_bind_net( self.net, str(self.net) + prefix, prefix, blob_remap, rec) if self._stop_signal is None: stop_signal = None elif str(self._stop_signal) in remappings: stop_signal = core.BlobReference( remappings[str(self._stop_signal)], net=new_net) else: stop_signal = self._stop_signal self._blob_maps.append(remappings) return Output([new_net], new_net.output_record(), stop_signal)
def testWhile(self): with NetBuilder(_use_control_ops=True) as nb: ops.Copy(ops.Const(0), "i") ops.Copy(ops.Const(1), "one") ops.Copy(ops.Const(2), "two") ops.Copy(ops.Const(2.0), "x") ops.Copy(ops.Const(3.0), "y") ops.Copy(ops.Const(2.0), "z") # raises x to the power of 4 and y to the power of 2 # and z to the power of 3 with ops.WhileNet(): with ops.Condition(): ops.Add(["i", "one"], "i") ops.LE(["i", "two"]) ops.Pow("x", "x", exponent=2.0) with ops.IfNet(ops.LT(["i", "two"])): ops.Pow("y", "y", exponent=2.0) with ops.Else(): ops.Pow("z", "z", exponent=3.0) ops.Add(["x", "y"], "x_plus_y") ops.Add(["x_plus_y", "z"], "s") assert len(nb.get()) == 1, "Expected a single net produced" net = nb.get()[0] net.AddGradientOperators(["s"]) workspace.RunNetOnce(net) # (x^4)' = 4x^3 self.assertAlmostEqual(workspace.FetchBlob("x_grad"), 32) self.assertAlmostEqual(workspace.FetchBlob("x"), 16) # (y^2)' = 2y self.assertAlmostEqual(workspace.FetchBlob("y_grad"), 6) self.assertAlmostEqual(workspace.FetchBlob("y"), 9) # (z^3)' = 3z^2 self.assertAlmostEqual(workspace.FetchBlob("z_grad"), 12) self.assertAlmostEqual(workspace.FetchBlob("z"), 8)
def test_if_net(self): with NetBuilder() as nb: x0 = ops.Const(0) x1 = ops.Const(1) x2 = ops.Const(2) y0 = ops.Const(0) y1 = ops.Const(1) y2 = ops.Const(2) # basic logic first_res = ops.Const(0) with ops.IfNet(ops.Const(True)): ops.Const(1, blob_out=first_res) with ops.Else(): ops.Const(2, blob_out=first_res) second_res = ops.Const(0) with ops.IfNet(ops.Const(False)): ops.Const(1, blob_out=second_res) with ops.Else(): ops.Const(2, blob_out=second_res) # nested and sequential ifs, # empty then/else, # passing outer blobs into branches, # writing into outer blobs, incl. into input blob # using local blobs with ops.IfNet(ops.LT([x0, x1])): local_blob = ops.Const(900) ops.Add([ops.Const(100), local_blob], [y0]) gt = ops.GT([x1, x2]) with ops.IfNet(gt): # empty then pass with ops.Else(): ops.Add([y1, local_blob], [local_blob]) ops.Add([ops.Const(100), y1], [y1]) with ops.IfNet(ops.EQ([local_blob, ops.Const(901)])): ops.Const(7, blob_out=y2) ops.Add([y1, y2], [y2]) with ops.Else(): # empty else pass plan = Plan('if_net_test') plan.AddStep(to_execution_step(nb)) ws = workspace.C.Workspace() ws.run(plan) first_res_value = ws.blobs[str(first_res)].fetch() second_res_value = ws.blobs[str(second_res)].fetch() y0_value = ws.blobs[str(y0)].fetch() y1_value = ws.blobs[str(y1)].fetch() y2_value = ws.blobs[str(y2)].fetch() self.assertEquals(first_res_value, 1) self.assertEquals(second_res_value, 2) self.assertEquals(y0_value, 1000) self.assertEquals(y1_value, 101) self.assertEquals(y2_value, 108) self.assertTrue(str(local_blob) not in ws.blobs)
def testIf(self): W_a_values = [2.0, 1.5] B_a_values = [0.5] W_b_values = [7.0, 3.5] B_b_values = [1.5] with NetBuilder(_use_control_ops=True) as init_nb: W_a = ops.UniformFill([], "W_a", shape=[1, 2], min=-1., max=1.) B_a = ops.ConstantFill([], "B_a", shape=[1], value=0.0) W_b = ops.UniformFill([], "W_b", shape=[1, 2], min=-1., max=1.) B_b = ops.ConstantFill([], "B_b", shape=[1], value=0.0) W_gt_a = ops.GivenTensorFill( [], "W_gt_a", shape=[1, 2], values=W_a_values) B_gt_a = ops.GivenTensorFill([], "B_gt_a", shape=[1], values=B_a_values) W_gt_b = ops.GivenTensorFill( [], "W_gt_b", shape=[1, 2], values=W_b_values) B_gt_b = ops.GivenTensorFill([], "B_gt_b", shape=[1], values=B_b_values) params = [W_gt_a, B_gt_a, W_a, B_a, W_gt_b, B_gt_b, W_b, B_b] with NetBuilder(_use_control_ops=True, initial_scope=params) as train_nb: Y_pred = ops.ConstantFill([], "Y_pred", shape=[1], value=0.0) Y_noise = ops.ConstantFill([], "Y_noise", shape=[1], value=0.0) switch = ops.UniformFill( [], "switch", shape=[1], min=-1., max=1., run_once=0) zero = ops.ConstantFill([], "zero", shape=[1], value=0.0) X = ops.GaussianFill( [], "X", shape=[4096, 2], mean=0.0, std=1.0, run_once=0) noise = ops.GaussianFill( [], "noise", shape=[4096, 1], mean=0.0, std=1.0, run_once=0) with ops.IfNet(ops.LT([switch, zero])): Y_gt = ops.FC([X, W_gt_a, B_gt_a], "Y_gt") ops.Add([Y_gt, noise], Y_noise) ops.FC([X, W_a, B_a], Y_pred) with ops.Else(): Y_gt = ops.FC([X, W_gt_b, B_gt_b], "Y_gt") ops.Add([Y_gt, noise], Y_noise) ops.FC([X, W_b, B_b], Y_pred) dist = ops.SquaredL2Distance([Y_noise, Y_pred], "dist") loss = dist.AveragedLoss([], ["loss"]) assert len(init_nb.get()) == 1, "Expected a single init net produced" assert len(train_nb.get()) == 1, "Expected a single train net produced" train_net = train_nb.get()[0] gradient_map = train_net.AddGradientOperators([loss]) init_net = init_nb.get()[0] ITER = init_net.ConstantFill( [], "ITER", shape=[1], value=0, dtype=core.DataType.INT64) train_net.Iter(ITER, ITER) LR = train_net.LearningRate(ITER, "LR", base_lr=-0.1, policy="step", stepsize=20, gamma=0.9) ONE = init_net.ConstantFill([], "ONE", shape=[1], value=1.) train_net.WeightedSum([W_a, ONE, gradient_map[W_a], LR], W_a) train_net.WeightedSum([B_a, ONE, gradient_map[B_a], LR], B_a) train_net.WeightedSum([W_b, ONE, gradient_map[W_b], LR], W_b) train_net.WeightedSum([B_b, ONE, gradient_map[B_b], LR], B_b) workspace.RunNetOnce(init_net) workspace.CreateNet(train_net) # print("Before training, W_a is: {}".format(workspace.FetchBlob("W_a"))) # print("Before training, B_a is: {}".format(workspace.FetchBlob("B_a"))) # print("Before training, W_b is: {}".format(workspace.FetchBlob("W_b"))) # print("Before training, B_b is: {}".format(workspace.FetchBlob("B_b"))) for _epoch in range(1000): workspace.RunNet(train_net.Proto().name) # print("After training, W_a is: {}".format(workspace.FetchBlob("W_a"))) # print("After training, B_a is: {}".format(workspace.FetchBlob("B_a"))) # print("After training, W_b is: {}".format(workspace.FetchBlob("W_b"))) # print("After training, B_b is: {}".format(workspace.FetchBlob("B_b"))) # print("Ground truth W_a is: {}".format(workspace.FetchBlob("W_gt_a"))) # print("Ground truth B_a is: {}".format(workspace.FetchBlob("B_gt_a"))) # print("Ground truth W_b is: {}".format(workspace.FetchBlob("W_gt_b"))) # print("Ground truth B_b is: {}".format(workspace.FetchBlob("B_gt_b"))) values_map = { "W_a": W_a_values, "B_a": B_a_values, "W_b": W_b_values, "B_b": B_b_values, } train_eps = 0.01 for blob_name, values in values_map.items(): trained_values = workspace.FetchBlob(blob_name) if trained_values.ndim == 2: self.assertEqual(trained_values.shape[0], 1) trained_values = trained_values[0][:] else: self.assertEqual(trained_values.ndim, 1) self.assertEqual(trained_values.size, len(values)) for idx in range(len(trained_values)): self.assertTrue(abs(trained_values[idx] - values[idx]) < train_eps)
def _pipe_step(input, output=None, num_threads=1, processor=None, name=None, capacity=None, group=None, final_outputs=None): """ """ if isinstance(input, Reader): reader = input elif hasattr(input, 'reader'): reader = input.reader() else: raise ValueError('in must be a reader, queue or streaam.') if processor is not None: reader = ProcessingReader(reader, processor) if num_threads == 0: assert output is None return reader, None if name is None and processor is not None: name = processor_name(processor) if name is None and output is not None: name = 'pipe_into:%s' % processor_name(output) if name is None: name = 'pipe_from:%s' % processor_name(input) node_name = str(Node.current()) profiler_name = "{0}/{1}/{2}/{3}/{4}".format( node_name, "pipe", name, processor_name(input) if input else "NoInput", processor_name(output) if output else "NoOutput") with Task(name=name, group=group, outputs=final_outputs) as task: global_exit_net = core.Net('exit') global_init_net = core.Net('init') reader.setup_ex(global_init_net, global_exit_net) out_queue = None writer = None steps = [] for thread_id in range(num_threads): with NetBuilder(name='t:%d' % thread_id) as nb: init_net = core.Net('init') exit_net = core.Net('exit') read_nets, status, rec = reader.read_record_ex( init_net, exit_net) init_net.ConstantFill([], [status], shape=[], value=False, dtype=core.DataType.BOOL) if rec is not None: if writer is None: # hack so that the out queue gets the right name prefix # (otherwise they would be prefixed with the thread id) with NetBuilder(_fullname=task.name): out_queue, writer = _init_output( output, capacity, global_init_net, global_exit_net) write_nets, _ = writer.write_record_ex( rec, init_net, exit_net, status) else: write_nets = [] timer_start_net = core.Net('timer_start') timer = timer_start_net.TimerBegin([], counter_name=profiler_name) timer_end_net = core.Net('timer_end') timer_end_net.TimerEnd(timer, []) ops.net(init_net) ops.net( core.execution_step('body', [timer_start_net] + list(read_nets) + list(write_nets) + [timer_end_net], should_stop_blob=status)) ops.net(timer_end_net) ops.net(exit_net) steps.append(core.to_execution_step(nb)) ops.net(global_init_net) ops.net(core.execution_step('body', steps, concurrent_substeps=True)) ops.net(global_exit_net) return out_queue, task
# ### Conditional Execution # Let's start with conditional operator. We will demostrate how to use it in two Caffe2 APIs used for building nets: NetBuilder and Brew. # In the first example, we first define several blobs and then use 'If' operator to set value of one of them conditionally depending on values of other blobs. # In[1]: from caffe2.python import workspace from caffe2.python.core import Plan, to_execution_step, Net from caffe2.python.net_builder import ops, NetBuilder # In[2]: with NetBuilder() as nb: ops.Const(0.0, blob_out="zero") ops.Const(1.0, blob_out="one") ops.Const(0.5, blob_out="x") ops.Const(0.0, blob_out="y") with ops.IfNet(ops.GT(["x", "zero"])): ops.Copy("one", "y") with ops.Else(): ops.Copy("zero", "y") # Note the usage of NetBuilder's ops.IfNet and ops.Else calls: ops.IfNet accepts a blob reference or blob name as an input, it expects an input blob to have a scalar value convertible to bool, also note that optional ops.Else is at the same level as ops.IfNet and immediately follows corresponding ops.IfNet. Let's execute resulting net (execution step) and check values of blobs. # In[3]: plan = Plan('if_net_test') plan.AddStep(to_execution_step(nb))
def _pipe_step(input, output=None, num_threads=1, processor=None, name=None, capacity=None, group=None, final_outputs=None): """ """ if isinstance(input, Reader): reader = input elif hasattr(input, 'reader'): reader = input.reader() else: raise ValueError('in must be a reader, queue or streaam.') if processor is not None: reader = ProcessingReader(reader, processor) if num_threads == 0: assert output is None return reader, None if name is None and processor is not None: name = processor_name(processor) if name is None and output is not None: name = 'pipe_into:%s' % processor_name(output) if name is None: name = 'pipe_from:%s' % processor_name(input) with Task(name=name, group=group, outputs=final_outputs) as task: global_exit_net = core.Net('exit') global_init_net = core.Net('init') reader.setup_ex(global_init_net, global_exit_net) out_queue = None writer = None steps = [] for thread_id in range(num_threads): with NetBuilder(name='t:%d' % thread_id) as nb: init_net = core.Net('init') exit_net = core.Net('exit') read_nets, status, rec = reader.read_record_ex( init_net, exit_net) if rec is not None: if writer is None: # hack so that the out queue gets the right name prefix # (otherwise they would be prefixed with the thread id) with NetBuilder(_fullname=task.name): out_queue, writer = _init_output( output, capacity, global_init_net, global_exit_net) write_nets, _ = writer.write_record_ex( rec, init_net, exit_net, status) else: write_nets = [] ops.net(init_net) ops.net( core.execution_step('body', list(read_nets) + list(write_nets), should_stop_blob=status)) ops.net(exit_net) steps.append(core.to_execution_step(nb)) ops.net(global_init_net) ops.net(core.execution_step('body', steps, concurrent_substeps=True)) ops.net(global_exit_net) return out_queue, task