How to avoid `intimplicit` when `torch.jit.trace` a Model?

DavidG: <p>I am trying to convert a PyTorch model to CoreML but CoreML needs a traced model BUT does not support all the ops generated by <code>torch.jit.trace</code></p>
<p>For example, trying to <code>coremltools.converters.convert</code> a traced PyTorch model and I got an error:</p>
<p><code>PyTorch convert function for op 'intimplicit' not implemented</code></p>
<p>I am trying to convert a RVC model from <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git" rel="noopener nofollow ugc">github</a>.</p>
<p>I traced the model with <code>torch.jit.trace</code> and it fails. So I traced down the problematic part to the WN layer:</p>
<aside class="onebox githubblob" data-onebox-src="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/modules.py#L188">
  <header class="source">

      <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/modules.py#L188" target="_blank" rel="noopener nofollow ugc">github.com</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/modules.py#L188" target="_blank" rel="noopener nofollow ugc">RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/modules.py#L188</a></h4>



    <pre class="onebox"><code class="lang-py">
      <ol class="start lines" start="178" style="counter-reset: li-counter 177 ;">
          <li>        # last one is not necessary
</li>
          <li>        if i &lt; n_layers - 1:
</li>
          <li>            res_skip_channels = 2 * hidden_channels
</li>
          <li>        else:
</li>
          <li>            res_skip_channels = hidden_channels
</li>
          <li>
</li>
          <li>        res_skip_layer = torch.nn.Conv1d(hidden_channels, res_skip_channels, 1)
</li>
          <li>        res_skip_layer = torch.nn.utils.weight_norm(res_skip_layer, name="weight")
</li>
          <li>        self.res_skip_layers.append(res_skip_layer)
</li>
          <li>
</li>
          <li class="selected">def forward(
</li>
          <li>    self, x: torch.Tensor, x_mask: torch.Tensor, g: Optional[torch.Tensor] = None
</li>
          <li>):
</li>
          <li>    output = torch.zeros_like(x)
</li>
          <li>    n_channels_tensor = torch.IntTensor([self.hidden_channels])
</li>
          <li>
</li>
          <li>    if g is not None:
</li>
          <li>        g = self.cond_layer(g)
</li>
          <li>
</li>
          <li>    for i, (in_layer, res_skip_layer) in enumerate(
</li>
          <li>        zip(self.in_layers, self.res_skip_layers)
</li>
      </ol>
    </code></pre>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<pre><code class="lang-auto">import torch
import coremltools as ct
from infer.lib.infer_pack.modules import WN

model = WN(192, 5, dilation_rate=1, n_layers=16, gin_channels=256, p_dropout=0)
model.remove_weight_norm()
model.eval()

test_x = torch.rand(1, 192, 200)
test_x_mask = torch.rand(1, 1, 200)
test_g = torch.rand(1, 256, 1)

traced_model = torch.jit.trace(model, (test_x, test_x_mask, test_g), check_trace = True)

x = ct.TensorType(name='x', shape=test_x.shape)
x_mask = ct.TensorType(name='x_mask', shape=test_x_mask.shape)
g = ct.TensorType(name='g', shape=test_g.shape)

mlmodel = ct.converters.convert(traced_model, inputs=[x, x_mask, g])
</code></pre>
<p>I got an error <code>RuntimeError: PyTorch convert function for op 'intimplicit' not implemented.</code></p>
<p>How could I modify the <code>WN::forward</code> so it does not generate an <code>intimplicit</code> operator ?</p>
<p>Thanks</p>
<p>David</p>

DavidG: <p>I finally found the source of this issue.</p>
<p>Model is calling a function that has <code>@torch.jit.script</code> decorator :</p><aside class="onebox githubblob" data-onebox-src="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/commons.py#L108">
  <header class="source">

      <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/commons.py#L108" target="_blank" rel="noopener nofollow ugc">github.com</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/commons.py#L108" target="_blank" rel="noopener nofollow ugc">RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/infer/lib/infer_pack/commons.py#L108</a></h4>



    <pre class="onebox"><code class="lang-py">
      <ol class="start lines" start="98" style="counter-reset: li-counter 97 ;">
          <li>    signal = get_timing_signal_1d(length, channels, min_timescale, max_timescale)
</li>
          <li>    return torch.cat([x, signal.to(dtype=x.dtype, device=x.device)], axis)
</li>
          <li>
</li>
          <li>
</li>
          <li>def subsequent_mask(length):
</li>
          <li>    mask = torch.tril(torch.ones(length, length)).unsqueeze(0).unsqueeze(0)
</li>
          <li>    return mask
</li>
          <li>
</li>
          <li>
</li>
          <li>@torch.jit.script
</li>
          <li class="selected">def fused_add_tanh_sigmoid_multiply(input_a, input_b, n_channels):
</li>
          <li>    n_channels_int = n_channels[0]
</li>
          <li>    in_act = input_a + input_b
</li>
          <li>    t_act = torch.tanh(in_act[:, :n_channels_int, :])
</li>
          <li>    s_act = torch.sigmoid(in_act[:, n_channels_int:, :])
</li>
          <li>    acts = t_act * s_act
</li>
          <li>    return acts
</li>
          <li>
</li>
          <li>
</li>
          <li># def convert_pad_shape(pad_shape):
</li>
          <li>#     l = pad_shape[::-1]
</li>
      </ol>
    </code></pre>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>Removing this decorator, <code>torch.jit.trace</code> no longer add a <code>intimplicit</code> operator in the trace and CoreML tools could succesfully convert the model.</p>