def before(): x = relay.var("x", shape=(10, 20)) y = relay.add(x, relay.const(1, "float32")) z = relay.squeeze(y) u = relay.transpose(y, axes=[0, 1]) w = relay.left_shift(z, u) return relay.Function([x], w)
def quantize(data, shift_bits, target_bits=relay.const(7, dtype='int32')): """Quantize output of layer, to be consistent with source code @yx Question: should the shift_bits participating to network control flow? At mxnet quantization with truman's code, the bits number of max_v is converted to normal interger using function `asscalar()`. However, I cannot find the related function in relay. I am confused with the control flow logic in model network, whether the condition `shift_bits == -1` should join in model network or just left it in python code flow. By Longtao.Wang Parameters ---------- shift_bits: tvm.relay.Expr The shift_bits parameter is never used according to @yx's source code, which always be constant Expr(-1). """ max_v = relay.max(relay.abs(data)) min_v = relay.min(data) ln_max_v = relay.log(relay.cast(max_v, 'float32')) ln_2 = relay.log(relay.const(2.)) total_bits = relay.ceil(relay.divide(ln_max_v, ln_2)) # ceil( ln(max_v) / ln(2) ) shift_bits = relay.subtract(total_bits.astype('int32'), target_bits) shift_bits = relay.maximum(shift_bits, relay.const(0)) denominator = relay.left_shift(relay.const(1), relay.cast(shift_bits, 'int32')) out = relay.divide(data, denominator) # According to @yx's code, use divide operation instead of shift op for # possible negative number round. # out = relay.right_shift(data, shift_bits) out = relay.cast(relay.clip(out, a_min=-128, a_max=127), 'int8') return out, max_v, min_v, shift_bits
def create_graph(): input1 = relay.var("x1", shape=ifm_shape, dtype=dtype) input2 = relay.var("x2", shape=ifm2_shape, dtype=dtype) c1 = relay.left_shift(input1, input2) f = relay.Function([input1, input2], c1) mod = tvm.IRModule() mod["main"] = f return mod
def create_model(): ifm = relay.var("ifm", shape=ifm_shape, dtype=dtype) ifm2 = relay.var("ifm2", shape=ifm2_shape, dtype=dtype) c1 = relay.left_shift(ifm, ifm2) f = relay.Function([ifm, ifm2], c1) mod = tvm.IRModule() mod["main"] = f return mod
def expected(): x = relay.var("p", shape=(10, 20)) y = relay.add(x, relay.const(1, "float32")) z = relay.squeeze(y) u = relay.transpose(y, axes=[0, 1]) w = relay.left_shift(z, u) f1 = relay.Function([x], w) x = relay.var("x", shape=(10, 20)) y = relay.Call(f1, [x]) return relay.Function([x], y)
def approx_exp(x): x = relay.minimum(relay.maximum(x, C((- 88.0))), C(88.0)) x = (C(127.0) + (x * C(1.44269504))) xf = relay.floor(x) i = relay.cast(xf, 'int32') x = (x - xf) Y = (C(0.99992522) + (x * (C(0.69583354) + (x * (C(0.22606716) + (x * C(0.078024523))))))) exponent = relay.left_shift(i, relay.expr.const(23, 'int32')) exponent = relay.reinterpret(exponent, 'float32') return (exponent * Y)
def expected(): x = relay.var("p", shape=(10, 20)) y = relay.add(x, relay.const(1, "float32")) z = relay.squeeze(y) u = relay.transpose(y, axes=[0, 1]) w = relay.left_shift(z, u) f1 = relay.Function([x], w) f1 = f1.with_attr("Primitive", tvm.tir.IntImm("int32", 1)) x = relay.var("x", shape=(10, 20)) y = relay.Call(f1, [x]) return relay.Function([x], y)
def approx_exp(x): # An approximation derived from Opus, # https://github.com/xiph/opus/blob/c1c247/celt/mathops.h#L147-L165 x = relay.minimum(relay.maximum(x, C(-88.0)), C(88.0)) x = C(127.0) + x * C(1.44269504) xf = relay.floor(x) i = relay.cast(xf, "int32") x = x - xf Y = C(0.99992522) + x * (C(0.69583354) + x * (C(0.22606716) + x * C(0.078024523))) exponent = relay.left_shift(i, relay.expr.const(23, "int32")) exponent = relay.reinterpret(exponent, "float32") return exponent * Y
def generate_relay_counter_array(self, counter): """Generate relay symbolic uint64 counter array for Philox2x32 RNG. Generate a relay vector of 64-bits integers which encodes couples (counter, i) for i in range(n) counter must be a relay expression (e.g. a relay constant or variable). """ c = relay.cast(counter, "uint64") b = relay.op.transform.full(c, (self.n, ), "uint64") d = relay.left_shift(b, RELAY_UINT64_32) e = relay.arange(relay.const(self.n, "uint64"), dtype="uint64") return relay.bitwise_or(d, e)
def __impl_philox_2x_round(self, ctr, key): """Compute a round in Philox2x32. :param ctr: uint64 vector :param key: uint32 scalar :return: """ ctr_0 = relay.right_shift(ctr, RELAY_UINT64_32) ctr_1 = relay.bitwise_and(ctr, RELAY_UINT64_CLEAR_HIGH) # mul_hi_lo product = relay.multiply(RELAY_PHILOX_M2x32_0, ctr_0) key_64 = relay.cast(key, "uint64") ctr_1_xor_key = relay.bitwise_xor(ctr_1, key_64) ctr_1_xor_key_up = relay.left_shift(ctr_1_xor_key, RELAY_UINT64_32) return relay.bitwise_xor(product, ctr_1_xor_key_up)
def create_model(): ifm = relay.var("ifm", shape=ifm_shape, dtype=dtype) ifm2 = relay.var("ifm2", shape=ifm2_shape, dtype=dtype) c1 = relay.left_shift(ifm, ifm2) return tvm.IRModule.from_expr(relay.Function([ifm, ifm2], c1))