CAFFE2:加载ONNX模型和在多核主机 / Docker上的推理单线



当主机有多个内核时,我在docker上的模型上运行推断很难。该模型通过Pytorch 1.0 ONNX导出器导出:

torch.onnx.export(pytorch_net, dummyseq, ONNX_MODEL_PATH)

用单个核心启动模型服务器(用烧瓶包装)可接受性能(CPUSET将过程列为特定CPU)docker run --rm -p 8081:8080 --cpus 0.5 --cpuset-cpus 0 my_container

ab -c 1 -n 1000 http://0.0.0.0:8081/predict?itemids=5,100

的响应
Percentage of the requests served within a certain time (ms)
  50%      5
  66%      5
  75%      5
  80%      5
  90%      7
  95%     46
  98%     48
  99%     49

,但将其固定在四个内核中给出了同一AB-CLAL-docker run --rm -p 8081:8080 --cpus 0.5 --cpuset-cpus 0,1,2,3 my_container

的完全不同的统计数据
Percentage of the requests served within a certain time (ms)
  50%      9
  66%     12
  75%     14
  80%     18
  90%     62
  95%     66
  98%     69
  99%     69
 100%     77 (longest request)

模型推断是这样完成的,除了此问题外,它似乎可以按预期工作。(这在与模型导出的完全独立的环境中运行)

from caffe2.python import workspace
from caffe2.python.onnx.backend import Caffe2Backend as c2
from onnx import ModelProto

class Model:
    def __init__(self):
        self.predictor = create_caffe2_predictor(path)
    @staticmethod
    def create_caffe2_predictor(onnx_file_path):
        with open(onnx_file_path, 'rb') as onnx_model:
            onnx_model_proto = ModelProto()
            onnx_model_proto.ParseFromString(onnx_model.read())
            init_net, predict_net = c2.onnx_graph_to_caffe2_net(onnx_model_proto)
            predictor = workspace.Predictor(init_net, predict_net)
        return predictor

    def predict(self, numpy_array):
        return self.predictor.run({'0': numpy_array})
** wrapper flask app which calls Model.predict() on calls to /predict **

OMP_NUM_THREADS=1也存在于容器环境中,其中具有某些效果,但这不是最终问题。

您在这里看到的基准统计数据是在带有8个高线程的本地计算机上运行的,因此我不应该饱和我的计算机并影响测试。这些结果也出现在我的Kubernetes环境中,我在那里有大量的CFS(完全公平的调度程序)。

我正在kubernetes环境中跑步,所以我无法控制主机曝光多少CPU,并且在此固定似乎也有些骇人。

有什么方法可以将CAFFE2模型推断为单个处理器?我在这里显然做错了吗?caffe2.predictor对象不适合此任务吗?

任何帮助。

编辑:

我在这里添加了我可以想到的最简单的可再现示例,其中包括:https://github.com/negation/caffe2struggles

这不是对问题的直接答案,但是如果您的目标是在生产中提供Pytorch模型(并且只有pytorch模型,那么仅使用Pytorch模型),那么只需使用Pytorch Tracing即可成为更好的选择。

然后,您可以将其直接加载到C 前端中,类似于您通过CAFFE2的操作,但是Pytorch Tracing似乎维护得更良好。从我可以看到的没有速度放慢速度的情况下,配置要容易得多。

这样的示例是在单核容器上获得良好的性能,就像以前一样用OMP_NUM_THREADS=1运行,并如下导出模型:

from torch import jit
### Create a model
model.eval()
traced = jit.trace(model, torch.from_numpy(an_array_with_input_size))
traced.save("traced.pt")

,然后只需按照上述指南或通过python接口以纯C 的形式运行模型:

from torch import jit
model = jit.load("traced.pt")
output = model(some_input)

我认为这应该有效:

workspace.GlobalInit(["caffe2", "--caffe2_omp_num_threads=1"])

最新更新