def _common(cls, node, **kwargs): all_nodes = kwargs['all_nodes'] G = kwargs['G'] valid_name = kwargs['valid_name'] inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = cls._get_real_dim(x[2].shape) y = inputs[1] y_shape = cls._get_real_dim(y[2].shape) if cls.is_linear(y, x_shape, y_shape): filt_dim = FcFilterDim(y_shape[1], x_shape[0]) weights = np.transpose(cls.get_constant(y), [1, 0]) params = FcParameters(valid_name, filt=filt_dim, has_bias=False, in_dims_hint=SparseList([['c']]), out_dims_hint=SparseList([['c']]), constant_store=G.constant_store) params.weights = weights out_dims = params.get_output_size([Dim.unnamed(x_shape)]) else: params = MatMulOpParameters(valid_name) out_dims = params.get_output_size( [Dim.unnamed(x_shape), Dim.unnamed(y_shape)]) G.add_edge( NNEdge(from_node=y[0], to_node=params, from_idx=y[1], to_idx=1)) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) pout_dims = x[2].infer_mapping(out_dims[0].shape) all_nodes[node.output[0]] = (params, 0, pout_dims) return params
def test_fc(): filt = FcFilterDim(3, 3, 3, 1) params = FcParameters("test", filt=filt) weights_q = QType(16, 2, True) in_q = QType(16, 2, True) acc_q = QType(16, 4, True) calc_q = QType(16, 4, True) qrec = FilterQuantizationRecord(in_qs=[in_q], out_qs=[in_q], calc_q=calc_q, acc_q=acc_q, biases_q=None, weights_q=weights_q) weights = weights_q.quantize(np.full([3, 1, 3, 3], 1.0)) input_ = in_q.quantize(np.arange(9)).reshape([1, 3, 3]) in_dims = Dim.named(c=1, h=3, w=3).impose_order(['c', 'h', 'w']) out_dims = params.get_output_size([in_dims]) output_ = linear(params, in_dims, out_dims[0], input_, weights, None, qrec=qrec) output_ = in_q.dequantize(output_) assert np.array_equal(output_, [[[36]], [[36]], [[36]]])
def _common(cls, node, **kwargs): all_nodes = kwargs['all_nodes'] G = kwargs['G'] valid_name = kwargs['valid_name'] trans_a = node.attrs.get('transA', 0) trans_b = node.attrs.get('transB', 0) alpha = node.attrs.get('alpha', 1.0) beta = node.attrs.get('beta', 1.0) inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = x[2].shape y = inputs[1] y_shape = y[2].shape real_x_shape = cls._get_real_dim(x_shape) real_y_shape = cls._get_real_dim(y_shape) real_x_shape = [ real_x_shape[1], real_x_shape[0] ] if len(real_x_shape) == 2 and trans_a else real_x_shape real_y_shape = [ real_y_shape[1], real_y_shape[0] ] if len(real_y_shape) == 2 and trans_b else real_y_shape if not cls.is_linear(y, real_x_shape, real_y_shape) or trans_a: raise ValueError( "GEMM is only currently supported for operations that map onto a linear kernel" ) if len(inputs) > 2: has_bias = True biases = cls.get_constant(inputs[2]) else: biases = None has_bias = False filt_dim = FcFilterDim(real_y_shape[1], real_x_shape[0]) weights = cls.get_constant(y) * alpha if not trans_b: weights = np.transpose(weights, [1, 0]) params = FcParameters(valid_name, filt=filt_dim, has_bias=has_bias, in_dims_hint=SparseList([['c']]), out_dims_hint=SparseList([['c']]), constant_store=G.constant_store) params.weights = weights params.biases = biases * beta out_dims = params.get_output_size([Dim.unnamed(real_x_shape)]) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) if isinstance(x[2], ProvisionalDim): out_dim = x[2].infer_mapping(out_dims[0].shape) else: out_dim = out_dims[0] all_nodes[node.output[0]] = (params, 0, out_dim) return params
def _common(cls, node, **kwargs): all_nodes = kwargs['all_nodes'] G = kwargs['G'] valid_name = kwargs['valid_name'] inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = cls._get_real_dim(x[2].shape) y = inputs[1] y_shape = cls._get_real_dim(y[2].shape) if cls.is_linear(y, x_shape, y_shape): filt_dim = FcFilterDim(y_shape[1], x_shape[0]) weights = np.transpose(cls.get_constant(y), [1, 0]) weights_params = ConstantInputParameters(f'{valid_name}_weights', dims=Dim.unnamed( [y_shape[1], x_shape[0]]), value=weights) params = FcParameters(valid_name, filt=filt_dim, has_bias=True, # in_dims_hint=[ # ['c'], ['out_c', 'in_c'], ['out_c']], in_dims_hint=[ None, ['out_c', 'in_c'], ['out_c']], out_dims_hint=[['c']], constant_store=G.constant_store) out_dims = params.get_output_size([Dim.unnamed(x_shape)]) biases_params = ConstantInputParameters(f'{valid_name}_biases', dims=Dim.unnamed([y_shape[1]]), value=np.zeros((y_shape[1]), dtype=np.float32)) G.add_edge(NNEdge(from_node=weights_params, to_node=params, to_idx=1)) G.add_edge(NNEdge(from_node=biases_params, to_node=params, to_idx=2)) else: params = MatMulOpParameters(valid_name) out_dims = params.get_output_size( [Dim.unnamed(x_shape), Dim.unnamed(y_shape)]) G.add_edge( NNEdge(from_node=y[0], to_node=params, from_idx=y[1], to_idx=1)) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) pout_dims = x[2].infer_mapping(out_dims[0].shape) all_nodes[node.output[0]] = (params, 0, pout_dims) return params
def _handle(cls, node, quantized=False, **kwargs): all_nodes = kwargs['all_nodes'] G = kwargs['G'] valid_name = kwargs['valid_name'] inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = cls._get_real_dim(x[2].shape) y_idx = 3 if quantized else 1 y = inputs[y_idx] y_shape = cls._get_real_dim(y[2].shape) if quantized: qrecs = kwargs['qrecs'] x_zp = cls.get_constant(inputs[2]) x_scale = cls.get_constant(inputs[1]) if len(x_scale) > 1: raise NotImplementedError('QMatMul scales must be scalar') x_qtype = QType(dtype=x_zp.dtype, scale=x_scale, zero_point=x_zp) y_zp = cls.get_constant(inputs[5]) y_scale = cls.get_constant(inputs[4]) if len(y_scale) > 1: raise NotImplementedError('QMatMul scales must be scalar') y_qtype = QType(dtype=y_zp.dtype, scale=y_scale, zero_point=y_zp) o_zp = cls.get_constant(inputs[7]) o_scale = cls.get_constant(inputs[6]) o_qtype = QType(dtype=o_zp.dtype, scale=o_scale, zero_point=o_zp) else: o_qtype = None if cls.is_linear(y, x_shape, y_shape): filt_dim = FcFilterDim(y_shape[1], x_shape[0]) weights = np.transpose(cls.get_constant(y), [1, 0]) weights_params = ConstantInputParameters( f'{valid_name}_weights', dims=Dim.unnamed([y_shape[1], x_shape[0]]), value=weights) cls.record_constant_qrec(y, weights_params, **kwargs) params = FcParameters( valid_name, filt=filt_dim, has_bias=True, # in_dims_hint=[ # ['c'], ['out_c', 'in_c'], ['out_c']], in_dims_hint=[None, ['out_c', 'in_c'], ['out_c']], out_dims_hint=[['c']]) out_dims = params.get_output_size([Dim.unnamed(x_shape)]) biases_params = ConstantInputParameters( f'{valid_name}_biases', dims=Dim.unnamed([y_shape[1]]), value=np.zeros((y_shape[1]), dtype=np.float32)) G.add_edge( NNEdge(from_node=weights_params, to_node=params, to_idx=1)) G.add_edge( NNEdge(from_node=biases_params, to_node=params, to_idx=2)) if quantized: weights_params.qtype = y_qtype qrecs[NodeId(params)] = QRec.scaled( in_qs=[x_qtype, y_qtype, None], out_qs=[o_qtype], ) else: params = MatMulTransposedParameters(valid_name) trans_shape = [i for i in range(len(y_shape))] temp = trans_shape[-1] trans_shape[-1] = trans_shape[-2] trans_shape[-2] = temp trans2 = TransposeParameters(f'{valid_name}_tin2', transpose=tuple(trans_shape)) out_dims = params.get_output_size([ Dim.unnamed(x_shape), Dim.unnamed(y_shape[:-2] + y_shape[-2:][::-1]) ]) G.add_edge( NNEdge(from_node=y[0], to_node=trans2, from_idx=y[1], to_idx=0)) G.add_edge( NNEdge(from_node=trans2, to_node=params, from_idx=0, to_idx=1)) biases_params = ConstantInputParameters( f'{valid_name}_biases', dims=Dim.unnamed([out_dims[0].shape[1]]), value=np.zeros((out_dims[0].shape[1]), dtype=np.float32)) G.add_edge( NNEdge(from_node=biases_params, to_node=params, to_idx=2)) if quantized: qrecs[NodeId(trans2)] = QRec.scaled( in_qs=[y_qtype], out_qs=[y_qtype], ) qrecs[NodeId(params)] = QRec.scaled( in_qs=[x_qtype, y_qtype], out_qs=[o_qtype], ) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) pout_dims = x[2].infer_mapping(out_dims[0].shape) all_nodes[node.output[0]] = (params, 0, pout_dims, o_qtype) return params
def _common(cls, node, **kwargs): all_nodes = kwargs['all_nodes'] G = kwargs['G'] valid_name = kwargs['valid_name'] trans_a = node.attrs.get('transA', 0) trans_b = node.attrs.get('transB', 0) alpha = node.attrs.get('alpha', 1.0) beta = node.attrs.get('beta', 1.0) inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = x[2].shape y = inputs[1] y_shape = y[2].shape real_x_shape = cls._get_real_dim(x_shape) real_y_shape = cls._get_real_dim(y_shape) real_x_shape = [ real_x_shape[1], real_x_shape[0] ] if len(real_x_shape) == 2 and trans_a else real_x_shape real_y_shape = [ real_y_shape[1], real_y_shape[0] ] if len(real_y_shape) == 2 and trans_b else real_y_shape if not cls.is_linear(y, real_x_shape, real_y_shape) or trans_a: raise ValueError( "GEMM is only currently supported for operations that map onto a linear kernel" ) if len(inputs) > 2: biases = cls.get_constant(inputs[2]) else: biases = np.zeros([real_y_shape[1]], dtype=np.float32) filt_dim = FcFilterDim(real_y_shape[1], real_x_shape[0]) # always create new constants since they may be modified by this not and could be linked elsewhere weights = cls.get_constant(y) * alpha if not trans_b: weights = np.transpose(weights, [1, 0]) weights_params = ConstantInputParameters(f'{valid_name}_weights', dims=Dim.unnamed( weights.shape), value=weights) biases = biases * beta biases_params = ConstantInputParameters(f'{valid_name}_biases', dims=Dim.unnamed(biases.shape), value=biases) params = FcParameters( valid_name, filt=filt_dim, has_bias=True, # in_dims_hint=[['c']], in_dims_hint=[None, ['out_c', 'in_c'], ['out_c']], out_dims_hint=[['c']], constant_store=G.constant_store) G.add_edge(NNEdge(from_node=weights_params, to_node=params, to_idx=1)) G.add_edge(NNEdge(from_node=biases_params, to_node=params, to_idx=2)) out_dims = params.get_output_size([Dim.unnamed(real_x_shape)]) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) if isinstance(x[2], ProvisionalDim): out_dim = x[2].infer_mapping(out_dims[0].shape) else: out_dim = out_dims[0] all_nodes[node.output[0]] = (params, 0, out_dim) return params
def _common(cls, node, **kwargs): all_nodes = kwargs['all_nodes'] trans_a = node.attrs.get('transA', 0) trans_b = node.attrs.get('transB', 0) alpha = node.attrs.get('alpha', 1.0) beta = node.attrs.get('beta', 1.0) inputs = [all_nodes[inp] for inp in node.input] x = inputs[0] x_shape = x[2].shape y = inputs[1] y_shape = y[2].shape real_x_shape = cls._get_real_dim(x_shape) real_y_shape = cls._get_real_dim(y_shape) real_x_shape = [real_x_shape[1], real_x_shape[0]] if len( real_x_shape) == 2 and trans_a else real_x_shape real_y_shape = [real_y_shape[1], real_y_shape[0]] if len( real_y_shape) == 2 and trans_b else real_y_shape if not cls.is_linear(y, real_x_shape, real_y_shape) or trans_a: if alpha != 1.0 or beta != 1.0: raise NotImplementedError('Alpha and Beta not implemented on pure matmul GEMM') return cls._import_as_matmul(node, inputs, x, y, real_x_shape, real_y_shape, trans_a, trans_b, alpha, beta, **kwargs) G = kwargs['G'] valid_name = kwargs['valid_name'] if len(inputs) > 2: biases = cls.get_constant(inputs[2]) else: biases = np.zeros([real_y_shape[1]], dtype=np.float32) filt_dim = FcFilterDim(real_y_shape[1], real_x_shape[0]) # always create new constants since they may be modified by this not and could be linked elsewhere weights = cls.get_constant(y) * alpha if not trans_b: weights = np.transpose(weights, [1, 0]) weights_params = ConstantInputParameters( f'{valid_name}_weights', dims=Dim.unnamed(weights.shape), value=weights) if y[3]: if alpha == 1.0: cls.record_constant_qrec(y, weights_params, **kwargs) else: raise NotImplementedError("qtype on Gemm with alpha != 1.0") biases = biases * beta biases_params = ConstantInputParameters( f'{valid_name}_biases', dims=Dim.unnamed(biases.shape), value=biases) if len(inputs) > 2 and inputs[2][3]: if beta == 1.0: cls.record_constant_qrec(inputs[2], biases_params, **kwargs) else: raise NotImplementedError("qtype on Gemm with beta != 1.0") params = FcParameters(valid_name, filt=filt_dim, has_bias=True, # in_dims_hint=[['c']], in_dims_hint=[ None, ['out_c', 'in_c'], ['out_c']], out_dims_hint=[['c']]) G.add_edge(NNEdge(from_node=weights_params, to_node=params, to_idx=1)) G.add_edge(NNEdge(from_node=biases_params, to_node=params, to_idx=2)) out_dims = params.get_output_size([Dim.unnamed(real_x_shape)]) G.add_edge( NNEdge(from_node=x[0], to_node=params, from_idx=x[1], to_idx=0)) if isinstance(x[2], ProvisionalDim): out_dim = x[2].infer_mapping(out_dims[0].shape) else: out_dim = out_dims[0] all_nodes[node.output[0]] = (params, 0, out_dim, None) return params