ONNX: deploying a trained model in a C++ project

abweiss: <p>I expect that most people are using ONNX to transfer trained models from Pytorch to Caffe2 because they want to deploy their model as part of a C/C++ project.  However, there are no examples which show how to do this from beginning to end.</p>
<p>From the Pytorch documentation <a href="http://pytorch.org/docs/master/onnx.html" rel="nofollow noopener">here</a>, I understand how to convert a Pytorch model to ONNX format using <code>torch.onnx.export</code>, and also how to load that file into Caffe2 using <code>onnx.load</code>  + <code>onnx_caffe2.backend</code>… but  that’s just the python side of things.</p>
<p>I also understand something about loading pretrained Caffe2 models into a C++ project from .pb files as described in the Caffe2 C++ tutorials <a href="https://github.com/leonardvandriel/caffe2_cpp_tutorial#loading-pre-trained-models" rel="nofollow noopener">here</a>.  (Click on the <a href="https://github.com/leonardvandriel/caffe2_cpp_tutorial/blob/master/src/caffe2/binaries/pretrained.cc" rel="nofollow noopener">pretrained.cc</a> link.)</p>
<p>What I’m missing are the steps in between.  How do I take the output from <code>onnx_caffe2.backend</code> and create the .pb files found in the Caffe2 C++ tutorials?  Maybe these steps are obvious to a seasoned Caffe2 user, but this is my first exposure.  A step-by-step recipe would probably help a lot of Pytorch users.</p>

abweiss: <p>Does anyone know how to do this?  It seems like there was a lot of fanfare around ONNX, but not much support.</p>

houseroad: <p>Actually, with ONNX-Caffe2 package, you can easily turn an ONNX model to a Caffe2 model, then dump it into pb files.</p>
<p>Here is an example:</p>
<pre><code>import onnx
from onnx_caffe2.backend import Caffe2Backend

onnx_proto_file = "/onnx.proto"
torch.onnx.export(G, x, onnx_proto_file, verbose=True)
onnx_model = onnx.load(onnx_proto_file)
init_net, predict_net = Caffe2Backend.onnx_graph_to_caffe2_net(onnx_model.graph)
with open("onnx-init.pb", "wb") as f:
    f.write(init_net.SerializeToString())
with open("onnx-init.pbtxt", "w") as f:
    f.write(str(init_net))
with open(, "onnx-predict.pb", "wb") as f:
    f.write(predict_net.SerializeToString())
with open("onnx-predict.pbtxt", "w") as f:
    f.write(str(predict_net))</code></pre>

abweiss: <p>This is really great!  Thank you!</p>

hmimyou: <p>I think this <code>convert-onnx-to-caffe2</code> tool is what you are looking for: <a href="https://github.com/onnx/tutorials/blob/master/tutorials/OnnxCaffe2Import.ipynb" rel="nofollow noopener">https://github.com/onnx/tutorials/blob/master/tutorials/OnnxCaffe2Import.ipynb</a></p>

greed2411: <p>for future reference, one could look at these two advanced tutorials from the documentation:</p>
<ul>
<li><a href="https://pytorch.org/tutorials/advanced/super_resolution_with_caffe2.html" rel="nofollow noopener">convert pytorch to caffe2 using onnx</a></li>
<li><a href="https://pytorch.org/tutorials/advanced/cpp_extension.html" rel="nofollow noopener">custom C++ and CUDA extnesions</a></li>
</ul>

SPark9625: <p>I know this thread is now quite old, but did this work out <a class="mention" href="/u/abweiss">@abweiss</a>? Were you able to import it from caffe2 c++??</p>

jinfagang: <p>I think inference using onnxruntime is the ultimate solution instead…</p>

bfortuner: <p>Jin, could you elaborate? What is the 1. Current best option for deploying python trained models to a high performance c++ runtime (ideally supporting accelerators). 2. What is the option the pytorch team will recommend in the future (6-12 months)? I.e. where are we now? Where will we be in 6-12 months? Will onnx be replaced by libtorch?</p>

