我有10个模型,并希望将这些模型组合在一起。我需要以非常快的响应时间进行推理。
首先我定义了容器:
// model containder
std::vector<std::shared_ptr<LRModel>> container;
// predictions, n_models = 10
std::vector<std::vector<std::string>> pred_2d(n_models);
然后我使用线程池同时进行预测:
std::vector<std::thread> threads;
for (int i = 0; i < n_models; ++i) {
threads.emplace_back(std::thread(&Search::make_infer, this,
std::ref(container[i]),
std::ref(input),
std::ref(pred_2d[i])));
}
而Search::make_infer
定义为:
container[i]->predict(input, pred);
通过这样做,响应时间从80ms减少到40ms。但还是很满意。我需要将时间缩短到10ms。我该如何进一步优化这个?
一般规则是衡量,然后测量更多,所以使用工具来衡量你的时间。但是仍然有一些你应该注意的事情。
如果你的所有数据都已经在内存中,你应该作为一个规则,不要创建比你有硬件线程更多的线程,而是让每个线程处理多个搜索。根据您的幸运程度,任务切换大约需要1000个周期到20000个周期。
创建一个线程也不是免费的,所以如果你不能在你的CPU中使用额外的线程,你可以在那里保存一点,更好的是如果多次运行你可以使用一个线程池。
如果您的数据不在内存中,则更多线程可能会有所帮助,因为某些线程可以等待其他进行处理。
接下来减少共享数据的数量,在您的情况下,似乎只是访问容器。如果你的3个std::ref
中的每一个只被访问一次它几乎不重要,但我们无法看到predict
这样做,所以也可能有问题。如果你只是从vector
s那里读到了问题。
如果每个predict
花费相同的时间,并且每个最小运行时间没有一个硬件线程
time = time(predict)*num_predict/num_hardware_threads
并且您的运行时受限于最慢的软件/硬件线程组合,任务切换,系统调用,真/假共享等影响单个运行时。
同样为什么要使用std::ref
,你的数据似乎也可用作参考。
如果您不打算更改输入参数,还应使用它们的const
版本作为参数传递。