def _create_conv2d_leaky_relu_nhwc_oihw( in_shape, w_shape, conv_padding, conv_strides, conv_dilation, kernel_layout="OIHW", target="DPUCZDX8G-zcu104", ) -> XGraph: kernel_w, kernel_h = w_shape[2], w_shape[3] W = np.random.randint(-10, 10, size=w_shape).astype(np.float32) # B = np.array([1., -1.], dtype=np.float32) x1 = px.ops.input("in1", shape=list(in_shape)) w1 = px.ops.constant("weight", W) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[kernel_w, kernel_h], strides=list(conv_strides), padding_hw=list(conv_padding), dilation=list(conv_dilation), data_layout="NHWC", ) lr1 = px.ops.leaky_relu("lr1", [conv1], alpha=0.1) net = [x1, conv1, lr1] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) return xgraph
def convert_pyxir(self, target): """Convert Relay expression to PyXIR XGraph""" xgraph = pyxir.frontend.tvm.from_relay(self.function, params=self.params, postprocessing=None) xgraph = pyxir.partition(xgraph, targets=[target]) return xgraph
def annotation(mod, params, target): """Annotate Relay expression for Vitis-AI DPU accelerators""" xgraph = pyxir.frontend.tvm.from_relay(mod, params, postprocessing=None) xgraph = pyxir.partition(xgraph, targets=[target]) layers = xgraph.get_layers() relay_ids = [ list(np.array(layer.attrs["relay_id"]).flatten()) for layer in layers if layer.target == target ] relay_ids_flatten = [item for sublist in relay_ids for item in sublist] mod = VitisAIAnnotationPass("vitis_ai", relay_ids_flatten)(mod) return mod
def _create_conv2d_pool2d_nhwc_oihw( in_shape, w_shape, conv_padding, conv_strides, conv_dilation, pool_type, pool_size, pool_padding=[0, 0], pool_strides=[1, 1], conv_groups=1, conv_invalid=False, kernel_layout="OIHW", target="DPUCZDX8G-zcu104", conv_name="conv1", pool_name="pool1", ) -> XGraph: kernel_w, kernel_h = w_shape[2], w_shape[3] W = np.random.randint(-10, 10, size=w_shape).astype(np.float32) # B = np.array([1., -1.], dtype=np.float32) x1 = px.ops.input("in1", shape=list(in_shape)) w1 = px.ops.constant("weight", W) conv1 = px.ops.conv2d( op_name=conv_name, input_layer=x1, weights_layer=w1, kernel_size=[kernel_w, kernel_h], strides=list(conv_strides), padding_hw=list(conv_padding), dilation=list(conv_dilation), groups=conv_groups, data_layout="NHWC", ) pool1 = px.ops.pool2d( op_name=pool_name, input_layer=conv1, pool_type=pool_type, pool_size=list(pool_size), padding=list(pool_padding), layout="NHWC", ) net = [x1, conv1, pool1] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) return xgraph
def annotation(mod, params, target): """Annotate Relay expression for Vitis-AI DPU accelerators""" # We need type information for supporting models that contain operations that don't # have a Relay to XLayer translation mod = relay.transform.InferType()(mod) xgraph = pyxir.frontend.tvm.from_relay(mod, params, postprocessing=None) xgraph = pyxir.partition(xgraph, targets=[target]) layers = xgraph.get_layers() relay_ids = [ list(np.array(layer.attrs["relay_id"]).flatten()) for layer in layers if layer.target == target ] relay_ids_flatten = [item for sublist in relay_ids for item in sublist] mod = VitisAIAnnotationPass("vitis_ai", relay_ids_flatten)(mod) return mod
def test_basic(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) x2 = px.ops.input("in2", shape=[1, 2, 2, 2]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], strides=[1, 1], padding_hw=[0, 0, 0, 0], dilation=[1, 1], groups=1, channels=2, data_layout="NCHW", kernel_layout="OIHW", ) pool = px.ops.pool2d( op_name="pool1", input_layer=conv, pool_type="Avg", pool_size=[2, 2], ) add = px.ops.eltwise("add1", pool, x2) net = [x1, x2, conv, pool, add] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 5 assert p_xgraph.get_subgraph_names() == ["xp0"] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Pooling"] assert p_xlayers[3].type[0] in ["Input"] assert p_xlayers[4].type[0] in ["Eltwise"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[3].target == "cpu" assert p_xlayers[4].target == "test" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp0" assert p_xlayers[2].subgraph == "xp0" assert p_xlayers[3].subgraph is None assert p_xlayers[4].subgraph == "xp0" subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1", "in2"] assert xp0.tops == [] assert xp0.shapes == [[-1, 2, 2, 2]] assert xp0.sizes == [8] assert len(xp0_xgraph) == 5 xp0_layers = xp0_xgraph.get_layers() assert xp0_layers[0].type[0] == "Input" assert xp0_layers[0].layer[0] == "conv1" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "Pooling" assert xp0_layers[3].type[0] == "Input" assert xp0_layers[4].type[0] == "Eltwise" assert xp0_layers[0].bottoms == [] assert xp0_layers[0].tops == ["conv1"] assert xp0_layers[1].bottoms == ["xinput0"] assert xp0_layers[1].tops == ["pool1"] assert xp0_layers[2].bottoms == ["conv1"] assert xp0_layers[2].tops == ["add1"]
def test_inception_like_block(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) x2 = px.ops.input("in2", shape=[1, 1, 4, 4]) concat1 = px.ops.concat("concat1", [x1, x2], axis=1) # 1, 2, 4, 4 w1 = px.ops.constant("weight", np.ones((4, 2, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=concat1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 4, 3, 3 pool1 = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Avg", pool_size=[2, 2], ) # 1, 4, 2, 2 w2 = px.ops.constant("weight2", np.ones((4, 2, 2, 2), dtype=np.float32)) conv2 = px.ops.conv2d( op_name="conv2", input_layer=concat1, weights_layer=w2, kernel_size=[2, 2], strides=[2, 2], ) # 1, 4, 2, 2 concat2 = px.ops.concat("concat2", [pool1, conv2], axis=1) # 1, 8, 2, 2 net = [x1, x2, concat1, conv1, pool1, conv2, concat2] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 7 p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "cpu" assert p_xlayers[2].target == "cpu" assert p_xlayers[3].target == "test" assert p_xlayers[4].target == "test" assert p_xlayers[5].target == "cpu" assert p_xlayers[6].target == "cpu" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph is None assert p_xlayers[2].subgraph is None assert p_xlayers[3].subgraph == "xp0" assert p_xlayers[4].subgraph == "xp0" assert p_xlayers[5].subgraph is None assert p_xlayers[6].subgraph is None subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["concat1"] assert xp0.tops == ["concat2"] assert xp0.shapes == [[-1, 4, 2, 2]] assert xp0.sizes == [16] assert len(xp0_xgraph) == 3 xp0_layers = xp0_xgraph.get_layers() assert xp0_layers[0].type[0] == "Input" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "Pooling"
def test_small(self): net = [ XLayer(name='in1', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv1'], layer=['in1'], targets=[]), XLayer(name='in2', type=['Input'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=[], tops=['dense1'], layer=['in2'], targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['in1'], tops=['pool1'], layer=['conv1'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]], 'kernel_size': [3, 3], 'strides': [1, 1], 'dilation': [1, 1], 'groups': 1, 'channels': [2, 2] }, targets=[]), XLayer(name='pool1', type=['Pooling'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['conv1'], tops=['dense1'], layer=['pool1'], attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]], 'kernel_size': [3, 3], 'strides': [1, 1], }, targets=[]), XLayer(name='dense1', type=['Dense'], shapes=[1, 20], sizes=[20], bottoms=['pool1', 'in2'], tops=[], data=ConvData(np.array([1, 1]), np.array([0, 0])), layer=['dense1'], targets=[]) ] xgraph = TestDPUContrib.xgraph_factory.build_from_xlayer(net) p_xgraph = partition(xgraph, ['dpuv2-zcu104']) dpu_xgraph = TestDPUContrib.target_registry\ .get_target_build_func('dpuv2-zcu104')(p_xgraph) assert len(dpu_xgraph) == 6 layers = dpu_xgraph.get_layers() assert layers[0].type[0] == 'Input' assert layers[1].type[0] == 'Transpose' assert layers[1].bottoms == ['in1'] assert layers[1].tops == ['xp0'] assert layers[2].type[0] == 'DPU' assert layers[2].bottoms == ['conv1_bottom_NCHW>NHWC'] assert layers[2].tops == ['pool1'] assert layers[2].shapes == [[1, 2, 2, 2]] assert layers[2].attrs['target'] == 'dpuv2-zcu104' assert layers[2].attrs['input_names'] == ['xinput0'] assert layers[2].attrs['output_names'] == ['pool1'] assert layers[2].attrs['input_layers']['xinput0'] == ['conv1'] assert layers[2].attrs['output_layers']['pool1'] == ['pool1'] assert layers[2].attrs['__top_tensors'] ==\ {'pool1': ['pool1_top_NHWC>NCHW']} assert layers[2].attrs['orig_top_tensors'] ==\ {'pool1': ['dense1']} assert layers[2].attrs['__bottom_tensors'] ==\ {'xinput0': ['conv1_bottom_NCHW>NHWC']} assert layers[2].attrs['orig_bottom_tensors'] ==\ {'xinput0': ['in1']} # Merged TupleGetItem and Transpose layer assert layers[3].type[0] == 'TupleGetItem' assert layers[3].name == 'pool1' assert layers[3].shapes == [1, 2, 2, 2] assert layers[3].bottoms == ['xp0'] assert layers[3].tops == ['dense1'] assert layers[3].attrs['transpose'] is True assert layers[4].type[0] == 'Input' assert layers[4].name == 'in2' assert layers[4].tops == ['dense1'] assert layers[5].type[0] == 'Dense' assert layers[5].name == 'dense1' assert layers[5].shapes == [1, 20] assert layers[5].bottoms == ['pool1', 'in2'] assert layers[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., 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'])
bn_handling=BatchNormHandling.MERGE_AND_QUANTIZE) # Finetune the model # . . . # Export to ONNX onnx_filename = 'dpuv2_resnet18.onnx' export_dpuv2_onnx(model, input_shape=IN_SIZE, input_t=inp, export_path=onnx_filename) # Load ONNX into PyXIR onnx_model = onnx.load(onnx_filename) xgraph = from_onnx(onnx_model) xgraph = pyxir.partition(xgraph, [target]) xgraph = pyxir.optimize(xgraph, target) work_dir = os.path.join(file_dir, f'{target}_quant_trained_resnet18_workdir') inputs = np.random.randn(*IN_SIZE) def inputs_func(iter): return {'inp.1': inputs} xgraph = pyxir.quantize(xgraph, target, inputs_func, work_dir=work_dir) pyxir.build(xgraph, target, work_dir=work_dir, build_dir=work_dir, runtime='cpu-np')
def test_inception_like_block(self): net = [ XLayer(name='in1', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['concat1'], layer=['in1'], targets=[]), XLayer(name='in2', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['concat1'], layer=['in2'], targets=[]), XLayer(name='concat1', type=['Concat'], shapes=[1, 2, 4, 4], sizes=[32], bottoms=['in1', 'in2'], tops=['conv1', 'conv2'], layer=['concat1'], attrs={'axis': 1}, targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[1, 4, 3, 3], sizes=[], bottoms=['concat1'], tops=['pool1'], layer=['conv1'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='pool1', type=['Pooling'], shapes=[1, 4, 2, 2], sizes=[], bottoms=['conv1'], tops=['concat2'], layer=['pool1'], attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='conv2', type=['Convolution'], shapes=[1, 4, 2, 2], sizes=[], bottoms=['concat1'], tops=['concat2'], layer=['conv2'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='concat2', type=['Concat'], shapes=[1, 8, 2, 2], sizes=[32], bottoms=['pool1', 'conv2'], tops=['dense1'], layer=['concat2'], attrs={'axis': 1}, targets=[]), XLayer(name='dense1', type=['Dense'], shapes=[1, 20], sizes=[20], bottoms=['concat2'], tops=[], layer=['dense1'], data=ConvData(np.array([1, 1]), np.array([0, 0])), targets=[]) ] xgraph = TestSubgraphBuildFunc.xgraph_factory.build_from_xlayer(net) p_xgraph = partition(xgraph, ['test']) dpu_xgraph = TestSubgraphBuildFunc.target_registry\ .get_target_build_func('test')(p_xgraph) layers = dpu_xgraph.get_layers() assert len(dpu_xgraph) == 7 assert layers[0].type[0] == 'Input' assert layers[0].name == 'in1' assert layers[0].shapes == [1, 1, 4, 4] assert layers[0].bottoms == [] assert layers[0].tops ==\ ['0_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC'] assert layers[0].target == 'cpu' assert layers[0].subgraph is None assert layers[1].type[0] == 'Transpose' assert layers[1].name ==\ '0_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC' assert layers[1].shapes == [1, 4, 4, 1] assert layers[1].bottoms == ['in1'] assert layers[1].tops == ['xp0'] assert layers[1].target == 'cpu' assert layers[1].subgraph is None assert layers[2].type[0] == 'Input' assert layers[2].name == 'in2' assert layers[2].shapes == [1, 1, 4, 4] assert layers[2].bottoms == [] assert layers[2].tops ==\ ['1_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC'] assert layers[2].target == 'cpu' assert layers[2].subgraph is None assert layers[3].type[0] == 'Transpose' assert layers[3].name ==\ '1_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC' assert layers[3].shapes == [1, 4, 4, 1] assert layers[3].bottoms == ['in2'] assert layers[3].tops == ['xp0'] assert layers[3].target == 'cpu' assert layers[3].subgraph is None assert layers[4].type[0] == 'TEST' assert layers[4].name == 'xp0' assert layers[4].shapes == [[1, 2, 2, 8]] assert layers[4].bottoms ==\ ['0_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC', '1_split_conv1_bottom_NCHW-NHWC_conv2_bottom_NCHW-NHWC'] assert layers[4].tops == ['concat2'] assert layers[4].target == 'cpu' assert layers[4].subgraph is None assert layers[4].tops == ['concat2'] assert layers[4].attrs['target'] == 'test' assert layers[4].attrs['input_names'] == ['xinput0', 'xinput1'] assert layers[4].attrs['output_names'] == ['concat2'] assert layers[4].attrs['input_layers']['xinput0'] == ['concat1'] assert layers[4].attrs['input_layers']['xinput1'] == ['concat1'] assert layers[4].attrs['output_layers']['concat2'] == ['concat2'] assert (layers[4].attrs['__bottom_tensors'] == { 'xinput0': ['0_split_conv1_bottom_NCHW-NHWC_conv2_bottom' '_NCHW-NHWC'], 'xinput1': ['1_split_conv1_bottom_NCHW-NHWC_conv2_bottom' '_NCHW-NHWC'] }) assert (layers[4].attrs['orig_bottom_tensors'] == { 'xinput0': ['in1'], 'xinput1': ['in2'] }) assert layers[4].attrs['__top_tensors'] ==\ {'concat2': ['merge_pool1_top_NHWC-NCHW_conv2_top_NHWC-NCHW']} assert layers[4].attrs['orig_top_tensors'] ==\ {'concat2': ['dense1']} assert layers[5].type[0] == 'TupleGetItem' assert layers[5].name == 'concat2' assert layers[5].shapes == [1, 8, 2, 2] assert layers[5].bottoms == ['xp0'] assert layers[5].tops == ['dense1'] # assert layers[6].type[0] == 'Transpose' # assert layers[6].name ==\ # 'merge_pool1_top_NHWC-NCHW_conv2_top_NHWC-NCHW' # assert layers[6].shapes == [1, 8, 2, 2] # assert layers[6].bottoms == ['concat2'] # assert layers[6].tops == ['dense1'] assert layers[6].type[0] == 'Dense' assert layers[6].name == 'dense1' assert layers[6].shapes == [1, 20] assert layers[6].bottoms == ['concat2'] assert layers[6].tops == []
def test_basic_diff_layout(self): net = [ XLayer(name='in1', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv1'], layer=['in1'], targets=[]), XLayer(name='in2', type=['Input'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=[], tops=['add1'], layer=['in2'], targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['in1'], tops=['pool1'], layer=['conv1'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='pool1', type=['Pooling'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['conv1'], tops=['add1'], layer=['pool1'], attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='add1', type=['Eltwise'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['pool1', 'in2'], tops=[], layer=['add1'], targets=[]) ] xgraph = TestSubgraphBuildFunc.xgraph_factory.build_from_xlayer(net) p_xgraph = partition(xgraph, ['test']) dpu_xgraph = TestSubgraphBuildFunc.target_registry\ .get_target_build_func('test')(p_xgraph) layers = dpu_xgraph.get_layers() # print(layers) assert (len(dpu_xgraph) == 6) assert (layers[0].type[0] == 'Input') assert (layers[0].name == 'in1') assert (layers[0].bottoms == []) assert (layers[0].tops == ['conv1_bottom_NCHW-NHWC']) assert (layers[1].type[0] == 'Transpose') assert (layers[1].name == 'conv1_bottom_NCHW-NHWC') assert (layers[1].bottoms == ['in1']) assert (layers[1].tops == ['xp0']) assert (layers[2].type[0] == 'TEST') assert (layers[2].bottoms == ['conv1_bottom_NCHW-NHWC']) assert (layers[2].tops == ['pool1']) assert (layers[2].attrs['target'] == 'test') assert (layers[2].attrs['input_names'] == ['xinput0']) assert (layers[2].attrs['output_names'] == ['pool1']) assert (layers[2].attrs['input_layers']['xinput0'] == ['conv1']) assert (layers[2].attrs['output_layers']['pool1'] == ['pool1']) assert (layers[2].attrs['__bottom_tensors'] == { 'xinput0': ['conv1_bottom_NCHW-NHWC'] }) assert (layers[2].attrs['orig_bottom_tensors'] == {'xinput0': ['in1']}) assert (layers[2].attrs['__top_tensors'] == { 'pool1': ['pool1_top_NHWC-NCHW'] }) assert (layers[2].attrs['orig_top_tensors'] == {'pool1': ['add1']}) assert (layers[3].type[0] == 'TupleGetItem') assert (layers[3].bottoms == ['xp0']) assert (layers[3].tops == ['add1']) assert layers[3].attrs['transpose'] is True assert layers[3].attrs['axes'] == [0, 3, 1, 2] # assert(layers[4].type[0] == 'Transpose') # assert(layers[4].name == 'pool1_top_NHWC-NCHW') # assert(layers[4].bottoms == ['pool1']) # assert(layers[4].tops == ['add1']) # assert layers[4].attrs['axes'] == [0, 3, 1, 2] assert layers[4].type[0] == 'Input' assert layers[4].name == 'in2' assert layers[4].bottoms == [] assert layers[4].tops == ['add1'] assert layers[5].type[0] == 'Eltwise' assert layers[5].name == 'add1' assert layers[5].bottoms == ['pool1', 'in2'] assert layers[5].tops == []
def test_multi_top_tensors(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 2, 3, 3 pool1 = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Avg", pool_size=[2, 2], ) # 1, 2, 2, 2 t1 = px.ops.transpose("t1", pool1, axes=[0, 2, 3, 1], internal=1) t2 = px.ops.transpose("t2", pool1, axes=[0, 2, 3, 1], internal=1) s1 = px.ops.sqrt("s1", [t1]) s2 = px.ops.sqrt("s2", [t2]) s3 = px.ops.sqrt("s3", [t2]) net = [x1, conv1, pool1, t1, t2, s1, s2, s3] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 8 assert p_xgraph.get_subgraph_names() == ["xp0"] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Pooling"] assert p_xlayers[3].type[0] in ["Transpose"] assert p_xlayers[4].type[0] in ["Sqrt"] assert p_xlayers[5].type[0] in ["Transpose"] assert p_xlayers[6].type[0] in ["Sqrt"] assert p_xlayers[7].type[0] in ["Sqrt"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[3].target == "cpu" assert p_xlayers[4].target == "cpu" assert p_xlayers[5].target == "cpu" assert p_xlayers[6].target == "cpu" assert p_xlayers[7].target == "cpu" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp0" assert p_xlayers[2].subgraph == "xp0" assert p_xlayers[3].subgraph is None assert p_xlayers[4].subgraph is None assert p_xlayers[5].subgraph is None assert p_xlayers[6].subgraph is None assert p_xlayers[7].subgraph is None subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1"] assert xp0.tops == ["t1", "t2"] assert xp0.shapes == [[-1, 2, 2, 2], [-1, 2, 2, 2]] assert xp0.sizes == [8, 8] assert len(xp0_xgraph) == 3 __bottom_tensors = xp0.attrs["__bottom_tensors"] orig_bottom_tensors = xp0.attrs["orig_bottom_tensors"] assert len(__bottom_tensors) == 1 assert "xinput0" in __bottom_tensors assert __bottom_tensors["xinput0"] == ["in1"] assert len(orig_bottom_tensors) == 1 assert "xinput0" in orig_bottom_tensors assert orig_bottom_tensors["xinput0"] == ["in1"] __top_tensors = xp0.attrs["__top_tensors"] orig_top_tensors = xp0.attrs["orig_top_tensors"] assert len(__top_tensors) == 1 assert "pool1" in __top_tensors assert __top_tensors["pool1"] == ["t1", "t2"] assert len(orig_top_tensors) == 1 assert "pool1" in orig_top_tensors assert orig_top_tensors["pool1"] == ["s1", "s2", "s3"]
def test_one_subgraph(self): W = np.reshape( np.array([[[1, 1], [0, 1]], [[3, 4], [-1, 0]]], dtype=np.float32), (2, 1, 2, 2)) B = np.array([1., -1.], dtype=np.float32) net = [ XLayer(name='in1', type=['Input'], shapes=[-1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv1'], layer=['in1'], targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[-1, 2, 3, 3], sizes=[18], bottoms=['in1'], tops=['pool1'], layer=['conv2d0'], data=ConvData(W, B), attrs={ 'data_layout': 'NCHW', 'kernel_layout': 'OIHW', 'shape': [1, 2, 3, 3], 'padding': [[0, 0], [0, 0], [0, 0], [0, 0]], 'strides': [1, 1], 'dilation': [1, 1], 'groups': 1 }, targets=[]), XLayer( name='pool1', type=['Pooling'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['conv1'], tops=['pool2'], layer=['pool1'], targets=[], attrs={ 'padding': [[0, 0], [0, 0], [0, 0], [0, 0]], 'strides': [1, 1], 'kernel_size': [2, 2], 'insize': [3, 3], # HW 'outsize': [2, 2], 'data_layout': 'NCHW', 'pool_type': 'Max' }), XLayer( name='pool2', type=['Pooling'], shapes=[1, 2, 1, 1], sizes=[2], bottoms=['pool1'], tops=[], layer=['pool2'], targets=[], attrs={ 'padding': [[0, 0], [0, 0], [0, 0], [0, 0]], 'strides': [1, 1], 'kernel_size': [2, 2], 'insize': [2, 2], # HW 'outsize': [1, 1], 'data_layout': 'NCHW', 'pool_type': 'Avg' }) ] xgraph = TestBaseSubgraphQuantizer.xgraph_factory\ .build_from_xlayer(net) p_xgraph = partition(xgraph, ['test']) assert len(p_xgraph.get_layer_names()) == 4 assert p_xgraph.get_subgraph_names() == ['xp0'] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ['Input'] assert p_xlayers[1].type[0] in ['Convolution'] assert p_xlayers[2].type[0] in ['Pooling'] assert p_xlayers[3].type[0] in ['Pooling'] inputs = np.reshape( np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], dtype=np.float32), (1, 1, 4, 4)) def inputs_func(iter): return {'in1': inputs} quantizer = BaseSubgraphQuantizerTest(xgraph=p_xgraph, inputs_func=inputs_func) quantizer.quantize() assert 'xp0' in quantizer.test_inputs assert 'xinput0' in quantizer.test_inputs['xp0'] expected = np.reshape( np.array([[[4, 4, 4], [4, 4, 4], [4, 4, 4]], [[5, 5, 5], [5, 5, 5], [5, 5, 5]]]), (1, 2, 3, 3)) np.testing.assert_array_equal(quantizer.test_inputs['xp0']['xinput0'], expected)
def _create_multi_output_conv2d_nhwc_oihw( in_shape, w_shape, conv_padding, conv_strides, conv_dilation, kernel_layout="OIHW", target="DPUCZDX8G-zcu104", out_names=["out1", "out2"], ) -> XGraph: kernel_w, kernel_h = w_shape[2], w_shape[3] W = np.random.randint(-100, 100, size=w_shape).astype(np.float32) # B = np.array([1., -1.], dtype=np.float32) out_ch = w_shape[kernel_layout.index("O")] x1 = px.ops.input("in1", shape=list(in_shape)) w1 = px.ops.constant("weight", W) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[kernel_w, kernel_h], strides=list(conv_strides), padding_hw=list(conv_padding), dilation=list(conv_dilation), data_layout="NHWC", ) r1 = px.ops.relu("r1", [conv1]) W2 = np.random.randint(-10, 10, size=(10, out_ch, 1, 1)).astype(np.float32) w2 = px.ops.constant("weight2", W2) conv2 = px.ops.conv2d( op_name=out_names[0], input_layer=r1, weights_layer=w2, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0], dilation=[1, 1], data_layout="NHWC", ) W3 = np.random.randint(-10, 10, size=(10, out_ch, 1, 1)).astype(np.float32) w3 = px.ops.constant("weight2", W3) conv3 = px.ops.conv2d( op_name="conv3", input_layer=r1, weights_layer=w3, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0], dilation=[1, 1], data_layout="NHWC", ) r3 = px.ops.relu(out_names[1], [conv3]) net = [x1, conv1, r1, conv2, conv3, r3] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) return xgraph
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 _create_resnetv1_block( in_shape, pool_size, pool_strides, w1_shape, w2_shape, w3_shape, w4_shape, c1_padding=[0, 0, 0, 0], c2_padding=[0, 0, 0, 0], c3_padding=[0, 0, 0, 0], c4_padding=[0, 0, 0, 0], c1_strides=[1, 1], c2_strides=[1, 1], c3_strides=[1, 1], c4_strides=[1, 1], c1_dilation=[1, 1], c2_dilation=[1, 1], c3_dilation=[1, 1], c4_dilation=[1, 1], kernel_layout="OIHW", target="DPUCZDX8G-zcu104", ) -> XGraph: x1 = px.ops.input("in1", shape=list(in_shape)) pool1 = px.ops.pool2d( op_name="pool1", input_layer=x1, pool_type="Max", pool_size=pool_size, padding=[0, 0], strides=pool_strides, layout="NHWC", ) W1 = np.random.randint(-10, 10, size=w1_shape).astype(np.float32) w1 = px.ops.constant("w1", W1) conv1 = px.ops.conv2d( op_name="conv1", input_layer=pool1, weights_layer=w1, kernel_size=[w1_shape[2], w1_shape[3]], strides=list(c1_strides), padding_hw=list(c1_padding), dilation=list(c1_dilation), groups=1, data_layout="NHWC", ) W2 = np.random.randint(-10, 10, size=w2_shape).astype(np.float32) w2 = px.ops.constant("w2", W2) conv2 = px.ops.conv2d( op_name="conv2", input_layer=pool1, weights_layer=w2, kernel_size=[w2_shape[2], w2_shape[3]], strides=list(c2_strides), padding_hw=list(c2_padding), dilation=list(c2_dilation), groups=1, data_layout="NHWC", ) W3 = np.random.randint(-10, 10, size=w3_shape).astype(np.float32) w3 = px.ops.constant("w3", W3) conv3 = px.ops.conv2d( op_name="conv3", input_layer=conv2, weights_layer=w3, kernel_size=[w3_shape[2], w3_shape[3]], strides=list(c3_strides), padding_hw=list(c3_padding), dilation=list(c3_dilation), groups=1, data_layout="NHWC", ) W4 = np.random.randint(-10, 10, size=w4_shape).astype(np.float32) w4 = px.ops.constant("w4", W4) conv4 = px.ops.conv2d( op_name="conv4", input_layer=conv3, weights_layer=w4, kernel_size=[w4_shape[2], w4_shape[3]], strides=list(c4_strides), padding_hw=list(c4_padding), dilation=list(c4_dilation), groups=1, data_layout="NHWC", ) add = px.ops.eltwise("add", conv1, conv4) net = [x1, pool1, conv1, conv2, conv3, conv4, add] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) return xgraph
def _create_scale_conv2d_nhwc_oihw( in_shape, w_shape, conv_padding, conv_strides, conv_dilation, conv_groups=1, kernel_layout="OIHW", target="DPUCZDX8G-zcu104", ) -> XGraph: kernel_w, kernel_h = w_shape[2], w_shape[3] in_ch = w_shape[0] Gamma = np.random.randint(0, 2, size=(in_ch,)) Beta = np.random.randint(0, 2, size=(in_ch,)) W = np.random.randint(-10, 10, size=w_shape).astype(np.float32) # B = np.array([1., -1.], dtype=np.float32) x1 = px.ops.input("in1", shape=list(in_shape)) w1 = px.ops.constant("weight", W) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[kernel_w, kernel_h], strides=list(conv_strides), padding_hw=list(conv_padding), dilation=list(conv_dilation), groups=conv_groups, data_layout="NHWC", ) pool1 = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Max", pool_size=[3, 3], padding=[0, 0], layout="NHWC", ) g1 = px.ops.constant("gamma", Gamma) b1 = px.ops.constant("beta", Beta) scale = px.ops.scale("scale1", pool1, g1, b1, axis=3) r1 = px.ops.relu("r1", [scale]) W2 = np.random.randint(-10, 10, size=(in_ch, in_ch, 1, 1)).astype(np.float32) w2 = px.ops.constant("weight2", W2) conv2 = px.ops.conv2d( op_name="conv2", input_layer=r1, weights_layer=w2, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0], dilation=[1, 1], groups=1, data_layout="NHWC", ) net = [x1, conv1, pool1, scale, r1, conv2] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) return xgraph
def test_two_partitions_interrupt(self): net = [ XLayer(name='in1', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv1'], layer=['in1'], targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['in1'], tops=['pool1', 'bn1'], layer=['conv1'], targets=[], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }), XLayer(name='pool1', type=['Pooling'], shapes=[1, 4, 3, 3], sizes=[36], bottoms=['conv1'], tops=['concat1'], layer=['pool1'], targets=[], attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }), XLayer(name='bn1', type=['BatchNorm'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['conv1'], tops=['concat1'], layer=['bn1'], data=BatchData(np.array([1, 1]), np.array([0, 0]), np.array([1, 1]), np.array([0, 0])), targets=[]), XLayer(name='concat1', type=['Concat'], shapes=[1, 6, 3, 3], sizes=[54], bottoms=['pool1', 'bn1'], tops=['conv2'], layer=['concat1'], targets=[]), XLayer(name='conv2', type=['Convolution'], shapes=[1, 10, 2, 2], sizes=[40], bottoms=['concat1'], tops=[], layer=['conv2'], targets=[], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }) ] xgraph = TestSubgraphBuildFunc.xgraph_factory\ .build_from_xlayer(net) p_xgraph = partition(xgraph, ['test_simple']) dpu_xgraph = TestSubgraphBuildFunc.target_registry\ .get_target_build_func('test_simple')(p_xgraph) layers = dpu_xgraph.get_layers() assert len(dpu_xgraph) == 7 assert layers[0].type[0] == 'Input' assert layers[0].bottoms == [] assert layers[0].tops == ['xp0'] assert layers[1].type[0] == 'TEST_SIMPLE' assert layers[1].shapes == [[1, 2, 3, 3], [1, 4, 3, 3]] assert layers[1].bottoms == ['in1'] assert layers[1].tops == ['conv1', 'pool1'] assert layers[1].attrs['input_names'] == ['xinput0'] assert set(layers[1].attrs['output_names']) == set(['pool1', 'conv1']) assert layers[1].attrs['target'] == 'test_simple' assert layers[1].attrs['__bottom_tensors'] == {'xinput0': ['in1']} assert layers[1].attrs['orig_bottom_tensors'] == {'xinput0': ['in1']} assert layers[1].attrs['__top_tensors'] == \ {'conv1': ['bn1'], 'pool1': ['concat1']} assert layers[1].attrs['orig_top_tensors'] == \ {'conv1': ['bn1'], 'pool1': ['concat1']} assert layers[2].type[0] == 'TupleGetItem' assert layers[2].name == 'pool1' assert layers[2].bottoms == ['xp0'] assert layers[2].shapes == [1, 4, 3, 3] assert layers[2].tops == ['concat1'] assert layers[2].attrs['index'] == 1 assert layers[3].type[0] == 'TupleGetItem' assert layers[3].name == 'conv1' assert layers[3].bottoms == ['xp0'] assert layers[3].shapes == [1, 2, 3, 3] assert layers[3].tops == ['bn1'] assert layers[3].attrs['index'] == 0 assert layers[4].type[0] == 'BatchNorm' assert layers[4].name == 'bn1' assert layers[4].bottoms == ['conv1'] assert layers[4].shapes == [1, 2, 3, 3] assert layers[4].tops == ['concat1'] assert layers[5].type[0] == 'Concat' assert layers[5].name == 'concat1' assert layers[5].bottoms == ['pool1', 'bn1'] assert layers[5].shapes == [1, 6, 3, 3] assert layers[5].tops == ['conv2'] assert layers[6].type[0] == 'Convolution' assert layers[6].name == 'conv2' assert layers[6].bottoms == ['concat1'] assert layers[6].shapes == [1, 10, 2, 2] assert layers[6].tops == []
def test_interrupt_partition_in_add_branch(self): x = px.ops.input("in1", shape=[1, 28, 28, 2028]) w1 = px.ops.constant("weight", np.ones((2048, 2048, 1, 1), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x, weights_layer=w1, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0, 0, 0], dilation=[1, 1], groups=1, channels=2048, data_layout="NHWC", kernel_layout="OIHW", ) r1 = px.ops.relu("r1", [conv1]) w2 = px.ops.constant("weight", np.ones((512, 2048, 1, 1), dtype=np.float32)) conv2 = px.ops.conv2d( op_name="conv2", input_layer=r1, weights_layer=w2, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0, 0, 0], dilation=[1, 1], groups=1, channels=512, data_layout="NHWC", kernel_layout="OIHW", ) sigm = px.ops.sigmoid("sigm", [conv2]) # Unsupported layer w3 = px.ops.constant("weight", np.ones((2048, 512, 1, 1), dtype=np.float32)) conv3 = px.ops.conv2d( op_name="conv3", input_layer=sigm, weights_layer=w3, kernel_size=[1, 1], strides=[1, 1], padding_hw=[0, 0, 0, 0], dilation=[1, 1], groups=1, channels=2048, data_layout="NHWC", kernel_layout="OIHW", ) # Although this layer is supported, it should not be in the partition add = px.ops.eltwise( "add", r1, conv3 ) # Although this layer is supported, it should not be in the partition net = [x, conv1, r1, conv2, sigm, conv3, add] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 7 assert p_xgraph.get_subgraph_names() == ["xp0"] p_xlayers = p_xgraph.get_layers() assert p_xgraph.get("in1").target == "cpu" assert p_xgraph.get("conv1").target == "test" assert p_xgraph.get("r1").target == "test" assert p_xgraph.get("conv2").target == "test" assert p_xgraph.get("sigm").target == "cpu" assert p_xgraph.get("conv3").target == "cpu" assert p_xgraph.get("add").target == "cpu" subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1"] assert xp0.tops == ["add", "sigm"] assert xp0.shapes == [[-1, 28, 28, 2048], [-1, 28, 28, 512]] assert xp0.sizes == [28 * 28 * 2048, 28 * 28 * 512] assert len(xp0_xgraph) == 4 xp0_layers = xp0_xgraph.get_layers() assert xp0_layers[0].type[0] == "Input" assert xp0_layers[0].layer[0] == "conv1" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "ReLU" assert xp0_layers[3].type[0] == "Convolution"
def test_two_partition_diff_layout(self): net = [ XLayer(name='in1', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv1'], layer=['in1'], targets=[]), XLayer(name='in2', type=['Input'], shapes=[1, 4, 4, 1], sizes=[16], bottoms=[], tops=['in2_transpose'], layer=['in2'], targets=[]), XLayer(name='in2_transpose', type=['Transpose'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=['in2'], tops=['conv2'], layer=['in2'], attrs={'axes': [0, 3, 1, 2]}, targets=[]), XLayer(name='conv1', type=['Convolution'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['in1'], tops=['pool1'], layer=['conv1'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='pool1', type=['Pooling'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['conv1'], tops=['concat1'], layer=['pool1'], attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='conv2', type=['Convolution'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['in2_transpose'], tops=['concat1'], layer=['conv2'], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [1, 1], [1, 1]] }, targets=[]), XLayer(name='concat1', type=['Concat'], shapes=[1, 4, 2, 2], sizes=[16], bottoms=['pool1', 'conv2'], tops=['concat1_transpose'], layer=['concat1'], attrs={'axis': 1}, targets=[]), XLayer(name='concat1_transpose', type=['Transpose'], shapes=[1, 2, 2, 4], sizes=[16], bottoms=['concat1'], tops=['dense1'], layer=['concat1'], attrs={'axes': [0, 2, 3, 1]}, targets=[]), XLayer(name='dense1', type=['Dense'], shapes=[1, 20], sizes=[], bottoms=['concat1_transpose'], tops=[], data=ConvData(np.array([1, 1]), np.array([0, 0])), layer=['dense1'], targets=[]) ] xgraph = TestSubgraphBuildFunc.xgraph_factory.build_from_xlayer(net) p_xgraph = partition(xgraph, ['test']) p_xlayers = p_xgraph.get_layers() dpu_xgraph = TestSubgraphBuildFunc.target_registry\ .get_target_build_func('test')(p_xgraph) layers = dpu_xgraph.get_layers() assert len(dpu_xgraph) == 6 assert layers[0].type[0] == 'Input' assert layers[0].name == 'in1' assert layers[0].shapes == [1, 1, 4, 4] assert layers[0].bottoms == [] assert layers[0].tops == ['conv1_bottom_NCHW-NHWC'] assert layers[0].target == 'cpu' assert layers[0].subgraph is None assert layers[1].type[0] == 'Transpose' assert layers[1].name == 'conv1_bottom_NCHW-NHWC' assert layers[1].shapes == [1, 4, 4, 1] assert layers[1].bottoms == ['in1'] assert layers[1].tops == ['xp2'] assert layers[1].target == 'cpu' assert layers[1].subgraph is None assert layers[2].type[0] == 'Input' assert layers[2].name == 'in2' assert layers[2].shapes == [1, 4, 4, 1] assert layers[2].bottoms == [] assert layers[2].tops == ['xp2'] assert layers[2].target == 'cpu' assert layers[2].subgraph is None assert layers[3].type[0] == 'TEST' assert layers[3].name == 'xp2' assert layers[3].shapes == [[1, 2, 2, 4]] assert layers[3].bottoms == ['conv1_bottom_NCHW-NHWC', 'in2'] assert layers[3].tops == ['concat1'] assert layers[3].target == 'cpu' assert layers[3].subgraph is None assert layers[3].attrs['target'] == 'test' assert layers[3].attrs['input_names'] == ['xinput0', 'xinput1'] assert layers[3].attrs['output_names'] == ['concat1'] assert layers[3].attrs['input_layers']['xinput0'] == ['conv1'] assert layers[3].attrs['input_layers']['xinput1'] == ['conv2'] assert layers[3].attrs['output_layers']['concat1'] == ['concat1'] assert (layers[3].attrs['__bottom_tensors'] == { 'xinput0': ['conv1_bottom_NCHW-NHWC'], 'xinput1': ['in2'] }) assert (layers[3].attrs['orig_bottom_tensors'] == { 'xinput0': ['in1'], 'xinput1': ['in2'] }) assert layers[3].attrs['__top_tensors'] == {'concat1': ['dense1']} assert layers[3].attrs['orig_top_tensors'] == {'concat1': ['dense1']} assert layers[4].type[0] == 'TupleGetItem' assert layers[4].name == 'concat1' assert layers[4].shapes == [1, 2, 2, 4] assert layers[4].bottoms == ['xp2'] assert layers[4].tops == ['dense1'] assert layers[4].target == 'cpu' assert layers[4].subgraph is None assert layers[5].type[0] == 'Dense' assert layers[5].name == 'dense1' assert layers[5].shapes == [1, 20] assert layers[5].bottoms == ['concat1'] assert layers[5].tops == [] assert layers[5].target == 'cpu' assert layers[5].subgraph is None
def test_complete_partition(self): x = px.ops.input("in1", shape=[1, 1, 4, 4]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv = px.ops.conv2d( op_name="conv1", input_layer=x, weights_layer=w1, kernel_size=[2, 2], ) pool = px.ops.pool2d( op_name="pool1", input_layer=conv, pool_type="Avg", pool_size=[2, 2], ) net = [x, conv, pool] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 3 assert p_xgraph.get_subgraph_names() == ["xp0"] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Pooling"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp0" assert p_xlayers[2].subgraph == "xp0" subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1"] assert xp0.tops == [] assert xp0.shapes == [[-1, 2, 2, 2]] assert xp0.sizes == [8] assert xp0.attrs["target"] == "test" assert xp0.attrs["__bottom_tensors"] == {"xinput0": ["in1"]} assert xp0.attrs["orig_bottom_tensors"] == {"xinput0": ["in1"]} assert xp0.attrs["__top_tensors"] == {"pool1": []} assert xp0.attrs["orig_top_tensors"] == {"pool1": []} assert len(xp0_xgraph) == 3 xp0_layers = xp0_xgraph.get_layers() assert xp0_layers[0].type[0] == "Input" assert xp0_layers[0].layer[0] == "conv1" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "Pooling" assert xp0_layers[0].bottoms == [] assert xp0_layers[0].tops == ["conv1"] assert xp0_layers[1].bottoms == ["xinput0"] assert xp0_layers[1].tops == ["pool1"] assert xp0_layers[2].bottoms == ["conv1"] assert xp0_layers[2].tops == []
def test_two_partitions_through_interruption(self): # A layer inside a residual type branch os not supported # Here: BatchNorm x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 2, 3, 3 pool = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Avg", pool_size=[2, 2], padding=[1, 1, 0, 0], ) # 1, 2, 3, 3 bn_mean = px.ops.constant("mean", np.ones((2, ), dtype=np.float32)) bn_var = px.ops.constant("var", np.ones((2, ), dtype=np.float32)) bn_gamma = px.ops.constant("gamma", np.ones((2, ), dtype=np.float32)) bn_beta = px.ops.constant("beta", np.ones((2, ), dtype=np.float32)) bn = px.ops.batch_norm( op_name="bn1", input_layer=conv1, mean_layer=bn_mean, variance_layer=bn_var, gamma_layer=bn_gamma, beta_layer=bn_beta, axis=1, ) # 1, 2, 3, 3 concat = px.ops.concat("concat1", [pool, bn], axis=1) # 1, 4, 3, 3 w2 = px.ops.constant("weight2", np.ones((6, 2, 2, 2), dtype=np.float32)) conv2 = px.ops.conv2d( op_name="conv2", input_layer=concat, weights_layer=w2, kernel_size=[2, 2], padding_hw=[1, 1, 0, 0], ) # 1, 6, 3, 3 net = [x1, conv1, pool, bn, concat, conv2] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 6 assert p_xgraph.get_subgraph_names() == ["xp0"] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Pooling"] assert p_xlayers[3].type[0] in ["BatchNorm"] assert p_xlayers[4].type[0] in ["Concat"] assert p_xlayers[5].type[0] in ["Convolution"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[3].target == "cpu" assert p_xlayers[4].target == "cpu" assert p_xlayers[5].target == "cpu" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp0" assert p_xlayers[2].subgraph == "xp0" assert p_xlayers[3].subgraph is None assert p_xlayers[4].subgraph is None assert p_xlayers[5].subgraph is None assert p_xlayers[3].name == "bn1" assert p_xlayers[3].bottoms == ["conv1"] assert p_xlayers[3].tops == ["concat1"] assert p_xlayers[4].name == "concat1" assert p_xlayers[4].bottoms == ["pool1", "bn1"] assert p_xlayers[4].tops == ["conv2"] subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1"] assert xp0.tops == ["bn1", "concat1"] assert xp0.shapes == [[-1, 2, 3, 3], [-1, 2, 3, 3]] assert xp0.sizes == [18, 18] assert xp0.attrs["target"] == "test" assert xp0.attrs["__bottom_tensors"] == {"xinput0": ["in1"]} assert xp0.attrs["orig_bottom_tensors"] == {"xinput0": ["in1"]} assert xp0.attrs["__top_tensors"] == { "conv1": ["bn1"], "pool1": ["concat1"] } assert xp0.attrs["orig_top_tensors"] == { "conv1": ["bn1"], "pool1": ["concat1"] } assert len(xp0_xgraph) == 3 xp0_layers = xp0_xgraph.get_layers() assert [X.name for X in xp0_xgraph.get_input_layers()] == ["xinput0"] # TODO: XGraph only recognizes output layers when they have no top # layers assert [X.name for X in xp0_xgraph.get_output_layers()] == ["pool1"] assert xp0_layers[0].type[0] == "Input" assert xp0_layers[0].layer[0] == "conv1" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "Pooling" assert xp0_layers[0].bottoms == [] assert xp0_layers[0].tops == ["conv1"] assert xp0_layers[1].bottoms == ["xinput0"] assert xp0_layers[1].tops == ["pool1"] assert xp0_layers[2].bottoms == ["conv1"] assert xp0_layers[2].tops == []
def test_multiple_partitions(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) x2 = px.ops.input("in2", shape=[1, 2, 2, 2]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 2, 3, 3 pool = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Avg", pool_size=[2, 2], ) # 1, 2, 2, 2 add = px.ops.eltwise("add1", pool, x2) # 1, 2, 2, 2 bn_mean = px.ops.constant("mean", np.ones((2, ), dtype=np.float32)) bn_var = px.ops.constant("var", np.ones((2, ), dtype=np.float32)) bn_gamma = px.ops.constant("gamma", np.ones((2, ), dtype=np.float32)) bn_beta = px.ops.constant("beta", np.ones((2, ), dtype=np.float32)) bn = px.ops.batch_norm( op_name="bn1", input_layer=add, mean_layer=bn_mean, variance_layer=bn_var, gamma_layer=bn_gamma, beta_layer=bn_beta, axis=1, ) # 1, 2, 3, 3 pool2 = px.ops.pool2d( op_name="pool2", input_layer=bn, pool_type="Avg", pool_size=[2, 2], padding=[0, 0, 1, 1], ) # 1, 2, 2, 2 net = [x1, x2, conv1, pool, add, bn, pool2] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 7 # ! Only xp0 because only one subgraph can exist for now (largest) assert set(p_xgraph.get_subgraph_names()) == set(["xp0"]) p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Pooling"] assert p_xlayers[3].type[0] in ["Input"] assert p_xlayers[4].type[0] in ["Eltwise"] assert p_xlayers[5].type[0] in ["BatchNorm"] assert p_xlayers[6].type[0] in ["Pooling"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[3].target == "cpu" assert p_xlayers[4].target == "test" assert p_xlayers[5].target == "cpu" # ! CPU because only one subgraph can exist for now (largest) assert p_xlayers[6].target == "cpu" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp0" assert p_xlayers[2].subgraph == "xp0" assert p_xlayers[3].subgraph is None assert p_xlayers[4].subgraph == "xp0" assert p_xlayers[5].subgraph is None assert p_xlayers[6].subgraph is None subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp0 = subgraphs[0] assert xp0.name == "xp0" xp0_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp0.subgraph_data) assert xp0.bottoms == ["in1", "in2"] assert xp0.tops == ["bn1"] assert xp0.shapes == [[-1, 2, 2, 2]] assert xp0.sizes == [8] assert len(xp0_xgraph) == 5 xp0_layers = xp0_xgraph.get_layers() assert xp0_layers[0].type[0] == "Input" assert xp0_layers[0].layer[0] == "conv1" assert xp0_layers[1].type[0] == "Convolution" assert xp0_layers[2].type[0] == "Pooling" assert xp0_layers[3].type[0] == "Input" assert xp0_layers[4].type[0] == "Eltwise" assert xp0_layers[0].bottoms == [] assert xp0_layers[0].tops == ["conv1"] assert xp0_layers[1].bottoms == ["xinput0"] assert xp0_layers[1].tops == ["pool1"] assert xp0_layers[2].bottoms == ["conv1"] assert xp0_layers[2].tops == ["add1"]
def test_conv_maxpool_subgraph(self): W = np.reshape( np.array([[[1, 2], [3, 0]], [[1, 1], [0, 1]]], dtype=np.float32), (2, 1, 2, 2)) B = np.array([0., 0.], dtype=np.float32) net = [ XLayer( name='in', type=['Input'], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=['conv2d0'], layer=['in'], targets=[] ), XLayer( name='conv2d0', type=['Convolution'], shapes=[1, 2, 3, 3], sizes=[18], bottoms=['in'], tops=[], layer=['conv2d0'], data=ConvData(W, B), attrs={ 'data_layout': 'NCHW', 'kernel_layout': 'OIHW', 'shape': [1, 2, 3, 3], 'padding': [[0, 0], [0, 0], [0, 0], [0, 0]], 'strides': [1, 1], 'dilation': [1, 1], 'groups': 1 }, targets=[] ), XLayer( name='max_pool2d0', type=['Pooling'], shapes=[1, 2, 2, 2], sizes=[8], bottoms=['conv2d0'], tops=[], layer=['max_pool2d0'], attrs={ 'kernel_size': [2, 2], 'insize': [3, 3], 'outsize': [2, 2], 'data_layout': 'NCHW', 'padding': [[0, 0], [0, 0], [0, 0], [0, 0]], 'strides': [1, 1], 'pool_type': 'Max' }, targets=[] ) ] xgraph = TestQuantSimPass.xgraph_factory.build_from_xlayer( net, name='testtest' ) p_xgraph = partition(xgraph, ['npu_test']) assert p_xgraph.get_layers()[0].target == 'cpu' assert p_xgraph.get_layers()[1].target == 'npu_test' assert p_xgraph.get_layers()[2].target == 'cpu' assert p_xgraph.get_layers()[0].subgraph is None assert p_xgraph.get_layers()[1].subgraph == 'xp0' assert p_xgraph.get_layers()[2].subgraph is None quant_sim_pass = XGraphQuantSimPass( fdir=FILE_PATH, name=xgraph.get_name() + '_qsim' ) qsim_xgraph = quant_sim_pass.execute(xgraph=p_xgraph, subgraphs_only=True) exec_graph = TestQuantSimPass.xf_exec_graph_factory.build_runtime( qsim_xgraph ) inpts = { 'in': np.reshape( np.array([ [10, 10, 0, 40], [50, 10, 0, 80], [30, 50, 10, 0], [10, 90, 30, 40]], dtype=np.float32 ), (1, 1, 4, 4)) } res = exec_graph.run(inpts) outpt = res[0] expected_outpt = np.array([[ [[182.28346, 189.5748], [342.6929, 342.6929]], [[109.37008, 123.95275], [167.70079, 87.49606]]]], dtype=np.float32) np.testing.assert_array_almost_equal(outpt, expected_outpt, decimal=4)
def test_multiple_partitions_largest_last(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) w1 = px.ops.constant("weight1", np.ones((2, 1, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 2, 3, 3 t1 = px.ops.transpose("t1", conv1, axes=[0, 2, 3, 1]) # 1, 3, 3, 2 w2 = px.ops.constant("weight2", np.ones((4, 2, 2, 2), dtype=np.float32)) conv2 = px.ops.conv2d( op_name="conv2", input_layer=t1, weights_layer=w2, kernel_size=[2, 2], padding_hw=[1, 0, 1, 0], data_layout="NHWC", ) # 1, 3, 3, 4 pool = px.ops.pool2d( op_name="pool1", input_layer=conv2, pool_type="Avg", pool_size=[2, 2], layout="NHWC", ) # 1, 2, 2, 4 net = [x1, conv1, t1, conv2, pool] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 5 # ! Only xp1 because only one subgraph can exist for now (largest) assert set(p_xgraph.get_subgraph_names()) == set(["xp1"]) p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].type[0] in ["Input"] assert p_xlayers[1].type[0] in ["Convolution"] assert p_xlayers[2].type[0] in ["Transpose"] assert p_xlayers[3].type[0] in ["Convolution"] assert p_xlayers[4].type[0] in ["Pooling"] assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "cpu" assert p_xlayers[2].target == "cpu" assert p_xlayers[3].target == "test" assert p_xlayers[4].target == "test" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph is None assert p_xlayers[2].subgraph is None assert p_xlayers[3].subgraph == "xp1" assert p_xlayers[4].subgraph == "xp1" subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp1 = subgraphs[0] assert xp1.name == "xp1" xp1_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp1.subgraph_data) assert xp1.bottoms == ["t1"] assert xp1.tops == [] assert xp1.shapes == [[-1, 2, 2, 4]] assert xp1.sizes == [16] assert len(xp1_xgraph) == 3 xp1_layers = xp1_xgraph.get_layers() assert xp1_layers[0].type[0] == "Input" assert xp1_layers[0].layer[0] == "conv2" assert xp1_layers[1].type[0] == "Convolution" assert xp1_layers[2].type[0] == "Pooling" assert xp1_layers[0].bottoms == [] assert xp1_layers[0].tops == ["conv2"] assert xp1_layers[1].bottoms == ["xinput0"] assert xp1_layers[1].tops == ["pool1"] assert xp1_layers[2].bottoms == ["conv2"] assert xp1_layers[2].tops == []
def test_small(self): net = [ XLayer( name="in1", type=["Input"], shapes=[1, 1, 4, 4], sizes=[16], bottoms=[], tops=["conv1"], layer=["in1"], targets=[], ), XLayer( name="in2", type=["Input"], shapes=[1, 2, 2, 2], sizes=[8], bottoms=[], tops=["dense1"], layer=["in2"], targets=[], ), XLayer( name="conv1", type=["Convolution"], shapes=[1, 2, 3, 3], sizes=[18], bottoms=["in1"], tops=["pool1"], layer=["conv1"], data=ConvData(np.array([1, 1]), np.array([0, 0])), attrs={ "data_layout": "NCHW", "padding": [[0, 0], [0, 0], [1, 1], [1, 1]], "kernel_size": [3, 3], "strides": [1, 1], "dilation": [1, 1], "groups": 1, "channels": [2, 2], }, targets=[], ), XLayer( name="pool1", type=["Pooling"], shapes=[1, 2, 2, 2], sizes=[8], bottoms=["conv1"], tops=["dense1"], layer=["pool1"], attrs={ "data_layout": "NCHW", "padding": [[0, 0], [0, 0], [1, 1], [1, 1]], "kernel_size": [3, 3], "strides": [1, 1], }, targets=[], ), XLayer( name="dense1", type=["Dense"], shapes=[1, 20], sizes=[20], bottoms=["pool1", "in2"], tops=[], data=ConvData(np.array([1, 1]), np.array([0, 0])), layer=["dense1"], targets=[], ), ] xgraph = TestDPUCZDX8G.xgraph_factory.build_from_xlayer(net) p_xgraph = partition(xgraph, ["dpuv2-zcu104"]) dpu_xgraph = TestDPUCZDX8G.target_registry.get_target_build_func( "dpuv2-zcu104")(p_xgraph) assert len(dpu_xgraph) == 6 layers = dpu_xgraph.get_layers() assert layers[0].type[0] == "Input" assert layers[1].type[0] == "Transpose" assert layers[1].bottoms == ["in1"] assert layers[1].tops == ["xp0"] assert layers[2].type[0] == "DPU" assert layers[2].bottoms == ["conv1_bottom_NCHW-NHWC"] assert layers[2].tops == ["pool1"] assert layers[2].shapes == [[1, 2, 2, 2]] assert layers[2].attrs["target"] == "dpuv2-zcu104" assert layers[2].attrs["input_names"] == ["xinput0"] assert layers[2].attrs["output_names"] == ["pool1"] assert layers[2].attrs["input_layers"]["xinput0"] == ["conv1"] assert layers[2].attrs["output_layers"]["pool1"] == ["pool1"] assert layers[2].attrs["__top_tensors"] == { "pool1": ["pool1_top_NHWC-NCHW"] } assert layers[2].attrs["orig_top_tensors"] == {"pool1": ["dense1"]} assert layers[2].attrs["__bottom_tensors"] == { "xinput0": ["conv1_bottom_NCHW-NHWC"] } assert layers[2].attrs["orig_bottom_tensors"] == {"xinput0": ["in1"]} # Merged TupleGetItem and Transpose layer assert layers[3].type[0] == "TupleGetItem" assert layers[3].name == "pool1" assert layers[3].shapes == [1, 2, 2, 2] assert layers[3].bottoms == ["xp0"] assert layers[3].tops == ["dense1"] assert layers[3].attrs["transpose"] is True assert layers[4].type[0] == "Input" assert layers[4].name == "in2" assert layers[4].tops == ["dense1"] assert layers[5].type[0] == "Dense" assert layers[5].name == "dense1" assert layers[5].shapes == [1, 20] assert layers[5].bottoms == ["pool1", "in2"] assert layers[5].tops == []
def test_two_partition_inputs(self): x1 = px.ops.input("in1", shape=[1, 1, 4, 4]) x2 = px.ops.input("in2", shape=[1, 1, 4, 4]) w1 = px.ops.constant("weight", np.ones((2, 1, 2, 2), dtype=np.float32)) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[2, 2], ) # 1, 2, 3, 3 pool = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type="Avg", pool_size=[3, 3], ) # 1, 2, 1, 1 w2 = px.ops.constant("weight2", np.ones((2, 1, 4, 4), dtype=np.float32)) conv2 = px.ops.conv2d( op_name="conv2", input_layer=x2, weights_layer=w2, kernel_size=[4, 4], strides=[1, 1], ) # 1, 2, 1, 1 add = px.ops.eltwise("add1", pool, conv2) reshape = px.ops.reshape("reshape1", add, [-1, 2]) wd = px.ops.constant("weight_dense", np.ones((20, 2), dtype=np.float32)) dense = px.ops.dense( op_name="dense1", input_layer=reshape, weights_layer=wd, units=20, ) net = [x1, x2, conv1, pool, conv2, add, reshape, dense] xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer(net) p_xgraph = px.partition(xgraph, ["test"]) assert len(p_xgraph.get_layer_names()) == 8 assert p_xgraph.get_subgraph_names() == ["xp2"] p_xlayers = p_xgraph.get_layers() assert p_xlayers[0].target == "cpu" assert p_xlayers[1].target == "test" assert p_xlayers[2].target == "test" assert p_xlayers[3].target == "cpu" assert p_xlayers[4].target == "test" assert p_xlayers[5].target == "test" assert p_xlayers[6].target == "cpu" assert p_xlayers[7].target == "cpu" assert p_xlayers[0].subgraph is None assert p_xlayers[1].subgraph == "xp2" assert p_xlayers[2].subgraph == "xp2" assert p_xlayers[3].subgraph is None assert p_xlayers[4].subgraph == "xp2" assert p_xlayers[5].subgraph == "xp2" assert p_xlayers[6].subgraph is None assert p_xlayers[7].subgraph is None subgraphs = TestXGraphPartitioner.xgraph_partitioner.get_subgraphs( p_xgraph) assert len(subgraphs) == 1 xp2 = subgraphs[0] assert xp2.name == "xp2" xp2_xgraph = TestXGraphPartitioner.xgraph_factory.build_from_xlayer( xp2.subgraph_data) assert xp2.bottoms == ["in1", "in2"] assert xp2.tops == ["reshape1"] assert xp2.shapes == [[-1, 2, 1, 1]] assert xp2.sizes == [2] assert len(xp2_xgraph) == 6 xp2_layers = xp2_xgraph.get_layers() assert xp2_layers[0].type[0] == "Input" assert xp2_layers[0].layer[0] == "conv1" assert xp2_layers[1].type[0] == "Convolution" assert xp2_layers[2].type[0] == "Pooling" assert xp2_layers[3].type[0] == "Input" assert xp2_layers[3].layer[0] == "conv2" assert xp2_layers[4].type[0] == "Convolution" assert xp2_layers[5].type[0] == "Eltwise" assert xp2_layers[0].bottoms == [] assert xp2_layers[0].tops == ["conv1"] assert xp2_layers[1].bottoms == ["xinput0"] assert xp2_layers[1].tops == ["pool1"] assert xp2_layers[2].bottoms == ["conv1"] assert xp2_layers[2].tops == ["add1"] assert xp2_layers[3].bottoms == [] assert xp2_layers[3].tops == ["conv2"] assert xp2_layers[4].bottoms == ["xinput1"] assert xp2_layers[4].tops == ["add1"] assert xp2_layers[5].bottoms == ["pool1", "conv2"] assert xp2_layers[5].tops == []
def conv2d_pool2d_nhwc_oihw_test( in_shape, w_shape, conv_padding, conv_strides, conv_dilation, pool_type, pool_size, pool_padding=[0, 0], pool_strides=[1, 1], conv_groups=1, conv_invalid=False, kernel_layout="OIHW", target="test-DPU", ): kernel_w, kernel_h = w_shape[2], w_shape[3] W = np.random.randint(-10, 10, size=w_shape).astype(np.float32) # B = np.array([1., -1.], dtype=np.float32) x1 = px.ops.input("in1", shape=list(in_shape)) w1 = px.ops.constant("weight", W) conv1 = px.ops.conv2d( op_name="conv1", input_layer=x1, weights_layer=w1, kernel_size=[kernel_w, kernel_h], strides=list(conv_strides), padding_hw=list(conv_padding), dilation=list(conv_dilation), groups=conv_groups, data_layout="NHWC", ) pool1 = px.ops.pool2d( op_name="pool1", input_layer=conv1, pool_type=pool_type, pool_size=list(pool_size), padding=list(pool_padding), layout="NHWC", ) net = [x1, conv1, pool1] xgraph = XGRAPH_FACTORY.build_from_xlayer(net) xgraph = px.partition(xgraph, [target]) def inputs_func(iter): inputs = np.ones(in_shape, dtype=np.float32) return {'in1': inputs} quantizer = DECENTQuantizer(xgraph, inputs_func, work_dir=FILE_PATH) q_xgraph = quantizer.quantize() assert len(q_xgraph) == 3 conv, pool = q_xgraph.get("conv1"), q_xgraph.get("pool1") if not conv_invalid: assert "vai_quant_weights" in conv.attrs assert "vai_quant_in" in conv.attrs assert "vai_quant_out" in conv.attrs assert "vai_quant" in conv.attrs assert "vai_quant_in" in pool.attrs assert "vai_quant_out" in pool.attrs assert "vai_quant" in pool.attrs remove_all_files_with_suffix(FILE_PATH, ".pb") remove_all_files_with_suffix(FILE_PATH, ".txt")
def prequantize_onnx_model(onnx_model, target, inputs_func, out_file, **kwargs): xgraph = _from_onnx(onnx_model) xgraph = px.partition(xgraph, [target]) xgraph = px.optimize(xgraph, target) q_xgraph = px.quantize(xgraph, target, inputs_func, **kwargs) # Move quant_info information from XGraph to ONNX model tensor_quant_info = {} for X in q_xgraph.get_layers(): if "vai_quant" in X.attrs and X.attrs["vai_quant"] != []: tensor_name = X.attrs['onnx_id'] if tensor_name in tensor_quant_info: raise NotImplementedError("Quantization for ONNX tensor: {}" " already provided. Merging of" " multiple tensor quantization info" " parameters not supported yet") tensor_quant_info[tensor_name] = { "vai_quant": X.attrs["vai_quant"] } for vai_quant_elem in X.attrs['vai_quant']: tensor_quant_info[tensor_name][vai_quant_elem] = \ X.attrs[vai_quant_elem] for node in onnx_model.graph.node: node_w = NodeWrapper(node) tensor_name = node_w.get_outputs()[0] if tensor_name in tensor_quant_info: node_w.add_attribute( 'vai_quant', list(tensor_quant_info[tensor_name]['vai_quant']), 'STRINGS' ) for vai_quant_elem in tensor_quant_info[tensor_name]['vai_quant']: node_w.add_attribute( vai_quant_elem, tensor_quant_info[tensor_name][vai_quant_elem], 'INTS' ) # q_output = q_xgraph.get_quantizer_output() # for qkey in q_output.keys(): # quant_file = q_output.get_q_file(qkey) # quant_info_file = q_output.get_q_info(qkey) # quant_orig_pb = q_output.get_orig_pb(qkey) # if not os.path.isfile(quant_info_file): # raise ValueError("quant file: {} for qkey: {} does not exist" # .format(quant_info_file, qkey)) # meta = onnx_model.metadata_props.add() # meta.key = "vitis_ai_quant--q_file--" + qkey # meta.value = str(quant_file) # meta = onnx_model.metadata_props.add() # meta.key = "vitis_ai_quant--q_info--" + qkey # meta.value = str(quant_info_file) # meta = onnx_model.metadata_props.add() # meta.key = "vitis_ai_quant--orig_pb--" + qkey # meta.value = str(quant_orig_pb) onnx.save(onnx_model, out_file)