def load_scheduled_xgraph_opaque_func(build_dir: str, cb_scheduled_xgraph: XGraph): """ Expose the load scheduled xgraph function as an opaque function so it can be called in a language agnostic way Arguments --------- build_dir: str the path to the build directory containing a meta.json file cb_scheduled_xgraph: XGraph return the scheduled XGraph """ meta_file = os.path.join(build_dir, 'meta.json') if (not os.path.isfile(meta_file)): raise ValueError("Could not find meta file at: {}".format(meta_file)) with open(meta_file) as json_file: meta_d = json.load(json_file) px_net_file = meta_d['px_model'] px_params_file = meta_d['px_params'] if not os.path.isabs(px_net_file): px_net_file = os.path.join(build_dir, px_net_file) if not os.path.isabs(px_params_file): px_params_file = os.path.join(build_dir, px_params_file) scheduled_xgraph = load(px_net_file, px_params_file) cb_scheduled_xgraph.copy_from(scheduled_xgraph)
def quantization_opaque_func(xgraph: XGraph, target: str, in_names: List[str], in_tensors: List[XBuffer]) -> None: """ Expose quantization as an opaque function so it can be called from both Python and C++ Arguments --------- xgraph: XGraph the XGraph model target: str the target backend for executing this xgraph the target should be registered with a corresponding build function. in_names: List[str] the names of the input names (in the same order as the input data) in_tensors: List[XBuffer] The input tensors (in the same order as the ) """ def inputs_func(iter): inputs = { in_name: it.to_numpy() for in_name, it in zip(in_names, in_tensors) } return inputs q_xgraph = _quantize(xgraph, target, inputs_func) xgraph.copy_from(q_xgraph)
def test_multiple_registrations(self): assert OpaqueFuncRegistry.Size() == 0 @register_opaque_func('py_func1', [TypeCode.Str, TypeCode.XGraph]) def py_func(str_name, xgraph): assert xgraph.get_name() == "name1" xgraph.set_name(str_name) @register_opaque_func('py_func2', [TypeCode.Str, TypeCode.XGraph]) def py_func2(str_name, xgraph): xgraph.add(XLayer(name=str_name, type=[str_name])) assert OpaqueFuncRegistry.Size() == 2 assert set(OpaqueFuncRegistry.GetRegisteredFuncs()) == \ set(['py_func1', 'py_func2']) xg = XGraph("name1") of1 = OpaqueFuncRegistry.Get("py_func1") of1("name2", xg) assert xg.get_name() == "name2" assert len(xg) == 0 of2 = OpaqueFuncRegistry.Get("py_func2") of2("x1", xg) assert xg.get_name() == "name2" assert len(xg) == 1 assert xg.get('x1').name == 'x1' assert xg.get('x1').type == ['x1']
def test_xgraph_arg_name(self): def py_func(xg): assert xg.get_name() == "test" xg.set_name("test2") xgraph = XGraph("test") of = OpaqueFunc(py_func, [TypeCode.XGraph]) of(xgraph) assert xgraph.get_name() == "test2"
def optimize(xgraph: XGraph, target: str, **kwargs) -> XGraph: """Optimize the XGraph for the given target""" fancy_logger.banner("START GRAPH OPTIMIZATION FOR TARGET: {}" .format(target)) opt_xgraph = target_registry.get_target_optimizer(target)( xgraph, target=target, **kwargs) if xgraph.is_quantized(): opt_xgraph.set_quantizer_output(xgraph.get_quantizer_output()) return opt_xgraph
def partition_opaque_func(xgraph: XGraph, targets: List[str], last_layer: str = None): """ Expose the XGraph partition function an opaque function so it can be called from both Python and C++ """ if last_layer == "": last_layer = None p_xgraph = partition(xgraph, targets, last_layer) xgraph.copy_from(p_xgraph)
def test_xgraph_layer_add(self): def py_func(xg): assert xg.get_name() == "test" X = XLayer(name='x1', type=['X1']) xg.add(X) xgraph = XGraph("test") assert len(xgraph) == 0 of = OpaqueFunc(py_func, [TypeCode.XGraph]) of(xgraph) assert xgraph.get_name() == "test" assert len(xgraph) == 1 assert xgraph.get('x1').type == ['X1']
def test_registration_flow(self): assert OpaqueFuncRegistry.Size() == 0 @register_opaque_func('py_func', [TypeCode.Str, TypeCode.XGraph]) def py_func(str_name, xgraph): assert xgraph.get_name() == "name1" xgraph.set_name(str_name) assert OpaqueFuncRegistry.Size() == 1 assert OpaqueFuncRegistry.GetRegisteredFuncs() == ['py_func'] xg = XGraph("name1") of = OpaqueFuncRegistry.Get("py_func") of("name2", xg) assert xg.get_name() == "name2"
def read_xgraph_str(xg_str: bytes): of = OpaqueFuncRegistry.Get("pyxir.io.deserialize_xgraph") xg = XGraph() s = BytesContainer(xg_str) # import pdb; pdb.set_trace() of(xg, s) return xg
def test_xgraph_meta_attrs(self): xgraph = XGraph("xg") assert len(xgraph.meta_attrs) == 0 xgraph.meta_attrs["test_attr"] = "test_val" assert len(xgraph.meta_attrs) == 1 assert xgraph.meta_attrs["test_attr"] == "test_val" xgraph.meta_attrs["test_attr2"] = {"test_key": "test_val"} assert len(xgraph.meta_attrs) == 2 assert xgraph.meta_attrs["test_attr2"] == {"test_key": "test_val"} xgraph.meta_attrs = {"d_test_attr": ["t1", "t2"]} assert len(xgraph.meta_attrs) == 1 assert xgraph.meta_attrs["d_test_attr"] == ["t1", "t2"]
def schedule(xgraph: XGraph, target: str, **kwargs) -> XGraph: """ Schedule a xgraph for execution on the given target Returns XGraph containing only executable operations """ fancy_logger.banner("SCHEDULE `{}` EXECUTION GRAPH".format(target)) xgraph = target_registry.get_target_build_func(target)(xgraph.copy(), **kwargs) return xgraph
def test_copy(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='in2', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='add1', type=['Eltwise'], bottoms=['conv1', 'in2'], tops=[], targets=[] )) xgraph.insert(XLayer( name='conv2', type=['Convolution'], bottoms=['in2'], tops=['add1'], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='pool1', type=['Pooling'], bottoms=['add1'], tops=[], targets=[] )) assert len(xgraph) == 6 assert xgraph.get_layer_names() == \ ['in1', 'conv1', 'in2', 'conv2', 'add1', 'pool1'] xg_copy = xgraph.copy() assert len(xg_copy) == 6 assert xg_copy.get_layer_names() == \ ['in1', 'conv1', 'in2', 'conv2', 'add1', 'pool1'] xgc_layers = xg_copy.get_layers() assert xgc_layers[1].type == ['Convolution'] assert xg_copy.get('conv1').type == ['Convolution'] xgc_layers[1].type = ['Convolution2'] assert xg_copy.get('conv1').type == ['Convolution2'] xgc_layers[1].type = ['Convolution'] assert xgc_layers[1].type == ['Convolution'] assert xg_copy.get('conv1').type == ['Convolution'] np.testing.assert_array_equal( xgc_layers[1].data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32) ) np.testing.assert_array_equal( xgc_layers[1].data.biases, np.array([0., 1.], dtype=np.float32) ) xgraph.get('conv1').data = ConvData( weights=xgc_layers[1].data.weights * 2, biases=xgc_layers[1].data.biases ) np.testing.assert_array_equal( xgraph.get('conv1').data.weights, np.array([[[[2, 4], [6, 8]]]], dtype=np.float32) ) np.testing.assert_array_equal( xgc_layers[1].data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32) ) np.testing.assert_array_equal( xgc_layers[1].data.biases, np.array([0., 1.], dtype=np.float32) )
def test_xgraph_device_tagging(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='in2', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='add1', type=['Eltwise'], bottoms=['conv1', 'in2'], tops=[], targets=[] )) xgraph.insert(XLayer( name='conv2', type=['Convolution'], bottoms=['in2'], tops=['add1'], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='pool1', type=['Pooling'], bottoms=['add1'], tops=[], targets=[] )) xgraph = partition(xgraph, ['cpu']) assert len(xgraph) == 6 xlayers = xgraph.get_layers() assert xgraph.get_layer_names() == \ ['in1', 'conv1', 'in2', 'conv2', 'add1', 'pool1'] assert set(xlayers[0].targets) == set(['cpu', 'qsim']) assert set(xlayers[1].targets) == set(['cpu', 'qsim', 'test']) assert set(xlayers[2].targets) == set(['cpu', 'qsim']) assert set(xlayers[3].targets) == set(['cpu', 'qsim', 'test']) assert set(xlayers[4].targets) == set(['cpu', 'qsim']) assert set(xlayers[5].targets) == set(['cpu', 'qsim', 'test']) xgraph.remove('conv1') assert len(xgraph) == 5 xlayers = xgraph.get_layers() assert xgraph.get_layer_names() == \ ['in1', 'in2', 'conv2', 'add1', 'pool1'] assert xlayers[3].type[0] == 'Eltwise' assert xlayers[3].bottoms == ['in1', 'conv2'] assert set(xlayers[0].targets) == set(['cpu', 'qsim']) assert set(xlayers[1].targets) == set(['cpu', 'qsim']) assert set(xlayers[2].targets) == set(['cpu', 'qsim', 'test']) assert set(xlayers[3].targets) == set(['cpu', 'qsim']) assert set(xlayers[4].targets) == set(['cpu', 'qsim', 'test'])
def test_xgraph_insert(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) assert(len(xgraph) == 1) assert(len(xgraph.get_layer_names()) == 1) assert(len(xgraph.get_output_names()) == 1) assert(len(xgraph.get_input_names()) == 1) X_conv = XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] ) xgraph.add(X_conv) assert len(xgraph) == 2 assert len(xgraph.get_layer_names()) == 2 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 X_pool = XLayer( name='pool1', type=['Pooling'], bottoms=['in1'], tops=['conv1'], targets=[] ) xgraph.insert(X_pool) assert len(xgraph) == 3 assert len(xgraph.get_layer_names()) == 3 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 xlayers = xgraph.get_layers() assert xlayers[0].name == 'in1' assert xlayers[0].bottoms == [] assert xlayers[0].tops == ['pool1'] assert xlayers[1].name == 'pool1' assert xlayers[1].bottoms == ['in1'] assert xlayers[1].tops == ['conv1'] assert xlayers[2].name == 'conv1' assert xlayers[2].bottoms == ['pool1'] assert xlayers[2].tops == [] X_in2 = XLayer( name='in2', type=['Input'], bottoms=[], tops=[], targets=[] ) xgraph.add(X_in2) X_add = XLayer( name='add1', type=['Eltwise'], bottoms=['conv1', 'in2'], tops=[], targets=[] ) xgraph.add(X_add) X_conv2 = XLayer( name='conv2', type=['Convolution'], bottoms=['in2'], tops=['add1'], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] ) xgraph.insert(X_conv2) assert(len(xgraph) == 6) assert(len(xgraph.get_layer_names()) == 6) assert(len(xgraph.get_output_names()) == 1) assert(len(xgraph.get_input_names()) == 2) xlayers = xgraph.get_layers() assert xlayers[0].name == 'in1' assert xlayers[0].bottoms == [] assert xlayers[0].tops == ['pool1'] assert xlayers[1].name == 'pool1' assert xlayers[1].bottoms == ['in1'] assert xlayers[1].tops == ['conv1'] assert xlayers[2].name == 'conv1' assert xlayers[2].bottoms == ['pool1'] assert xlayers[2].tops == ['add1'] assert xlayers[3].name == 'in2' assert xlayers[3].bottoms == [] assert xlayers[3].tops == ['conv2'] assert xlayers[4].name == 'conv2' assert xlayers[4].bottoms == ['in2'] assert xlayers[4].tops == ['add1'] assert xlayers[5].name == 'add1' assert xlayers[5].bottoms == ['conv1', 'conv2'] assert xlayers[5].tops == []
def test_xgraph_add_remove(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) assert(len(xgraph) == 1) assert(len(xgraph.get_layer_names()) == 1) assert(len(xgraph.get_output_names()) == 1) assert(len(xgraph.get_input_names()) == 1) X_conv = XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] ) xgraph.add(X_conv) assert(len(xgraph) == 2) assert(len(xgraph.get_layer_names()) == 2) assert(len(xgraph.get_output_names()) == 1) assert(len(xgraph.get_input_names()) == 1) xgraph.remove(X_conv.name) assert(len(xgraph) == 1) assert(len(xgraph.get_layer_names()) == 1) assert(len(xgraph.get_output_names()) == 1) assert(len(xgraph.get_input_names()) == 1)
def _test_xgraph_insert( in_name: str, in2_name: str, conv_name: str, pool_name: str, add_name: str, conv2_name: str, ): expected_in_name = px.stringify(in_name) expected_in2_name = px.stringify(in2_name) expected_conv_name = px.stringify(conv_name) expected_pool_name = px.stringify(pool_name) expected_add_name = px.stringify(add_name) expected_conv2_name = px.stringify(conv2_name) in1 = px.ops.input(op_name=in_name, shape=[1, 2, 4, 4]) W = px.ops.constant( "W", np.array([[[[1, 2], [3, 4]]]], dtype=np.float32)) X_conv = px.ops.conv2d(op_name=conv_name, input_layer=in1, weights_layer=W, kernel_size=[2, 2]) # X_pool = px.ops.pool2d(op_name=pool_name, input_layer=X_conv, ) xgraph = XGraph() xgraph.add(in1) assert len(xgraph) == 1 assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 xgraph.add(X_conv) assert len(xgraph) == 2 assert len(xgraph.get_layer_names()) == 2 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 X_pool = XLayer( name=pool_name, type=["Pooling"], bottoms=[in_name], tops=[conv_name], targets=[], ) xgraph.insert(X_pool) assert len(xgraph) == 3 assert len(xgraph.get_layer_names()) == 3 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 xlayers = xgraph.get_layers() assert xlayers[0].name == expected_in_name assert xlayers[0].bottoms == [] assert xlayers[0].tops == [expected_pool_name] assert xlayers[1].name == expected_pool_name assert xlayers[1].bottoms == [expected_in_name] assert xlayers[1].tops == [expected_conv_name] assert xlayers[2].name == expected_conv_name assert xlayers[2].bottoms == [expected_pool_name] assert xlayers[2].tops == [] X_in2 = px.ops.input(op_name=in2_name, shape=[1, 2, 4, 4]) xgraph.add(X_in2) X_add = XLayer( name=add_name, type=["Eltwise"], bottoms=[conv_name, in2_name], tops=[], targets=[], ) xgraph.add(X_add) X_conv2 = XLayer( name=conv2_name, type=["Convolution"], bottoms=[in2_name], tops=[add_name], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], ) xgraph.insert(X_conv2) assert len(xgraph) == 6 assert len(xgraph.get_layer_names()) == 6 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 2 xlayers = xgraph.get_layers() assert xlayers[0].name == expected_in_name assert xlayers[0].bottoms == [] assert xlayers[0].tops == [expected_pool_name] assert xlayers[1].name == expected_pool_name assert xlayers[1].bottoms == [expected_in_name] assert xlayers[1].tops == [expected_conv_name] assert xlayers[2].name == expected_conv_name assert xlayers[2].bottoms == [expected_pool_name] assert xlayers[2].tops == [expected_add_name] assert xlayers[3].name == expected_in2_name assert xlayers[3].bottoms == [] assert xlayers[3].tops == [expected_conv2_name] assert xlayers[4].name == expected_conv2_name assert xlayers[4].bottoms == [expected_in2_name] assert xlayers[4].tops == [expected_add_name] assert xlayers[5].name == expected_add_name assert xlayers[5].bottoms == [ expected_conv_name, expected_conv2_name ] assert xlayers[5].tops == []
def test_xgraph_device_tagging(self): xgraph = XGraph() xgraph.add( XLayer(name="in1", type=["Input"], bottoms=[], tops=[], targets=[])) xgraph.add( XLayer(name="in2", type=["Input"], bottoms=[], tops=[], targets=[])) xgraph.add( XLayer( name="conv1", type=["Convolution"], bottoms=["in1"], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add( XLayer( name="add1", type=["Eltwise"], bottoms=["conv1", "in2"], tops=[], targets=[], )) xgraph.insert( XLayer( name="conv2", type=["Convolution"], bottoms=["in2"], tops=["add1"], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add( XLayer(name="pool1", type=["Pooling"], bottoms=["add1"], tops=[], targets=[])) xgraph = partition(xgraph, ["cpu"]) assert len(xgraph) == 6 xlayers = xgraph.get_layers() assert xgraph.get_layer_names() == [ "in1", "conv1", "in2", "conv2", "add1", "pool1", ] assert set(xlayers[0].targets) == set(["cpu", "qsim"]) assert set(xlayers[1].targets) == set(["cpu", "qsim", "test"]) assert set(xlayers[2].targets) == set(["cpu", "qsim"]) assert set(xlayers[3].targets) == set(["cpu", "qsim", "test"]) assert set(xlayers[4].targets) == set(["cpu", "qsim"]) assert set(xlayers[5].targets) == set(["cpu", "qsim", "test"]) xgraph.remove("conv1") assert len(xgraph) == 5 xlayers = xgraph.get_layers() assert xgraph.get_layer_names() == [ "in1", "in2", "conv2", "add1", "pool1" ] assert xlayers[3].type[0] == "Eltwise" assert xlayers[3].bottoms == ["in1", "conv2"] assert set(xlayers[0].targets) == set(["cpu", "qsim"]) assert set(xlayers[1].targets) == set(["cpu", "qsim"]) assert set(xlayers[2].targets) == set(["cpu", "qsim", "test"]) assert set(xlayers[3].targets) == set(["cpu", "qsim"]) assert set(xlayers[4].targets) == set(["cpu", "qsim", "test"])
def compile_opaque_func(xgraph: XGraph, target: str, in_tensor_names: List[str], out_tensor_names: List[str], build_dir: str, work_dir: str, cb_scheduled_xgraph: XGraph) -> None: """ Expose the compile function as an opaque function so it can be called from both Python and C++ Arguments --------- xgraph: XGraph the XGraph model target: str the target backend for executing this xgraph the target should be registered with a corresponding build function. in_tensor_names: List[str] the names of the input tensors (in the order that they will be provided at runtime) out_tensor_names: List[str] the names of the output tensors (in the order that they will be retrieved at runtime) build_dir: str the directory to be used for the final build files work_dir: str the directory to be used for temporary work files cb_scheduled_xgraph: XGraph return the scheduled XGraph """ in_tensor_names = [stringify(itn) for itn in in_tensor_names] out_tensor_names = [stringify(otn) for otn in out_tensor_names] # if work_dir is None: if not work_dir: work_dir = os.path.abspath(os.path.join(os.getcwd(), target + "_work")) if not build_dir: build_dir = os.path.abspath( os.path.join(os.getcwd(), target + "_build")) opt_xgraph = optimize(xgraph, target) c_xgraph = compile(opt_xgraph, target, work_dir=work_dir, build_dir=build_dir) # full_graph_input_names = xgraph.get_input_names() # Create scheduled XGraph # TODO: work_dir <-> build_dir scheduled_xgraph = schedule(c_xgraph, target, work_dir=build_dir) # Save and add to meta file model_file = os.path.join(build_dir, 'px_model') save(scheduled_xgraph, model_file) meta_file = os.path.join(build_dir, 'meta.json') if (not os.path.isfile(meta_file)): raise ValueError("Could not find meta file at: {}".format(meta_file)) with open(meta_file, 'r') as json_file: meta_d = json.load(json_file) meta_d['px_model'] = 'px_model.json' meta_d['px_params'] = 'px_model.h5' with open(meta_file, 'w') as f: json.dump(meta_d, f, indent=4, sort_keys=True) # Set callback cb_scheduled_xgraph.copy_from(scheduled_xgraph)
def _test_copy( in1_name: str, in2_name: str, conv1_name: str, add_name: str, conv2_name: str, pool_name: str, ): expected_in1_name = px.stringify(in1_name) expected_in2_name = px.stringify(in2_name) expected_conv1_name = px.stringify(conv1_name) expected_conv2_name = px.stringify(conv2_name) expected_pool_name = px.stringify(pool_name) expected_add_name = px.stringify(add_name) in1 = px.ops.input(op_name=in1_name, shape=[1, 2, 4, 4]) in2 = px.ops.input(op_name=in2_name, shape=[1, 2, 4, 4]) W = px.ops.constant( "W", np.array([[[[1, 2], [3, 4]]]], dtype=np.float32)) X_conv = px.ops.conv2d(op_name=conv1_name, input_layer=in1, weights_layer=W, kernel_size=[2, 2]) X_add = px.ops.eltwise(op_name=add_name, lhs_layer=X_conv, rhs_layer=in2) X_conv2 = px.ops.conv2d(op_name=conv2_name, input_layer=in2, weights_layer=W, kernel_size=[2, 2]) X_pool = px.ops.pool2d(op_name=pool_name, input_layer=X_add, pool_type="Avg", pool_size=[2, 2]) xgraph = XGraph() xgraph.add(in1) xgraph.add(in2) xgraph.add(X_conv) xgraph.add(X_add) xgraph.insert( XLayer( name=conv2_name, type=["Convolution"], bottoms=[in2_name], tops=[add_name], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add(X_pool) assert len(xgraph) == 6 assert xgraph.get_layer_names() == [ expected_in1_name, expected_conv1_name, expected_in2_name, expected_conv2_name, expected_add_name, expected_pool_name, ] xg_copy = xgraph.copy() assert len(xg_copy) == 6 assert xg_copy.get_layer_names() == [ expected_in1_name, expected_conv1_name, expected_in2_name, expected_conv2_name, expected_add_name, expected_pool_name, ] xgc_layers = xg_copy.get_layers() assert xgc_layers[1].type == ["Convolution"] assert xg_copy.get(conv1_name).type == ["Convolution"] xgc_layers[1].type = ["Convolution2"] assert xg_copy.get(conv1_name).type == ["Convolution2"] xgc_layers[1].type = ["Convolution"] assert xgc_layers[1].type == ["Convolution"] assert xg_copy.get(conv1_name).type == ["Convolution"] np.testing.assert_array_equal( xgc_layers[1].data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), ) np.testing.assert_array_equal(xgc_layers[1].data.biases, np.array([0.0], dtype=np.float32)) xgraph.get(conv1_name).data = ConvData( weights=xgc_layers[1].data.weights * 2, biases=xgc_layers[1].data.biases) np.testing.assert_array_equal( xgraph.get(conv1_name).data.weights, np.array([[[[2, 4], [6, 8]]]], dtype=np.float32), ) np.testing.assert_array_equal( xgc_layers[1].data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), ) np.testing.assert_array_equal(xgc_layers[1].data.biases, np.array([0.0], dtype=np.float32))
def _test_add_remove(in_name: str, conv_name: str): in1 = px.ops.input(op_name=in_name, shape=[1, 2, 4, 4]) W = px.ops.constant( "W", np.array([[[[1, 2], [3, 4]]]], dtype=np.float32)) X_conv = px.ops.conv2d(op_name=conv_name, input_layer=in1, weights_layer=W, kernel_size=[2, 2]) xgraph = XGraph() xgraph.add(in1) assert len(xgraph) == 1 assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 xgraph.add(X_conv) assert len(xgraph) == 2 assert len(xgraph.get_layer_names()) == 2 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 xgraph.remove(X_conv.name) assert len(xgraph) == 1 assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1
def test_visualize(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='in2', type=['Input'], bottoms=[], tops=[], targets=[] )) xgraph.add(XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='add1', type=['Eltwise'], bottoms=['conv1', 'in2'], tops=[], targets=[] )) xgraph.insert(XLayer( name='conv2', type=['Convolution'], bottoms=['in2'], tops=['add1'], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='conv3', type=['Convolution'], bottoms=['add1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] )) xgraph.add(XLayer( name='pool1', type=['Pooling'], bottoms=['add1'], tops=[], targets=[] )) xgraph.add(XLayer( name='add2', type=['Eltwise'], bottoms=['conv3', 'pool1'], tops=[], targets=[] )) assert len(xgraph) == 8 assert xgraph.get_layer_names() == \ ['in1', 'conv1', 'in2', 'conv2', 'add1', 'conv3', 'pool1', 'add2'] out_file = os.path.join(FILE_DIR, 'viz.png') xgraph.visualize(out_file) os.remove(out_file)
def test_visualize(self): xgraph = XGraph() xgraph.add( XLayer(name="in1", type=["Input"], bottoms=[], tops=[], targets=[])) xgraph.add( XLayer(name="in2", type=["Input"], bottoms=[], tops=[], targets=[])) xgraph.add( XLayer( name="conv1", type=["Convolution"], bottoms=["in1"], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add( XLayer( name="add1", type=["Eltwise"], bottoms=["conv1", "in2"], tops=[], targets=[], )) xgraph.insert( XLayer( name="conv2", type=["Convolution"], bottoms=["in2"], tops=["add1"], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add( XLayer( name="conv3", type=["Convolution"], bottoms=["add1"], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0.0, 1.0], dtype=np.float32), ), targets=[], )) xgraph.add( XLayer(name="pool1", type=["Pooling"], bottoms=["add1"], tops=[], targets=[])) xgraph.add( XLayer( name="add2", type=["Eltwise"], bottoms=["conv3", "pool1"], tops=[], targets=[], )) assert len(xgraph) == 8 assert xgraph.get_layer_names() == [ "in1", "conv1", "in2", "conv2", "add1", "conv3", "pool1", "add2", ] out_file = os.path.join(FILE_DIR, "viz.png") xgraph.visualize(out_file) os.remove(out_file)
def _test_add_get(in_name: str, conv_name: str): expected_in_name = px.stringify(in_name) expected_conv_name = px.stringify(conv_name) in1 = px.ops.input(op_name=expected_in_name, shape=[1, 2, 4, 4]) W = px.ops.constant( "W", np.array([[[[1, 2], [3, 4]]]], dtype=np.float32)) X_conv = px.ops.conv2d(op_name=conv_name, input_layer=in1, weights_layer=W, kernel_size=[2, 2]) xgraph = XGraph() xgraph.add(in1) assert len(xgraph) == 1 assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 assert isinstance(xgraph.get(in_name), XLayer) assert xgraph.get(in_name).bottoms == [] assert xgraph.get(in_name).tops == [] xgraph.add(X_conv) assert len(xgraph) == 2 assert xgraph.get_layer_names() == [ expected_in_name, expected_conv_name ] assert xgraph.get_output_names() == [expected_conv_name] assert xgraph.get_input_names() == [expected_in_name] assert xgraph.get(in_name).tops == [expected_conv_name] assert isinstance(xgraph.get(conv_name), XLayer) assert xgraph.get(conv_name).bottoms == [expected_in_name] assert xgraph.get(conv_name).tops == [] assert xgraph.get(conv_name).type == ["Convolution"] np.testing.assert_array_equal( xgraph.get(conv_name).data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), ) np.testing.assert_array_equal( xgraph.get(conv_name).data.biases, np.array([0.0], dtype=np.float32), ) xgraph.get(conv_name).data = ConvData( weights=xgraph.get(conv_name).data.weights * 2, biases=xgraph.get(conv_name).data.biases, ) np.testing.assert_array_equal( xgraph.get(conv_name).data.weights, np.array([[[[2, 4], [6, 8]]]], dtype=np.float32), ) xgraph.remove(X_conv.name) assert len(xgraph) == 1 assert in_name in xgraph assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1
def test_xgraph_add_get(self): xgraph = XGraph() xgraph.add(XLayer( name='in1', type=['Input'], bottoms=[], tops=[], targets=[] )) assert len(xgraph) == 1 assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1 assert isinstance(xgraph.get('in1'), XLayer) assert xgraph.get('in1').bottoms == [] assert xgraph.get('in1').tops == [] X_conv = XLayer( name='conv1', type=['Convolution'], bottoms=['in1'], tops=[], data=ConvData( weights=np.array([[[[1, 2], [3, 4]]]], dtype=np.float32), biases=np.array([0., 1.], dtype=np.float32) ), targets=[] ) xgraph.add(X_conv) assert len(xgraph) == 2 assert xgraph.get_layer_names() == ['in1', 'conv1'] assert xgraph.get_output_names() == ['conv1'] assert xgraph.get_input_names() == ['in1'] assert xgraph.get('in1').tops == ['conv1'] assert isinstance(xgraph.get('conv1'), XLayer) assert xgraph.get('conv1').bottoms == ['in1'] assert xgraph.get('conv1').tops == [] assert xgraph.get('conv1').type == ['Convolution'] np.testing.assert_array_equal( xgraph.get('conv1').data.weights, np.array([[[[1, 2], [3, 4]]]], dtype=np.float32) ) np.testing.assert_array_equal( xgraph.get('conv1').data.biases, np.array([0., 1.], dtype=np.float32) ) xgraph.get('conv1').data = ConvData( weights=xgraph.get('conv1').data.weights * 2, biases=xgraph.get('conv1').data.biases ) np.testing.assert_array_equal( xgraph.get('conv1').data.weights, np.array([[[[2, 4], [6, 8]]]], dtype=np.float32) ) xgraph.remove(X_conv.name) assert len(xgraph) == 1 assert 'in1' in xgraph assert len(xgraph.get_layer_names()) == 1 assert len(xgraph.get_output_names()) == 1 assert len(xgraph.get_input_names()) == 1
class OpaqueFunc(object): # TypeCode conversion functions # First: C++ -> Python # Second: Python -> C++ type_codes_ = { TypeCode.vInt: ( lambda arg_: IntVector(arg_.ints), lambda arg_: lpx.OpaqueValue(lpx.IntVector(arg_))), TypeCode.Str: ( lambda arg_: arg_.s, lambda arg_: lpx.OpaqueValue(arg_)), TypeCode.Byte: ( lambda arg_: arg_.bytes, lambda arg_: lpx.OpaqueValue(arg_)), TypeCode.vStr: ( lambda arg_: StrVector(arg_.strings), lambda arg_: lpx.OpaqueValue(lpx.StrVector(arg_))), TypeCode.StrContainer: ( lambda arg_: StrContainer.from_lib(arg_.str_c), lambda arg_: lpx.OpaqueValue(arg_._str_c)), TypeCode.BytesContainer: ( lambda arg_: BytesContainer.from_lib(arg_.bytes_c), lambda arg_: lpx.OpaqueValue(arg_._bytes_c)), TypeCode.XGraph: ( lambda arg_: XGraph._from_xgraph(arg_.xg), lambda arg_: lpx.OpaqueValue(arg_._xgraph)), TypeCode.XBuffer: ( lambda arg_: XBuffer.from_lib(arg_.xb), lambda arg_: lpx.OpaqueValue(arg_._xb)), TypeCode.vXBuffer: ( lambda arg_: [XBuffer.from_lib(e) for e in arg_.xbuffers], lambda arg_: lpx.OpaqueValue( lpx.XBufferHolderVector([xb._xb for xb in arg_]))), TypeCode.OpaqueFunc: ( lambda arg_: OpaqueFunc.from_lib(arg_.of), lambda arg_: lpx.OpaqueValue(arg_._of)) } def __init__(self, func: Callable = None, type_codes: List[TypeCode] = None) -> None: self._of = lpx.OpaqueFunc() if type_codes is None: type_codes = [] if func is not None: self.set_func(func, type_codes) @classmethod def from_lib(cls, _of: lpx.OpaqueFunc) -> 'OpaqueFunc': of = OpaqueFunc.__new__(cls) of._of = _of return of def set_func(self, func: Callable, type_codes: List[TypeCode]): # if type_codes is not None: for tc in type_codes: if tc not in OpaqueFunc.type_codes_: raise NotImplementedError("Function with argument of" " unsupported type: {} provided" .format(tc.name)) def opaque_func_wrapper(args): new_args = [] if type_codes is not None: args_type_codes = type_codes else: args_type_codes = [TypeCode(args[i].get_type_code_int()) for i in range(len(args))] for tc, arg_ in zip(args_type_codes, args): if tc not in OpaqueFunc.type_codes_: raise ValueError(f"Unsupported type code: {tc}") arg_ = OpaqueFunc.type_codes_[tc][0](arg_) new_args.append(arg_) func(*new_args) arg_type_codes_ = lpx.IntVector([tc.value for tc in type_codes]) self._of.set_func(opaque_func_wrapper, arg_type_codes_) def __call__(self, *args: Any) -> None: """ Call internal lib OpaqueFunc with provided args """ args_type_codes = self.get_arg_type_codes() if len(args) != len(args_type_codes): raise ValueError("Invalid number of arguments detected." " OpaqueFunc is expecting {} arguments" " but got: {}" .format(len(args_type_codes), len(args))) oa_v = [] for tc, arg_ in zip(args_type_codes, args): if tc not in OpaqueFunc.type_codes_: raise ValueError(f"Unsupported type code: {tc}") oa_v.append(OpaqueFunc.type_codes_[tc][1](arg_)) oa = lpx.OpaqueArgs(oa_v) self._of(oa) def get_arg_type_codes(self): return [TypeCode(i) for i in self._of.get_arg_type_codes()] def get_nb_type_codes(self): return len(self.get_arg_type_codes()) def __del__(self): pass