| 64 | get_device_count("gpu") > 0, reason="cuda does not support nchw int8" |
| 65 | ) |
| 66 | def test_conv_bias(): |
| 67 | inp_scale = np.float32(np.random.rand() + 1) |
| 68 | w_scale = np.float32(np.random.rand() + 1) |
| 69 | outp_scale = np.float32(np.random.rand() + 1) |
| 70 | inp_dtype = dtype.qint8(inp_scale) |
| 71 | w_dtype = dtype.qint8(w_scale) |
| 72 | b_dtype = dtype.qint32(inp_scale * w_scale) |
| 73 | out_dtype = dtype.qint8(outp_scale) |
| 74 | |
| 75 | def run( |
| 76 | N, |
| 77 | IC, |
| 78 | OC, |
| 79 | IH, |
| 80 | IW, |
| 81 | KH, |
| 82 | KW, |
| 83 | PH, |
| 84 | PW, |
| 85 | SH, |
| 86 | SW, |
| 87 | has_bias=True, |
| 88 | nonlinear_mode="identity", |
| 89 | ): |
| 90 | inp_v = np.random.normal(size=(N, IC, IH, IW)) |
| 91 | w_v = np.random.normal(size=(OC, IC, KH, KW)) |
| 92 | b_v = np.random.normal(size=(1, OC, 1, 1)) |
| 93 | inp_scale = dtype.get_scale(inp_dtype) |
| 94 | w_scale = dtype.get_scale(w_dtype) |
| 95 | b_scale = dtype.get_scale(b_dtype) |
| 96 | |
| 97 | inpv = dtype.convert_to_qint8(inp_v * inp_scale, inp_dtype) |
| 98 | wv = dtype.convert_to_qint8(w_v * w_scale, w_dtype) |
| 99 | bv = dtype.convert_to_qint32(b_v * b_scale, b_dtype) |
| 100 | |
| 101 | inp_int8 = mge.tensor(inpv, dtype=inp_dtype) |
| 102 | w_int8 = mge.Parameter(wv, dtype=w_dtype) |
| 103 | b_int32 = mge.Parameter(bv, dtype=b_dtype) |
| 104 | |
| 105 | inp_fp32 = inp_int8.astype("float32") |
| 106 | w_fp32 = w_int8.astype("float32") |
| 107 | b_fp32 = b_int32.astype("float32") |
| 108 | |
| 109 | def convert_to_nchw4(var): |
| 110 | var = F.reshape( |
| 111 | var, (var.shape[0], var.shape[1] // 4, 4, var.shape[2], var.shape[3]) |
| 112 | ) |
| 113 | var = F.transpose(var, (0, 1, 3, 4, 2)) |
| 114 | return var |
| 115 | |
| 116 | def run_conv2d(inp, w, b): |
| 117 | O = F.conv2d( |
| 118 | inp, w, b if has_bias else None, stride=(SH, SW), padding=(PH, PW), |
| 119 | ) |
| 120 | if nonlinear_mode == "relu": |
| 121 | return F.relu(O) |
| 122 | else: |
| 123 | return O |