@@ -361,6 +361,37 @@ Status DynamicSingleOp::SetHostTensorValue(const std::vector<std::pair<size_t, u | |||
return SUCCESS; | |||
} | |||
Status DynamicSingleOp::SetHostTensorValue(const vector<GeTensorDesc> &input_desc, | |||
const vector<DataBuffer> &input_buffers) { | |||
for (auto &tensor_map : tensor_with_hostmem_) { | |||
auto index = tensor_map.first; | |||
if (index >= input_desc.size() || index >= input_buffers.size()) { | |||
GELOGE(INTERNAL_ERROR, "[Check][Size]Index %d should smaller then input desc size %zu " | |||
"and input buffers size %zu.", index, input_desc.size(), input_buffers.size()); | |||
return INTERNAL_ERROR; | |||
} | |||
auto ge_tensor_desc = input_desc[index]; | |||
// reconstruct GeTensor by DataBuffer | |||
GeTensorPtr ge_tensor = MakeShared<GeTensor>(ge_tensor_desc); | |||
GE_CHECK_NOTNULL(ge_tensor); | |||
GELOGD("The %d tensor input type is host, desc data type is %d, input buffer addr is %p, size is %ld.", | |||
index, ge_tensor_desc.GetDataType(), input_buffers[index].data, input_buffers[index].length); | |||
if (ge_tensor->SetData(reinterpret_cast<uint8_t *>(input_buffers[index].data), | |||
static_cast<size_t>(input_buffers[index].length)) != SUCCESS) { | |||
GELOGE(INTERNAL_ERROR, "[Set][Data]Failed to set data of ge tensor."); | |||
return INTERNAL_ERROR; | |||
} | |||
for (auto &tensor_desc : tensor_map.second) { | |||
GE_CHECK_NOTNULL(tensor_desc); | |||
if (!AttrUtils::SetTensor(tensor_desc, ATTR_NAME_VALUE, ge_tensor)) { | |||
GELOGE(FAILED, "[Set][ATTR_NAME_VALUE]Failed to set ATTR_NAME_VALUE."); | |||
return FAILED; | |||
} | |||
} | |||
} | |||
return SUCCESS; | |||
} | |||
Status DynamicSingleOp::ExecuteAsync(const vector<GeTensorDesc> &input_desc, | |||
const vector<DataBuffer> &input_buffers, | |||
vector<GeTensorDesc> &output_desc, | |||
@@ -374,6 +405,7 @@ Status DynamicSingleOp::ExecuteAsync(const vector<GeTensorDesc> &input_desc, | |||
if (!inputs_size.empty()) { | |||
StreamResource *stream_resource = SingleOpManager::GetInstance().GetResource(resource_id_, stream_); | |||
GE_CHK_STATUS_RET_NOLOG(UpdateInputsBufferAddr(stream_resource, stream_, inputs_size, update_buffers)); | |||
GE_CHK_STATUS_RET_NOLOG(SetHostTensorValue(input_desc, input_buffers)); | |||
} | |||
if (hybrid_model_executor_ != nullptr) { | |||
@@ -81,9 +81,12 @@ class DynamicSingleOp { | |||
std::vector<DataBuffer> &outputs) const; | |||
Status SetHostTensorValue(const std::vector<std::pair<size_t, uint64_t>> &inputs_size, | |||
const vector<GeTensorDesc> &input_desc, const std::vector<DataBuffer> &input_buffers); | |||
Status SetHostTensorValue(const vector<GeTensorDesc> &input_desc, const vector<DataBuffer> &input_buffers); | |||
std::unique_ptr<OpTask> op_task_; | |||
std::unique_ptr<hybrid::HybridModel> hybrid_model_; | |||
std::unique_ptr<hybrid::HybridModelExecutor> hybrid_model_executor_; | |||
std::map<int32_t, std::vector<GeTensorDescPtr>> tensor_with_hostmem_; | |||
uintptr_t resource_id_ = 0; | |||
std::mutex *stream_mutex_; | |||
rtStream_t stream_ = nullptr; | |||
@@ -235,6 +235,13 @@ Status SingleOpModel::LoadAllNodes() { | |||
if (op_type == DATA_TYPE || op_type == AIPP_DATA_TYPE) { | |||
data_ops_.emplace_back(op_desc); | |||
auto tensor = op_desc->MutableInputDesc(0); | |||
if (AttrUtils::HasAttr(tensor, ATTR_NAME_VALUE)) { | |||
int32_t index = 0; | |||
(void) AttrUtils::GetInt(op_desc, ATTR_NAME_INDEX, index); | |||
GELOGD("Node %s, index %d, has host mem.", node->GetName().c_str(), index); | |||
op_with_hostmem_[index] = node; | |||
} | |||
continue; | |||
} | |||
@@ -616,6 +623,7 @@ Status SingleOpModel::BuildDynamicOp(StreamResource &resource, DynamicSingleOp & | |||
if (need_hybrid_model) { | |||
GELOGD("Build single op HybridModel."); | |||
GE_CHK_STATUS_RET_NOLOG(hybrid::NodeExecutorManager::GetInstance().EnsureInitialized()); | |||
GE_CHK_STATUS(SetHostMemTensor(single_op), "[Init][HostMem]Failed."); | |||
auto root_model = model_helper_.GetGeRootModel(); | |||
GE_CHECK_NOTNULL(root_model); | |||
root_model->SetRootGraph(GraphUtils::GetComputeGraph(ge_model->GetGraph())); | |||
@@ -634,4 +642,28 @@ Status SingleOpModel::BuildDynamicOp(StreamResource &resource, DynamicSingleOp & | |||
} | |||
return BuildTaskListForDynamicOp(&resource, single_op); | |||
} | |||
Status SingleOpModel::SetHostMemTensor(DynamicSingleOp &single_op) { | |||
for (auto &node_map : op_with_hostmem_) { | |||
auto node = node_map.second; | |||
auto out_anchor = node->GetOutDataAnchor(0); | |||
GE_CHECK_NOTNULL(out_anchor); | |||
auto in_anchors = out_anchor->GetPeerInDataAnchors(); | |||
vector<GeTensorDescPtr> tensor_descs; | |||
auto idx = node_map.first; | |||
for (auto anchor : in_anchors) { | |||
GE_CHECK_NOTNULL(anchor); | |||
auto output_node = anchor->GetOwnerNode(); | |||
GE_CHECK_NOTNULL(output_node); | |||
auto op_desc = output_node->GetOpDesc(); | |||
GE_CHECK_NOTNULL(op_desc); | |||
auto tensor_desc = op_desc->MutableInputDesc(anchor->GetIdx()); | |||
tensor_descs.emplace_back(tensor_desc); | |||
GELOGD("Get %d th input tensor desc of %s by %d data node: %s.", anchor->GetIdx(), | |||
output_node->GetName().c_str(), idx, node->GetName().c_str()); | |||
} | |||
single_op.tensor_with_hostmem_[idx] = tensor_descs; | |||
} | |||
return SUCCESS; | |||
} | |||
} // namespace ge |
@@ -77,6 +77,7 @@ class SingleOpModel { | |||
static void ParseOpModelParams(ModelHelper &model_helper, SingleOpModelParam ¶m); | |||
void ParseArgTable(OpTask *task, SingleOp &op); | |||
Status InitHybridModelExecutor(const StreamResource &resource, const GeModelPtr &ge_model, SingleOp &single_op); | |||
Status SetHostMemTensor(DynamicSingleOp &single_op); | |||
std::string model_name_; | |||
uint32_t model_id_ = 0; | |||
@@ -86,6 +87,7 @@ class SingleOpModel { | |||
ModelHelper model_helper_; | |||
map<uint32_t, NodePtr> op_list_; | |||
map<int32_t, NodePtr> op_with_hostmem_; | |||
SingleOpModelParam model_params_; | |||
std::vector<ptrdiff_t> input_offset_list_; | |||
@@ -27,6 +27,7 @@ | |||
#include "single_op/task/tbe_task_builder.h" | |||
#undef private | |||
#undef protected | |||
#include "graph/passes/graph_builder_utils.h" | |||
using namespace std; | |||
using namespace testing; | |||
@@ -223,3 +224,19 @@ TEST_F(UtestSingleOpModel, test_build_dynamic_op) { | |||
model.BuildDynamicOp(res, dynamic_single_op); | |||
} | |||
TEST_F(UtestSingleOpModel, test_host_mem) { | |||
string model_data_str = "123456789"; | |||
SingleOpModel model("model", model_data_str.c_str(), model_data_str.size()); | |||
// make graph | |||
ut::GraphBuilder builder = ut::GraphBuilder("graph"); | |||
auto data = builder.AddNode("Data", "Data", 0, 1); | |||
auto netoutput = builder.AddNode("Netoutput", "NetOutput", 1, 0); | |||
builder.AddDataEdge(data, 0, netoutput, 0); | |||
auto graph = builder.GetGraph(); | |||
model.op_with_hostmem_[0] = data; | |||
std::mutex stream_mu_; | |||
DynamicSingleOp single_op(0, &stream_mu_, nullptr); | |||
ASSERT_EQ(model.SetHostMemTensor(single_op), SUCCESS); | |||
} |
@@ -160,4 +160,23 @@ TEST_F(UtestSingleOp, test_singleop_execute_async2) { | |||
EXPECT_EQ(single_op.running_param_->mem_base, nullptr); | |||
EXPECT_EQ(single_op.tasks_.size(), 0); | |||
EXPECT_EQ(single_op.ExecuteAsync(input_buffers, output_buffers), PARAM_INVALID); | |||
} | |||
} | |||
TEST_F(UtestSingleOp, test_set_host_mem) { | |||
std::mutex stream_mu_; | |||
DynamicSingleOp single_op(0, &stream_mu_, nullptr); | |||
vector<DataBuffer> input_buffers; | |||
DataBuffer data_buffer; | |||
input_buffers.emplace_back(data_buffer); | |||
vector<GeTensorDesc> input_descs; | |||
GeTensorDesc tensor_desc1; | |||
input_descs.emplace_back(tensor_desc1); | |||
vector<GeTensorDescPtr> op_input_descs; | |||
auto tensor_desc2 = std::make_shared<GeTensorDesc>(); | |||
op_input_descs.emplace_back(tensor_desc2); | |||
single_op.tensor_with_hostmem_[0] = op_input_descs; | |||
EXPECT_EQ(single_op.SetHostTensorValue(input_descs, input_buffers), SUCCESS); | |||
} |