jinfagang: <p>Sorry for the late.</p>
<ol>
<li>
<p>I think currently the best way deploy python trained model depends on your target platform. If you wanna using GPU, fastest way is TensorRT, if you got a CPU, using some QNNPACK instead;</p>
</li>
<li>
<p>Pytorch team should encourage us using exporting to onnx for the deployment.</p>
</li>
</ol>

Marat: <p><a class="mention" href="/u/houseroad">@houseroad</a> Thank you! But how can I then import pb files into TensorRT? (I am asking because TensorRT has poor support of ONNX)</p>

amoakoRadjwan: <p>Hello everyone,<br>
I must confess I am a total newbie to pytorch framework and neural networks in general. I have been doing some reading and practice for about 2 months now. I am working on my thesis and I need to implement some classification at some point. I currently have a pretrained model in caffe and would like to convert it to c++ version of pytorch since I am a bit comfortable with pytorch now.</p>
<p>I would be glad if someone could direct me to a reading resource/library/tutorial that does this: caffe2–&gt;C++ torch. Most of what I have found is loading from caffe to pytorch in python not c++.</p>
<p>secondly, should I succeed in the convertion will the new model in torch still be a trained model or I woud I have to retain.<br>
I’ll be glad if someone could give me a prompt response as I am running out of time. Thanks in advance. <a class="mention" href="/u/jinfagang">@jinfagang</a> <a class="mention" href="/u/houseroad">@houseroad</a></p>

jspisak: <p>Hi Folks,<br>
A few comments and pointers. Caffe2 is unsupported at this point so, if you are going from PyTorch to ONNX, you can use the exporter directly (which is well supported by MSFT). A tutorial you can use is here: <a href="https://pytorch.org/tutorials/advanced/super_resolution_with_onnxruntime.html">https://pytorch.org/tutorials/advanced/super_resolution_with_onnxruntime.html</a></p>
<p>For TensorRT, with the improvements in the ONNX exporter, the experience should be better now. We can ping Nvidia folks if there are any issues: <a href="https://github.com/onnx/onnx-tensorrt">https://github.com/onnx/onnx-tensorrt</a></p>
<p>Generally speaking, for backend performance libraries (relating to the QNNPACK comment above), the following is guidance depending on the target platform:</p>
<p>Server CPU (x86) - MKL/DNN and FBGEMM(8bit integer quantized)</p>
<p>ARM/Neon CPU - QNNPACK (8b integer quantized, ready today) and XNNPACK (current WIP for integration)</p>
<p>Hope this helps! Happy NY!!</p>

jinfagang: <p>what XNNPack btw? Xlinx board?</p>

srohit0: <p>One can use simpler approach with <a href="https://github.com/ai-techsystems/deepC/" rel="nofollow noopener">deepC compiler</a> and convert exported onnx model to c++.</p>
<p>Check out simple example at <a href="https://github.com/ai-techsystems/deepC/blob/master/test/compiler/mnist/" rel="nofollow noopener">deepC compiler sample test</a></p>
<h2>Compile onnx model for your target machine</h2>
<p>Checkout <a href="https://github.com/ai-techsystems/deepC/blob/master/test/compiler/mnist/mnist.ir" rel="nofollow noopener">mnist.ir</a></p>
<h3>Step 1:</h3>
<p>Generate intermediate code</p>
<p><code>% onnx2cpp mnist.onnx</code></p>
<h3>Step 2:</h3>
<p>Optimize and compile</p>
<p><code>% g++ -O3 mnist.cpp -I ../../../include/ -isystem ../../../packages/eigen-eigen-323c052e1731/ -o mnist.exe</code></p>
<h3>Step 3:</h3>
<p>Test run</p>
<p><code>% ./mnist.exe</code></p>

srohit0: <p>Here is a brief talk on how to compile PyTorch models to a C++ project on MCUs</p><div class="youtube-onebox lazy-video-container" data-video-id="CLKATaIQHi8" data-video-title="ONNX on MCUs" data-provider-name="youtube">
  <a href="https://www.youtube.com/watch?v=CLKATaIQHi8" target="_blank" rel="noopener nofollow ugc">
    <img class="youtube-thumbnail" src="https://img.youtube.com/vi/CLKATaIQHi8/hqdefault.jpg" title="ONNX on MCUs" width="480" height="360">
  </a>
</div>