多个模型串行推理时如何传递数据
在用opencl推理时,有两个数据传递的问题想请教一下: (1)如果模型a的输出是模型b的输入,我现在是把模型a的输出copyToHostTensor,模型b的输入再copyFromHostTensor, 这样数据传递有点慢,有更加直接在opencl上传递的方法吗? (2)我用opencl写了一段特征处理的代码,想嵌入到mnn推理的过程中,cl_mem和mnn Tensor(opencl后端)之间如何不通过host传递数据?
非常感谢!
关于(1) ,有两种方案 A、设置模型 b 的 sessionMode 为 Session_Input_User ,在模型 a 的 session resize 完成后,把 a 的 output tensor 的 deviceId() 赋值给 模型 b 的 input tensor ,再调模型 b 的 session 去 resizeSession B、采用 Module API ,VARP 传递过去即可,不会出现内存拷贝
关于(2),目前 mnn opencl 不支持传入 opencl 上下文,需要修改 mnn 源码
关于(1) ,有两种方案 A、设置模型 b 的 sessionMode 为 Session_Input_User ,在模型 a 的 session resize 完成后,把 a 的 output tensor 的 deviceId() 赋值给 模型 b 的 input tensor ,再调模型 b 的 session 去 resizeSession B、采用 Module API ,VARP 传递过去即可,不会出现内存拷贝
关于(2),目前 mnn opencl 不支持传入 opencl 上下文,需要修改 mnn 源码
感谢解答! 请问一下(1)A中的方案,“deviceId() 赋值给 模型 b 的 input tensor” 这步是如何实现的?deviceId()返回值的类型不是tensor类型,好像不能直接赋值
b->buffer().device = a->buffer().device
b->buffer().device = a->buffer().device
@jxt1234 ,感谢回答,按照这个步骤实现了一下,发现还是不行,麻烦您帮忙看下代码 我的目标是pe net的输入传给pd net,pd net的输出和预期不一致,代码如下,非常感谢!
`
auto peFileName = "pe_s.mnn";
auto pdFileName = "pd_s.mnn";
std::shared_ptr<Interpreter> pe_net;
std::shared_ptr<Interpreter> pd_net;
pe_net.reset(Interpreter::createFromFile(peFileName));
pd_net.reset(Interpreter::createFromFile(pdFileName));
if (pe_net == nullptr || pd_net == nullptr) {
MNN_ERROR("Invalid Model\n");
return 0;
}
ScheduleConfig config;
config.type = MNN_FORWARD_OPENCL;
config.numThread = 1;
auto pe_session = pe_net->createSession(config);
auto pd_session = pd_net->createSession(config);
Interpreter::SessionMode inputMode = Interpreter::Session_Input_User;
pd_net->setSessionMode(inputMode); //设置 b 的 sessionMode 为 Session_Input_User
auto pe_inputs = pe_net->getSessionInputAll(pe_session);
auto pe_0_input = pe_inputs["0"];
auto pe_1_input = pe_inputs["1"];
auto pe_1_shape = pe_1_input->shape();
auto pe_0_shape = pe_0_input->shape();
pe_net->resizeSession(pe_session); //session resize
if (pe_0_shape[0] != 1 || pe_1_shape[0] != 1) {
cout << "pe input size error !" <<endl;
pe_0_shape[0] = 1;
pe_1_shape[0] = 1;
pe_net->resizeTensor(pe_1_input, pe_1_shape);
pe_net->resizeTensor(pe_0_input, pe_0_shape);
}
auto pe_output = pe_net->getSessionOutput(pe_session, nullptr);
auto pd_input = pd_net->getSessionInput(pd_session, nullptr);
auto pd_shape = pd_input->shape();
pd_input->buffer().device = pe_output->buffer().device; // a 的 output tensor 的 deviceId() 赋值给 模型 b 的 input tensor
pd_net->resizeSession(pd_session); //session resize
if (pd_shape[0] != 1) {
cout << "pd input size error !" <<endl;
pd_shape[0] = 1;
pd_net->resizeTensor(pd_input, pd_shape);
}
auto pd_output = pd_net->getSessionOutput(pd_session, nullptr);
//填充数据
auto pe_0_input_ = new Tensor(pe_0_input, Tensor::CAFFE); //src
auto pe_0_input_size = pe_0_input_ ->size();
::memcpy(pe_0_input_->host<float>(), src_img, pe_0_input_size);
pe_0_input->copyFromHostTensor(pe_0_input_);
delete pe_0_input_;
auto pe_1_input_ = new Tensor(pe_1_input, Tensor::CAFFE); //input
auto pe_1_input_size = pe_1_input_ ->size();
::memcpy(pe_1_input_->host<float>(), current_img, pe_1_input_size);
pe_1_input->copyFromHostTensor(pe_1_input_);
delete pe_1_input_;
pe_net->runSession(pe_session);
pd_net->runSession(pd_session);
//验证输出正确性
auto pd_output_ = new Tensor(pd_output, Tensor::CAFFE);
pd_output->copyToHostTensor(pd_output_);
auto pd_output_out = pd_output_->host<float>();
for(int i = 0; i<16; i++)
cout << pd_output_out[i] <<" ";
cout <<endl;
} `
两个 session 需要是同一个 runtime ,参考 https://www.yuque.com/mnn/cn/create_session#xtQLb 共享 runtime 试下