Bias quantized with the same scale as the Convolution result

iviarcio: <p>Hey everyone. I’m building a new backend for Glow called NMP (from NeuroMorphic Processor). It is an embedded device to make inferences from convolutional neural networks. This device only works with quantized models (Int8 and Int16). It turns out that the external library that performs the convolution operations expects the Bias to be quantized on the same scale as the Convolution result (the same applies to FullyConnected operations). Any ideas on how can I specialize this type of quantization?</p>

iviarcio: <p>I inserted the following code in the NMPBackend module:</p>
<pre><code class="lang-auto">template &lt;typename T&gt; static void RescaleBias(Node &amp;node, Function *F) {
  auto res = dyn_cast&lt;T&gt;(&amp;node)-&gt;getResult();
  const TypeRef resTy = res.getType();
  auto bias = dyn_cast&lt;T&gt;(&amp;node)-&gt;getBias();
  const TypeRef biasTy = bias.getType();
  auto ElemTy = biasTy-&gt;getElementType();
  const TypeRef newTy = F-&gt;getParent()-&gt;uniqueType(
      ElemTy, biasTy-&gt;dims(), resTy-&gt;getScale(), resTy-&gt;getOffset());
  bias.setType(newTy);
}

Expected&lt;bool&gt;
NMPBackend::transformPostOptPipeline(Function *F,
                                     CompilationContext &amp;cctx) const {
  for (auto &amp;node : F-&gt;getNodes()) {
    switch (node.getKind()) {
    case Kinded::Kind::ConvolutionNodeKind:
      RescaleBias&lt;ConvolutionNode&gt;(node, F);
      break;
    case Kinded::Kind::FullyConnectedNodeKind:
      RescaleBias&lt;FullyConnectedNode&gt;(node, F);
      break;
    default:;
    }
    continue;
  }
  convertQuantizedConstants(F, cctx);
</code></pre>
<p>Dumping the graph and LIR, the type and quantization information is correct, but the data is not quantized correctly. Apparently, the <code>convertQuantizedConstants(F, cctx)</code> call has no effect. Any tips?</p>

jfix: <p>Hi <a class="mention" href="/u/iviarcio">@iviarcio</a>, the <code>NodeValue::setType()</code> call does not change the actual payload of a Constant node, assuming this is what you are expecting to happen.</p>
<p>What you need to do is something like</p>
<pre><code class="lang-auto">template &lt;typename T&gt; static void rescaleBias(T *node, Function *F) {
  auto *bias = dyn_cast&lt;Constant&gt;(node-&gt;getBias());
  CHECK(bias) &lt;&lt; "Expected bias would be Constant";
  Tensor floatBias = quantization::dequantizeTensor(bias-&gt;getPayload(), 
                                                    ElemKind::FloatTy);
  auto outTy = node-&gt;getResult().getType();
  Tensor newBias = quantization::quantizeTensor(floatBias, 
                                                {outTy-&gt;getScale(), outTy-&gt;getOffset()},
                                                outTy-&gt;getElementType());
  Constant *newConst = F-&gt;getParent()-&gt;createConstant(bias-&gt;getName().str() + "_converted",
                                                      std::move(newBias));
  bias-&gt;getOutput().replaceAllUsesOfWith(newConst-&gt;getOutput());
}
</code></pre>

iviarcio: <p>Thank you <a class="mention" href="/u/jfix">@jfix</a>. I had already detected this issue and had adjusted the payload by a factor which is the ratio between the before and after scale, but its solution is more suitable as it follows the glow patterns.</p>