VTrain_BothSides/base/SingleOpProcess/SingleOpProcess.cpp

281 lines
10 KiB
C++

/*
* Copyright (c) 2020.Huawei Technologies Co., Ltd. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SingleOpProcess.h"
#include "acl/acl.h"
SingleOpProcess::SingleOpProcess()
: inputTensorNum_(0), outputTensorNum_(0), stream_(nullptr), attr_(nullptr), withHandle_(false), opHandle_(nullptr)
{}
SingleOpProcess::SingleOpProcess(const aclrtStream &stream)
: inputTensorNum_(0), outputTensorNum_(0), stream_(stream), attr_(nullptr), withHandle_(false), opHandle_(nullptr)
{
}
SingleOpProcess::~SingleOpProcess()
{
// only need destroy handle, other resource managed by smart pointer
if (withHandle_ == true) {
aclopDestroyHandle(opHandle_);
opHandle_ = nullptr;
}
stream_ = nullptr;
}
void SingleOpProcess::SetTypeName(std::string typeName)
{
typeName_ = typeName;
}
std::string SingleOpProcess::GetTypeName()
{
return typeName_;
}
APP_ERROR SingleOpProcess::SetInputTensor(std::vector<Tensor> tensors)
{
inputTensorDesc_.clear();
for (int i = 0; i < inputTensorNum_; i++) {
// create input tensor description
std::shared_ptr<aclTensorDesc> tensorDesc(aclCreateTensorDesc(tensors[i].dataType, tensors[i].numDim,
tensors[i].dims.data(), tensors[i].format),
aclDestroyTensorDesc);
if (tensorDesc == nullptr) {
LogError << "Failed to create acl input tensor description.";
return APP_ERR_COMM_INVALID_POINTER;
}
inputTensorDesc_.push_back(tensorDesc);
}
return APP_ERR_OK;
}
APP_ERROR SingleOpProcess::SetInputDataBuffer(std::vector<std::shared_ptr<void>> inputDataBuf,
std::vector<size_t> inputBufSize)
{
inputDataBuf_.clear();
inputData_ = inputDataBuf;
for (int i = 0; i < inputTensorNum_; i++) {
// create input data buffer
std::shared_ptr<aclDataBuffer> dataBuffer(aclCreateDataBuffer(inputDataBuf[i].get(),
inputBufSize[i]),
aclDestroyDataBuffer);
if (dataBuffer == nullptr) {
LogError << "Failed to create acl input data buffer.";
return APP_ERR_COMM_INVALID_POINTER;
}
inputDataBuf_.push_back(dataBuffer);
}
return APP_ERR_OK;
}
APP_ERROR SingleOpProcess::SetOutputTensor(std::vector<Tensor> tensors)
{
outputTensorDesc_.clear();
outputDataBuf_.clear();
outputData_.clear();
outputDataSize_.clear();
APP_ERROR ret = APP_ERR_OK;
for (int i = 0; i < outputTensorNum_; i++) {
// create output tensor describe
std::shared_ptr<aclTensorDesc> tensorDesc(aclCreateTensorDesc(tensors[i].dataType, tensors[i].numDim,
tensors[i].dims.data(), tensors[i].format),
aclDestroyTensorDesc);
if (tensorDesc == nullptr) {
LogError << "Failed to create acl output tensor description.";
return APP_ERR_COMM_INVALID_POINTER;
}
outputTensorDesc_.push_back(tensorDesc);
// create output data buffer
void *outDevBuf = nullptr;
size_t size = aclGetTensorDescSize(tensorDesc.get());
ret = aclrtMalloc(&outDevBuf, size, ACL_MEM_MALLOC_NORMAL_ONLY);
if (ret != APP_ERR_OK) {
LogError << "Failed to aclrtMalloc out result.";
return ret;
}
std::shared_ptr<aclDataBuffer> dataBuf(aclCreateDataBuffer(outDevBuf, size), aclDestroyDataBuffer);
if (dataBuf == nullptr) {
LogError << "Failed to create acl output data buffer.";
return APP_ERR_COMM_INVALID_POINTER;
}
outputDataBuf_.push_back(dataBuf);
std::shared_ptr<void> data(outDevBuf, aclrtFree);
outputData_.push_back(data);
outputDataSize_.push_back(size);
}
return APP_ERR_OK;
}
void SingleOpProcess::SetInputTensorNum(int num)
{
inputTensorNum_ = num;
}
int SingleOpProcess::GetInputTensorNum() const
{
return inputTensorNum_;
}
void SingleOpProcess::SetOutputTensorNum(int num)
{
outputTensorNum_ = num;
}
int SingleOpProcess::GetOutputTensorNum() const
{
return outputTensorNum_;
}
std::vector<std::shared_ptr<void>> SingleOpProcess::GetOutputData()
{
return outputData_;
}
std::vector<size_t> SingleOpProcess::GetOutputDataSize() const
{
return outputDataSize_;
}
std::vector<std::shared_ptr<aclTensorDesc>> SingleOpProcess::GetInputTensorDesc()
{
return inputTensorDesc_;
}
std::vector<std::shared_ptr<aclTensorDesc>> SingleOpProcess::GetOutputTensorDesc()
{
return outputTensorDesc_;
}
APP_ERROR SingleOpProcess::SetOpAttr(std::shared_ptr<aclopAttr> attr, OpAttr attrDesc)
{
attr_ = attr;
// set operator specifec attribute by attrDesc.type
switch (attrDesc.type) {
case BOOL_TYPE:
aclopSetAttrBool(attr.get(), attrDesc.name.c_str(), attrDesc.numBool);
break;
case INT_TYPE:
aclopSetAttrInt(attr.get(), attrDesc.name.c_str(), attrDesc.numInt);
break;
case FLOAT_TYPE:
aclopSetAttrFloat(attr.get(), attrDesc.name.c_str(), attrDesc.numFloat);
break;
case STRING_TYPE:
aclopSetAttrString(attr.get(), attrDesc.name.c_str(), attrDesc.numString.c_str());
break;
case LIST_BOOL_TYPE:
aclopSetAttrListBool(attr.get(), attrDesc.name.c_str(), attrDesc.num, attrDesc.valuesBool.data());
break;
case LIST_INT_TYPE:
aclopSetAttrListInt(attr.get(), attrDesc.name.c_str(), attrDesc.num, attrDesc.valuesInt.data());
break;
case LIST_FLOAT_TYPE:
aclopSetAttrListFloat(attr.get(), attrDesc.name.c_str(), attrDesc.num, attrDesc.valuesFloat.data());
break;
case LIST_STRING_TYPE: {
std::unique_ptr<const char* []> valuesString(new const char* [attrDesc.num],
std::default_delete<const char* []>());
for (int i = 0; i < attrDesc.num; i++) {
valuesString[i] = attrDesc.valuesString[i].c_str();
}
aclopSetAttrListString(attr.get(), attrDesc.name.c_str(), attrDesc.num, valuesString.get());
break;
}
case LIST_LIST_INT_TYPE: {
std::unique_ptr<const int64_t* []> valuesListList(new const int64_t* [attrDesc.num],
std::default_delete<const int64_t* []>());
for (int i = 0; i < attrDesc.num; i++) {
valuesListList[i] = attrDesc.valuesListList[i].data();
}
aclopSetAttrListListInt(attr.get(), attrDesc.name.c_str(),
attrDesc.num, attrDesc.numLists.data(), valuesListList.get());
break;
}
default:
break;
}
return APP_ERR_OK;
}
std::shared_ptr<aclopAttr> SingleOpProcess::GetOpAttr() const
{
return attr_;
}
void SingleOpProcess::SetStream(aclrtStream stream)
{
stream_ = stream;
}
const aclrtStream& SingleOpProcess::GetStream() const
{
return stream_;
}
APP_ERROR SingleOpProcess::RunSingleOp(const bool &withHandle)
{
withHandle_ = withHandle;
// convert inputTensorDesc_ to aclTensorDesc ** type for execute singleOp or create handle
std::vector<aclTensorDesc *> inTensorDesc;
for (auto tensor : inputTensorDesc_) {
inTensorDesc.push_back(tensor.get());
}
// convert inputDataBuf_ to aclDataBuffer ** type for execute singleOp
std::vector<aclDataBuffer *> inData;
for (auto data : inputDataBuf_) {
inData.push_back(data.get());
}
// convert outputTensorDesc_ to aclTensorDesc ** type for execute singleOp or create handle
std::vector<aclTensorDesc *> outTensorDesc;
for (auto tensor : outputTensorDesc_) {
outTensorDesc.push_back(tensor.get());
}
// convert outputDataBuf_ to aclDataBuffer ** type for execute singleOp
std::vector<aclDataBuffer *> outData;
for (auto data : outputDataBuf_) {
outData.push_back(data.get());
}
APP_ERROR ret = APP_ERR_OK;
if (withHandle_ == true) {
// create handle
ret = aclopCreateHandle(typeName_.c_str(), inputTensorNum_, inTensorDesc.data(),
outputTensorNum_, outTensorDesc.data(), attr_.get(), &opHandle_);
if (ret != APP_ERR_OK) {
LogError << typeName_ << "Failed to create handle, ret = " << ret;
return ret;
}
// execute single operator with handle
ret = aclopExecWithHandle(opHandle_, inputTensorNum_,
inData.data(), outputTensorNum_, outData.data(), stream_);
if (ret != APP_ERR_OK) {
LogError << typeName_ << "Failed to execute single operator with handle, ret = " << ret;
return ret;
}
} else {
#ifdef USE_ACL_OP_EXECUTE_V2
// execute single operator without handle
ret = aclopExecuteV2(typeName_.c_str(), inputTensorNum_, inTensorDesc.data(), inData.data(),
outputTensorNum_, outTensorDesc.data(), outData.data(), attr_.get(), stream_);
#else
// execute single operator without handle
ret = aclopExecute(typeName_.c_str(), inputTensorNum_, inTensorDesc.data(), inData.data(),
outputTensorNum_, outTensorDesc.data(), outData.data(), attr_.get(), stream_);
#endif
if (ret != APP_ERR_OK) {
LogError << "Failed to execute singleOp: " << typeName_ << " ret = " << ret;
return ret;
}
}
return APP_ERR_OK;
}