forked from huawei/mindspore2022
!21632 add post training quant of unet,maskrcnn,crnn,deeplabv3
Merge pull request !21632 from chenzhuo/quant
This commit is contained in:
commit
962c3f4ae3
|
|
@ -13,7 +13,7 @@
|
|||
# limitations under the License.
|
||||
# ============================================================================
|
||||
"""
|
||||
Compression common module.
|
||||
Common module for various compression algorithms, now only including datatype definition for quantization.
|
||||
"""
|
||||
|
||||
from .constant import QuantDtype
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
# limitations under the License.
|
||||
# ============================================================================
|
||||
"""
|
||||
Compression quant module.
|
||||
Quantization module, including base class of the quantizer, the quantization aware training algorithm,
|
||||
and quantization utils.
|
||||
"""
|
||||
|
||||
from .quantizer import OptimizeOption
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
- [Export MindIR](#export-mindir)
|
||||
- [Infer on Ascend310](#infer-on-ascend310)
|
||||
- [result](#result)
|
||||
- [Post Training Quantization](#post-training-quantization)
|
||||
- [Model Description](#model-description)
|
||||
- [Performance](#performance)
|
||||
- [Training Performance](#training-performance)
|
||||
|
|
@ -364,6 +365,41 @@ correct num: 2042 , total num: 3000
|
|||
result CRNNAccuracy is: 0.806666666666
|
||||
```
|
||||
|
||||
### [Post Training Quantization](#contents)
|
||||
|
||||
Relative executing script files reside in the directory "ascend310_quant_infer". Please implement following steps sequentially to complete post quantization.
|
||||
Current quantization project bases on IIIT5K dataset.
|
||||
|
||||
1. Generate data of .bin format required for AIR model inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
python export_bin.py --eval_dataset [DATASET NAME] --eval_dataset_path [DATA PATH]
|
||||
```
|
||||
|
||||
2. Export quantized AIR model.
|
||||
|
||||
Post quantization of model requires special toolkits for exporting quantized AIR model. Please refer to [official website](https://www.hiascend.com/software/cann/community).
|
||||
|
||||
```shell
|
||||
python post_quant.py --eval_dataset [DATASET NAME] --eval_dataset_path [DATA PATH] --ckpt_file [CKPT_PATH]
|
||||
```
|
||||
|
||||
The quantized AIR file will be stored as "./results/crnn_quant.air".
|
||||
|
||||
3. Implement inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
# Ascend310 quant inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]
|
||||
```
|
||||
|
||||
Inference result is saved in current path, you can find result like this in acc.log file.
|
||||
|
||||
```bash
|
||||
correct num: 2398 , total num: 3000
|
||||
result CRNNAccuracy is: 0.7933333333333
|
||||
```
|
||||
|
||||
## [Model Description](#contents)
|
||||
|
||||
### [Performance](#contents)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""postprocess for 310 inference"""
|
||||
import os
|
||||
import argparse
|
||||
import numpy as np
|
||||
import Levenshtein
|
||||
from mindspore import nn
|
||||
|
||||
|
||||
label_dict = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
parser = argparse.ArgumentParser("crnn quant postprocess")
|
||||
parser.add_argument("--result_path", type=str, required=True, help="path to inference results.")
|
||||
parser.add_argument("--label_path", type=str, required=True, help="path to label.npy.")
|
||||
parser.add_argument("--num_step", type=int, default=24, help="num step for LSTM layer")
|
||||
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
|
||||
class CRNNAccuracy(nn.Metric):
|
||||
"""
|
||||
Define accuracy metric for warpctc network.
|
||||
"""
|
||||
|
||||
def __init__(self, print_flag=True):
|
||||
super(CRNNAccuracy, self).__init__()
|
||||
self._correct_num = 0
|
||||
self._total_num = 0
|
||||
self.blank = len(label_dict)
|
||||
self.print_flag = print_flag
|
||||
|
||||
def clear(self):
|
||||
self._correct_num = 0
|
||||
self._total_num = 0
|
||||
|
||||
def update(self, *inputs):
|
||||
if len(inputs) != 2:
|
||||
raise ValueError('CRNNAccuracy need 2 inputs (y_pred, y), but got {}'.format(len(inputs)))
|
||||
y_pred = self._convert_data(inputs[0])
|
||||
str_pred = self._ctc_greedy_decoder(y_pred)
|
||||
if isinstance(inputs[1], list) and isinstance(inputs[1][0], str):
|
||||
str_label = [x.lower() for x in inputs[1]]
|
||||
else:
|
||||
y = self._convert_data(inputs[1])
|
||||
str_label = self._convert_labels(y)
|
||||
|
||||
for pred, label in zip(str_pred, str_label):
|
||||
if self.print_flag:
|
||||
print(pred, " :: ", label)
|
||||
edit_distance = Levenshtein.distance(pred, label)
|
||||
self._total_num += 1
|
||||
if edit_distance == 0:
|
||||
self._correct_num += 1
|
||||
|
||||
def eval(self):
|
||||
if self._total_num == 0:
|
||||
raise RuntimeError('Accuary can not be calculated, because the number of samples is 0.')
|
||||
print('correct num: ', self._correct_num, ', total num: ', self._total_num)
|
||||
sequence_accurancy = self._correct_num / self._total_num
|
||||
return sequence_accurancy
|
||||
|
||||
def _arr2char(self, inputs):
|
||||
string = ""
|
||||
for i in inputs:
|
||||
if i < self.blank:
|
||||
string += label_dict[i]
|
||||
return string
|
||||
|
||||
def _convert_labels(self, inputs):
|
||||
str_list = []
|
||||
for label in inputs:
|
||||
str_temp = self._arr2char(label)
|
||||
str_list.append(str_temp)
|
||||
return str_list
|
||||
|
||||
def _ctc_greedy_decoder(self, y_pred):
|
||||
"""
|
||||
parse predict result to labels
|
||||
"""
|
||||
indices = []
|
||||
seq_len, batch_size, _ = y_pred.shape
|
||||
indices = y_pred.argmax(axis=2)
|
||||
lens = [seq_len] * batch_size
|
||||
pred_labels = []
|
||||
for i in range(batch_size):
|
||||
idx = indices[:, i]
|
||||
last_idx = self.blank
|
||||
pred_label = []
|
||||
for j in range(lens[i]):
|
||||
cur_idx = idx[j]
|
||||
if cur_idx not in [last_idx, self.blank]:
|
||||
pred_label.append(cur_idx)
|
||||
last_idx = cur_idx
|
||||
pred_labels.append(pred_label)
|
||||
str_results = []
|
||||
for i in pred_labels:
|
||||
str_results.append(self._arr2char(i))
|
||||
return str_results
|
||||
|
||||
|
||||
def calculate_acc(result_path, label_path):
|
||||
"""
|
||||
Calculate accuracy according to the annotation file and result file.
|
||||
"""
|
||||
metrics = CRNNAccuracy()
|
||||
label_list = np.load(label_path)
|
||||
prefix = "crnn_data_bs_1_"
|
||||
for i in range(len(os.listdir(result_path))):
|
||||
result_file = os.path.join(result_path, prefix + str(i) + "_output_0.bin")
|
||||
class_num = len(label_dict) + 1
|
||||
pred_y = np.fromfile(result_file, dtype=np.float16).reshape(args.num_step, -1, class_num)
|
||||
label = label_list[i]
|
||||
label_str = str()
|
||||
for index in label[0]:
|
||||
if int(index) < len(label_dict):
|
||||
label_str += label_dict[int(index)]
|
||||
metrics.update(pred_y, [label_str])
|
||||
|
||||
print("result CRNNAccuracy is: ", metrics.eval())
|
||||
metrics.clear()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
calculate_acc(args.result_path, args.label_path)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""generate data and label needed for AIR model inference"""
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import numpy as np
|
||||
from mindspore import context
|
||||
|
||||
|
||||
def generate_data():
|
||||
"""
|
||||
Generate data and label needed for AIR model inference at Ascend310 platform.
|
||||
"""
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
|
||||
result_path = "./data"
|
||||
if os.path.exists(result_path):
|
||||
shutil.rmtree(result_path)
|
||||
os.makedirs(result_path)
|
||||
|
||||
data_path = os.path.join(result_path, "00_input")
|
||||
os.makedirs(data_path)
|
||||
|
||||
dataset = create_dataset(name=config.eval_dataset,
|
||||
dataset_path=config.eval_dataset_path,
|
||||
batch_size=1,
|
||||
is_training=False,
|
||||
config=config)
|
||||
labels_list = []
|
||||
prefix = "crnn_data_bs_1_"
|
||||
for i, data in enumerate(dataset):
|
||||
file_path = os.path.join(data_path, prefix + str(i) + ".bin")
|
||||
data[0].asnumpy().tofile(file_path)
|
||||
labels_list.append(data[1].asnumpy())
|
||||
np.save(os.path.join(result_path, "label.npy"), labels_list)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from src.dataset import create_dataset
|
||||
from src.model_utils.config import config
|
||||
|
||||
generate_data()
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* ModelProcess
|
||||
*/
|
||||
class ModelProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief load model from file with mem
|
||||
* @param [in] modelPath: model path
|
||||
* @return result
|
||||
*/
|
||||
Result LoadModelFromFileWithMem(const char *modelPath);
|
||||
|
||||
/**
|
||||
* @brief unload model
|
||||
*/
|
||||
void Unload();
|
||||
|
||||
/**
|
||||
* @brief create model desc
|
||||
* @return result
|
||||
*/
|
||||
Result CreateDesc();
|
||||
|
||||
/**
|
||||
* @brief destroy desc
|
||||
*/
|
||||
void DestroyDesc();
|
||||
|
||||
/**
|
||||
* @brief create model input
|
||||
* @param [in] inputDataBuffer: input buffer
|
||||
* @param [in] bufferSize: input buffer size
|
||||
* @return result
|
||||
*/
|
||||
Result CreateInput(void *inputDataBuffer, size_t bufferSize);
|
||||
|
||||
/**
|
||||
* @brief destroy input resource
|
||||
*/
|
||||
void DestroyInput();
|
||||
|
||||
/**
|
||||
* @brief create output buffer
|
||||
* @return result
|
||||
*/
|
||||
Result CreateOutput();
|
||||
|
||||
/**
|
||||
* @brief destroy output resource
|
||||
*/
|
||||
void DestroyOutput();
|
||||
|
||||
/**
|
||||
* @brief model execute
|
||||
* @return result
|
||||
*/
|
||||
Result Execute();
|
||||
|
||||
/**
|
||||
* @brief dump model output result to file
|
||||
*/
|
||||
void DumpModelOutputResult(char *output_name);
|
||||
|
||||
/**
|
||||
* @brief get model output result
|
||||
*/
|
||||
void OutputModelResult();
|
||||
|
||||
private:
|
||||
uint32_t modelId_;
|
||||
size_t modelMemSize_;
|
||||
size_t modelWeightSize_;
|
||||
void *modelMemPtr_;
|
||||
void *modelWeightPtr_;
|
||||
bool loadFlag_; // model load flag
|
||||
aclmdlDesc *modelDesc_;
|
||||
aclmdlDataset *input_;
|
||||
aclmdlDataset *output_;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* SampleProcess
|
||||
*/
|
||||
class SampleProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief init reousce
|
||||
* @return result
|
||||
*/
|
||||
Result InitResource();
|
||||
|
||||
/**
|
||||
* @brief sample process
|
||||
* @return result
|
||||
*/
|
||||
Result Process(char *om_path, char *input_folder);
|
||||
|
||||
void GetAllFiles(std::string path, std::vector<std::string> *files);
|
||||
|
||||
private:
|
||||
void DestroyResource();
|
||||
|
||||
int32_t deviceId_;
|
||||
aclrtContext context_;
|
||||
aclrtStream stream_;
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args)
|
||||
#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args)
|
||||
#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args)
|
||||
|
||||
typedef enum Result {
|
||||
SUCCESS = 0,
|
||||
FAILED = 1
|
||||
} Result;
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
class Utils {
|
||||
public:
|
||||
/**
|
||||
* @brief create device buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return device buffer of file
|
||||
*/
|
||||
static void *GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize);
|
||||
|
||||
/**
|
||||
* @brief create buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return buffer of pic
|
||||
*/
|
||||
static void* ReadBinFile(std::string fileName, uint32_t *fileSize);
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""do post training quantization for Ascend310"""
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from amct_mindspore.quantize_tool import create_quant_config
|
||||
from amct_mindspore.quantize_tool import quantize_model
|
||||
from amct_mindspore.quantize_tool import save_model
|
||||
import mindspore as ms
|
||||
from mindspore import Tensor, context, load_checkpoint
|
||||
|
||||
|
||||
def quant_crnn(network, dataset, input_data):
|
||||
"""
|
||||
Export post training quantization model of AIR format.
|
||||
|
||||
Args:
|
||||
network: the origin network for inference.
|
||||
dataset: the data for inference.
|
||||
input_data: the data used for constructing network. The shape and format of input data should be the same as
|
||||
actual data for inference.
|
||||
"""
|
||||
|
||||
# step2: create the quant config json file
|
||||
create_quant_config("./config.json", network, input_data)
|
||||
|
||||
# step3: do some network modification and return the modified network
|
||||
calibration_network = quantize_model("./config.json", network, input_data)
|
||||
calibration_network.set_train(False)
|
||||
|
||||
# step4: perform the evaluation of network to do activation calibration
|
||||
for data in dataset.create_dict_iterator(num_epochs=1):
|
||||
_ = calibration_network(data["image"])
|
||||
|
||||
# step5: export the air file
|
||||
save_model("results/crnn_quant", calibration_network, input_data)
|
||||
print("[INFO] the quantized AIR file has been stored at: \n {}".format("results/crnn_quant.air"))
|
||||
|
||||
|
||||
def model_export():
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=get_device_id())
|
||||
config.batch_size = 1
|
||||
net = crnn(config)
|
||||
load_checkpoint(config.ckpt_file, net=net)
|
||||
net.set_train(False)
|
||||
|
||||
input_data = Tensor(np.zeros([config.batch_size, 3, config.image_height, config.image_width]), ms.float32)
|
||||
|
||||
ds = create_dataset(name=config.eval_dataset,
|
||||
dataset_path=config.eval_dataset_path,
|
||||
batch_size=config.batch_size,
|
||||
is_training=False,
|
||||
config=config)
|
||||
dataset = ds.take(1)
|
||||
quant_crnn(net, dataset, input_data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.path.append("..")
|
||||
from src.crnn import crnn
|
||||
from src.model_utils.config import config
|
||||
from src.model_utils.device_adapter import get_device_id
|
||||
from src.dataset import create_dataset
|
||||
|
||||
model_export()
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Usage: bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]"
|
||||
echo "Example: bash run_quant_infer.sh ./crnn_quant.air ./00_data ./label.npy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_real_path(){
|
||||
if [ "${1:0:1}" == "/" ]; then
|
||||
echo "$1"
|
||||
else
|
||||
echo "$(realpath -m $PWD/$1)"
|
||||
fi
|
||||
}
|
||||
model=$(get_real_path $1)
|
||||
data_path=$(get_real_path $2)
|
||||
label_path=$(get_real_path $3)
|
||||
|
||||
echo "air name: "$model
|
||||
echo "dataset path: "$data_path
|
||||
echo "label path: "$label_path
|
||||
|
||||
export ASCEND_HOME=/usr/local/Ascend/
|
||||
if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then
|
||||
export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe
|
||||
export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp
|
||||
else
|
||||
export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/opp
|
||||
fi
|
||||
|
||||
function air_to_om()
|
||||
{
|
||||
atc --input_format=NCHW --framework=1 --model=$model --output=crnn_quant --soc_version=Ascend310 &> atc.log
|
||||
}
|
||||
|
||||
function compile_app()
|
||||
{
|
||||
bash ./src/build.sh &> build.log
|
||||
}
|
||||
|
||||
function infer()
|
||||
{
|
||||
if [ -d result ]; then
|
||||
rm -rf ./result
|
||||
fi
|
||||
mkdir result
|
||||
./out/main ./crnn_quant.om $data_path &> infer.log
|
||||
}
|
||||
|
||||
function cal_acc()
|
||||
{
|
||||
python3.7 ./acc.py --result_path=./result --label_path=$label_path &> acc.log
|
||||
}
|
||||
|
||||
echo "start atc================================================"
|
||||
air_to_om
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "air to om code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start compile============================================"
|
||||
compile_app
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "compile app code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start infer=============================================="
|
||||
infer
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " execute inference failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start calculate acc======================================"
|
||||
cal_acc
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "calculate accuracy failed"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
|
||||
|
||||
# CMake lowest version requirement
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
# project information
|
||||
project(InferClassification)
|
||||
# Check environment variable
|
||||
if(NOT DEFINED ENV{ASCEND_HOME})
|
||||
message(FATAL_ERROR "please define environment variable:ASCEND_HOME")
|
||||
endif()
|
||||
|
||||
# Compile options
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined")
|
||||
|
||||
# Skip build rpath
|
||||
set(CMAKE_SKIP_BUILD_RPATH True)
|
||||
|
||||
# Set output directory
|
||||
set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/../out)
|
||||
|
||||
# Set include directory and library directory
|
||||
set(FWKACL_LIB_DIR $ENV{ASCEND_HOME}/fwkacllib)
|
||||
set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib)
|
||||
set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib)
|
||||
|
||||
# Header path
|
||||
include_directories(${ACL_LIB_DIR}/include/)
|
||||
include_directories(${FWKACL_LIB_DIR}/include/)
|
||||
include_directories(${ATLAS_ACL_LIB_DIR}/include/)
|
||||
include_directories(${PROJECT_SRC_ROOT}/../inc)
|
||||
|
||||
# add host lib path
|
||||
link_directories(${ACL_LIB_DIR} ${FWKACL_LIB_DIR})
|
||||
find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${FWKACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64)
|
||||
|
||||
add_executable(main utils.cpp
|
||||
sample_process.cpp
|
||||
model_process.cpp
|
||||
main.cpp)
|
||||
|
||||
target_link_libraries(main ${acl} gflags pthread)
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
path_cur=$(cd "`dirname $0`" || exit; pwd)
|
||||
|
||||
function preparePath() {
|
||||
rm -rf $1
|
||||
mkdir -p $1
|
||||
cd $1 || exit
|
||||
}
|
||||
|
||||
function buildA300() {
|
||||
if [ ! "${ARCH_PATTERN}" ]; then
|
||||
# set ARCH_PATTERN to acllib when it was not specified by user
|
||||
export ARCH_PATTERN=acllib
|
||||
echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}"
|
||||
else
|
||||
echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib"
|
||||
export ARCH_PATTERN=${ARCH_PATTERN}/acllib
|
||||
fi
|
||||
|
||||
path_build=$path_cur/build
|
||||
preparePath $path_build
|
||||
cmake ..
|
||||
make -j
|
||||
ret=$?
|
||||
cd ..
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user
|
||||
if [ ! "${ASCEND_VERSION}" ]; then
|
||||
export ASCEND_VERSION=ascend-toolkit/latest
|
||||
echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}"
|
||||
else
|
||||
echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user"
|
||||
fi
|
||||
|
||||
buildA300
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include "../inc/sample_process.h"
|
||||
#include "../inc/utils.h"
|
||||
bool g_is_device = false;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
ERROR_LOG("usage:./main path_of_om path_of_inputFolder");
|
||||
return FAILED;
|
||||
}
|
||||
SampleProcess processSample;
|
||||
Result ret = processSample.InitResource();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample init resource failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processSample.Process(argv[1], argv[2]);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample process failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("execute sample success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/model_process.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
|
||||
ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr),
|
||||
modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) {
|
||||
}
|
||||
|
||||
ModelProcess::~ModelProcess() {
|
||||
Unload();
|
||||
DestroyDesc();
|
||||
DestroyInput();
|
||||
DestroyOutput();
|
||||
}
|
||||
|
||||
Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) {
|
||||
if (loadFlag_) {
|
||||
ERROR_LOG("has already loaded a model");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("query model failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_,
|
||||
modelMemSize_, modelWeightPtr_, modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("load model from file failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
loadFlag_ = true;
|
||||
INFO_LOG("load model %s success", modelPath);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateDesc() {
|
||||
modelDesc_ = aclmdlCreateDesc();
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("create model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlGetDesc(modelDesc_, modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("get model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("create model description success");
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyDesc() {
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) {
|
||||
input_ = aclmdlCreateDataset();
|
||||
if (input_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize);
|
||||
if (inputData == nullptr) {
|
||||
ERROR_LOG("can't create data buffer, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlAddDatasetBuffer(input_, inputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("add input dataset buffer failed");
|
||||
aclDestroyDataBuffer(inputData);
|
||||
inputData = nullptr;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyInput() {
|
||||
if (input_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i);
|
||||
aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
aclmdlDestroyDataset(input_);
|
||||
input_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateOutput() {
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("no model description, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
output_ = aclmdlCreateDataset();
|
||||
if (output_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
size_t outputSize = aclmdlGetNumOutputs(modelDesc_);
|
||||
for (size_t i = 0; i < outputSize; ++i) {
|
||||
size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i);
|
||||
|
||||
void *outputBuffer = nullptr;
|
||||
aclError ret = aclrtMalloc(&outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't create data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlAddDatasetBuffer(output_, outputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't add data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
aclDestroyDataBuffer(outputData);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("create model output success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DumpModelOutputResult(char *output_name) {
|
||||
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);
|
||||
|
||||
for (size_t i = 0; i < outputNum; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "result/" << output_name << "_output_" << i << ".bin";
|
||||
std::string outputFileName = ss.str();
|
||||
FILE *outputFile = fopen(outputFileName.c_str(), "wb");
|
||||
if (outputFile) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void* outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
(void)aclrtFreeHost(outHostData);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(outHostData, len, sizeof(char), outputFile);
|
||||
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fwrite(data, len, sizeof(char), outputFile);
|
||||
}
|
||||
fclose(outputFile);
|
||||
outputFile = nullptr;
|
||||
} else {
|
||||
ERROR_LOG("create output file [%s] failed", outputFileName.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("dump data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::OutputModelResult() {
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void *outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
float *outData = NULL;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
outData = reinterpret_cast<float*>(outHostData);
|
||||
} else {
|
||||
outData = reinterpret_cast<float*>(data);
|
||||
}
|
||||
std::map<float, unsigned int, std::greater<float> > resultMap;
|
||||
for (unsigned int j = 0; j < len / sizeof(float); ++j) {
|
||||
resultMap[*outData] = j;
|
||||
outData++;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (auto it = resultMap.begin(); it != resultMap.end(); ++it) {
|
||||
// print top 5
|
||||
if (++cnt > 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first);
|
||||
}
|
||||
if (!g_is_device) {
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("output data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyOutput() {
|
||||
if (output_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
(void)aclrtFree(data);
|
||||
(void)aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
|
||||
(void)aclmdlDestroyDataset(output_);
|
||||
output_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::Execute() {
|
||||
aclError ret = aclmdlExecute(modelId_, input_, output_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("execute model failed, modelId is %u", modelId_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("model execute success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::Unload() {
|
||||
if (!loadFlag_) {
|
||||
WARN_LOG("no model had been loaded, unload failed");
|
||||
return;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlUnload(modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("unload model failed, modelId is %u", modelId_);
|
||||
}
|
||||
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
|
||||
if (modelMemPtr_ != nullptr) {
|
||||
aclrtFree(modelMemPtr_);
|
||||
modelMemPtr_ = nullptr;
|
||||
modelMemSize_ = 0;
|
||||
}
|
||||
|
||||
if (modelWeightPtr_ != nullptr) {
|
||||
aclrtFree(modelWeightPtr_);
|
||||
modelWeightPtr_ = nullptr;
|
||||
modelWeightSize_ = 0;
|
||||
}
|
||||
|
||||
loadFlag_ = false;
|
||||
INFO_LOG("unload model success, modelId is %u", modelId_);
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/sample_process.h"
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../inc/model_process.h"
|
||||
#include "acl/acl.h"
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) {
|
||||
}
|
||||
|
||||
SampleProcess::~SampleProcess() {
|
||||
DestroyResource();
|
||||
}
|
||||
|
||||
Result SampleProcess::InitResource() {
|
||||
// ACL init
|
||||
|
||||
const char *aclConfigPath = "./src/acl.json";
|
||||
aclError ret = aclInit(aclConfigPath);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl init failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("acl init success");
|
||||
|
||||
// open device
|
||||
ret = aclrtSetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl open device %d failed", deviceId_);
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("open device %d success", deviceId_);
|
||||
|
||||
// create context (set current)
|
||||
ret = aclrtCreateContext(&context_, deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create context failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create context success");
|
||||
|
||||
// create stream
|
||||
ret = aclrtCreateStream(&stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create stream failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create stream success");
|
||||
|
||||
// get run mode
|
||||
aclrtRunMode runMode;
|
||||
ret = aclrtGetRunMode(&runMode);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl get run mode failed");
|
||||
return FAILED;
|
||||
}
|
||||
g_is_device = (runMode == ACL_DEVICE);
|
||||
INFO_LOG("get run mode success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::GetAllFiles(std::string path, std::vector<string> *files) {
|
||||
DIR *pDir = NULL;
|
||||
struct dirent* ptr;
|
||||
if (!(pDir = opendir(path.c_str()))) {
|
||||
return;
|
||||
}
|
||||
while ((ptr = readdir(pDir)) != 0) {
|
||||
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
|
||||
files->push_back(path + "/" + ptr->d_name);
|
||||
}
|
||||
}
|
||||
closedir(pDir);
|
||||
}
|
||||
|
||||
Result SampleProcess::Process(char *om_path, char *input_folder) {
|
||||
// model init
|
||||
double second_to_millisecond = 1000;
|
||||
double second_to_microsecond = 1000000;
|
||||
|
||||
double whole_cost_time = 0.0;
|
||||
struct timeval start_global = {0};
|
||||
struct timeval end_global = {0};
|
||||
double startTimeMs_global = 0.0;
|
||||
double endTimeMs_global = 0.0;
|
||||
|
||||
gettimeofday(&start_global, nullptr);
|
||||
|
||||
ModelProcess processModel;
|
||||
const char* omModelPath = om_path;
|
||||
|
||||
Result ret = processModel.LoadModelFromFileWithMem(omModelPath);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute LoadModelFromFileWithMem failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateDesc();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateDesc failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateOutput();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateOutput failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
std::vector<string> testFile;
|
||||
GetAllFiles(input_folder, &testFile);
|
||||
|
||||
if (testFile.size() == 0) {
|
||||
WARN_LOG("no input data under folder");
|
||||
}
|
||||
|
||||
double model_cost_time = 0.0;
|
||||
double edge_to_edge_model_cost_time = 0.0;
|
||||
|
||||
for (size_t index = 0; index < testFile.size(); ++index) {
|
||||
INFO_LOG("start to process file:%s", testFile[index].c_str());
|
||||
// model process
|
||||
|
||||
struct timeval time_init = {0};
|
||||
double timeval_init = 0.0;
|
||||
gettimeofday(&time_init, nullptr);
|
||||
timeval_init = (time_init.tv_sec * second_to_microsecond + time_init.tv_usec) / second_to_millisecond;
|
||||
|
||||
uint32_t devBufferSize;
|
||||
void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize);
|
||||
if (picDevBuffer == nullptr) {
|
||||
ERROR_LOG("get pic device buffer failed,index is %zu", index);
|
||||
return FAILED;
|
||||
}
|
||||
ret = processModel.CreateInput(picDevBuffer, devBufferSize);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateInput failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
struct timeval start = {0};
|
||||
struct timeval end = {0};
|
||||
double startTimeMs = 0.0;
|
||||
double endTimeMs = 0.0;
|
||||
gettimeofday(&start, nullptr);
|
||||
startTimeMs = (start.tv_sec * second_to_microsecond + start.tv_usec) / second_to_millisecond;
|
||||
|
||||
ret = processModel.Execute();
|
||||
|
||||
gettimeofday(&end, nullptr);
|
||||
endTimeMs = (end.tv_sec * second_to_microsecond + end.tv_usec) / second_to_millisecond;
|
||||
|
||||
double cost_time = endTimeMs - startTimeMs;
|
||||
INFO_LOG("model infer time: %lf ms", cost_time);
|
||||
|
||||
model_cost_time += cost_time;
|
||||
|
||||
double edge_to_edge_cost_time = endTimeMs - timeval_init;
|
||||
edge_to_edge_model_cost_time += edge_to_edge_cost_time;
|
||||
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute inference failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
int pos = testFile[index].find_last_of('/');
|
||||
std::string name = testFile[index].substr(pos+1);
|
||||
std::string outputname = name.substr(0, name.rfind("."));
|
||||
|
||||
// dump output result to file in the current directory
|
||||
processModel.DumpModelOutputResult(const_cast<char *>(outputname.c_str()));
|
||||
|
||||
// release model input buffer
|
||||
aclrtFree(picDevBuffer);
|
||||
processModel.DestroyInput();
|
||||
}
|
||||
double test_file_size = 0.0;
|
||||
test_file_size = testFile.size();
|
||||
INFO_LOG("infer dataset size:%lf", test_file_size);
|
||||
|
||||
gettimeofday(&end_global, nullptr);
|
||||
startTimeMs_global = (start_global.tv_sec * second_to_microsecond + start_global.tv_usec) / second_to_millisecond;
|
||||
endTimeMs_global = (end_global.tv_sec * second_to_microsecond + end_global.tv_usec) / second_to_millisecond;
|
||||
whole_cost_time = (endTimeMs_global - startTimeMs_global) / test_file_size;
|
||||
|
||||
model_cost_time /= test_file_size;
|
||||
INFO_LOG("model cost time per sample: %lf ms", model_cost_time);
|
||||
edge_to_edge_model_cost_time /= test_file_size;
|
||||
INFO_LOG("edge-to-edge model cost time per sample:%lf ms", edge_to_edge_model_cost_time);
|
||||
INFO_LOG("whole cost time per sample: %lf ms", whole_cost_time);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::DestroyResource() {
|
||||
aclError ret;
|
||||
if (stream_ != nullptr) {
|
||||
ret = aclrtDestroyStream(stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy stream failed");
|
||||
}
|
||||
stream_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy stream");
|
||||
|
||||
if (context_ != nullptr) {
|
||||
ret = aclrtDestroyContext(context_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy context failed");
|
||||
}
|
||||
context_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy context");
|
||||
|
||||
ret = aclrtResetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("reset device failed");
|
||||
}
|
||||
INFO_LOG("end to reset device is %d", deviceId_);
|
||||
|
||||
ret = aclFinalize();
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("finalize acl failed");
|
||||
}
|
||||
INFO_LOG("end to finalize acl");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "acl/acl.h"
|
||||
|
||||
extern bool g_is_device;
|
||||
|
||||
void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) {
|
||||
struct stat sBuf;
|
||||
int fileStatus = stat(fileName.data(), &sBuf);
|
||||
if (fileStatus == -1) {
|
||||
ERROR_LOG("failed to get file");
|
||||
return nullptr;
|
||||
}
|
||||
if (S_ISREG(sBuf.st_mode) == 0) {
|
||||
ERROR_LOG("%s is not a file, please enter a file", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream binFile(fileName, std::ifstream::binary);
|
||||
if (binFile.is_open() == false) {
|
||||
ERROR_LOG("open file %s failed", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.end);
|
||||
uint32_t binFileBufferLen = binFile.tellg();
|
||||
if (binFileBufferLen == 0) {
|
||||
ERROR_LOG("binfile is empty, filename is %s", fileName.c_str());
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.beg);
|
||||
|
||||
void* binFileBufferData = nullptr;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc for binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
if (binFileBufferData == nullptr) {
|
||||
ERROR_LOG("malloc binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen);
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
binFile.read(static_cast<char *>(binFileBufferData), binFileBufferLen);
|
||||
binFile.close();
|
||||
*fileSize = binFileBufferLen;
|
||||
return binFileBufferData;
|
||||
}
|
||||
|
||||
void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize) {
|
||||
uint32_t inputHostBuffSize = 0;
|
||||
void* inputHostBuff = Utils::ReadBinFile(fileName, &inputHostBuffSize);
|
||||
if (inputHostBuff == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!g_is_device) {
|
||||
void *inBufferDev = nullptr;
|
||||
uint32_t inBufferSize = inputHostBuffSize;
|
||||
aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u",
|
||||
inBufferSize, inputHostBuffSize);
|
||||
aclrtFree(inBufferDev);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
*fileSize = inBufferSize;
|
||||
return inBufferDev;
|
||||
} else {
|
||||
*fileSize = inputHostBuffSize;
|
||||
return inputHostBuff;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
- [Inference Process](#inference-process)
|
||||
- [Usage](#usage-2)
|
||||
- [result](#result-2)
|
||||
- [Post Training Quantization](#post-training-quantization)
|
||||
- [Model Description](#model-description)
|
||||
- [Performance](#performance)
|
||||
- [Evaluation Performance](#evaluation-performance)
|
||||
|
|
@ -803,6 +804,40 @@ Inference result is saved in current path, you can find result in acc.log file.
|
|||
| :----------: | :-----: | :----: | :----: | :-----: | :-----: | :-------------: |
|
||||
| deeplab_v3 | | √ | | | 78.84 | 78.51 |
|
||||
|
||||
## [Post Training Quantization](#contents)
|
||||
|
||||
Relative executing script files reside in the directory "ascend310_quant_infer". Please implement following steps sequentially to complete post quantization.
|
||||
In this project, the model is set as deeplab_v3_s8.
|
||||
|
||||
1. Generate data of .bin format required for AIR model inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
python export_bin.py --model [MODEL] --data_root [DATA ROOT] --data_lst [DATA LST]
|
||||
```
|
||||
|
||||
2. Export quantized AIR model.
|
||||
|
||||
Post quantization of model requires special toolkits for exporting quantized AIR model. Please refer to [official website](https://www.hiascend.com/software/cann/community).
|
||||
|
||||
```shell
|
||||
python post_quant.py --model [MODEL] --data_root [DATA ROOT] --data_lst [DATA LST] --ckpt_file [CKPT_PATH]
|
||||
```
|
||||
|
||||
The quantized AIR file will be stored as "./results/deeplabv3_quant.air".
|
||||
|
||||
3. Implement inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
# Ascend310 quant inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [SHAPE_PATH]
|
||||
```
|
||||
|
||||
Inference result is saved in current path, you can find result like this in acc.log file.
|
||||
|
||||
```bash
|
||||
mean Iou 0.7854572371350974
|
||||
```
|
||||
|
||||
# [Model Description](#contents)
|
||||
|
||||
## [Performance](#contents)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
- [推理过程](#推理过程)
|
||||
- [用法](#用法-2)
|
||||
- [结果](#结果-2)
|
||||
- [训练后量化推理](#训练后量化推理)
|
||||
- [模型描述](#模型描述)
|
||||
- [性能](#性能)
|
||||
- [训练性能](#训练性能)
|
||||
|
|
@ -804,6 +805,40 @@ bash run_infer_310.sh [MINDIR_PATH] [DATA_PATH] [DATA_ROOT] [DATA_LIST] [DEVICE_
|
|||
| :----------: | :-----: | :----: | :----: | :-----: | :-----: | :-------------: |
|
||||
| deeplab_v3 | | √ | | | 78.84 | 78.51 |
|
||||
|
||||
## [训练后量化推理](#contents)
|
||||
|
||||
训练后量化推理的相关执行脚本文件在"ascend310_quant_infer"目录下,依次执行以下步骤实现训练后量化推理。
|
||||
本训练后量化工程的模型类型是deeplab_v3_s8。
|
||||
|
||||
1、生成Ascend310平台AIR模型推理需要的.bin格式数据。
|
||||
|
||||
```shell
|
||||
python export_bin.py --model [MODEL] --data_root [DATA ROOT] --data_lst [DATA LST]
|
||||
```
|
||||
|
||||
2、导出训练后量化的AIR格式模型。
|
||||
|
||||
导出训练后量化模型需要配套的量化工具包,参考[官方地址](https://www.hiascend.com/software/cann/community)
|
||||
|
||||
```shell
|
||||
python post_quant.py --model [MODEL] --data_root [DATA ROOT] --data_lst [DATA LST] --ckpt_file [CKPT_PATH]
|
||||
```
|
||||
|
||||
导出的模型会存储在./result/deeplabv3_quant.air。
|
||||
|
||||
3、在Ascend310执行推理量化模型。
|
||||
|
||||
```shell
|
||||
# Ascend310 inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [SHAPE_PATH]
|
||||
```
|
||||
|
||||
推理结果保存在脚本执行的当前路径,可以在acc.log中看到精度计算结果。
|
||||
|
||||
```bash
|
||||
mean Iou 0.7854572371350974
|
||||
```
|
||||
|
||||
# 模型描述
|
||||
|
||||
## 性能
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""post process for 310 inference"""
|
||||
import os
|
||||
import argparse
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import cv2
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="deeplabv3 accuracy calculation")
|
||||
parser.add_argument('--crop_size', type=int, default=513, help='crop size')
|
||||
parser.add_argument('--num_classes', type=int, default=21, help='number of classes')
|
||||
parser.add_argument('--result_path', type=str, default='./result', help='result Files path')
|
||||
parser.add_argument('--label_path', type=str, default='./01_label', help='result Files path')
|
||||
parser.add_argument('--shape_path', type=str, default='./shape.npy', help='path of image shape')
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
|
||||
def get_img_size(file_name):
|
||||
img = Image.open(file_name)
|
||||
return img.size
|
||||
|
||||
|
||||
def get_resized_size(org_h, org_w, long_size=513):
|
||||
if org_h > org_w:
|
||||
new_h = long_size
|
||||
new_w = int(1.0 * long_size * org_w / org_h)
|
||||
else:
|
||||
new_w = long_size
|
||||
new_h = int(1.0 * long_size * org_h / org_w)
|
||||
return new_h, new_w
|
||||
|
||||
|
||||
def cal_hist(a, b, n):
|
||||
k = (a >= 0) & (a < n)
|
||||
return np.bincount(n * a[k].astype(np.int32) + b[k], minlength=n ** 2).reshape(n, n)
|
||||
|
||||
|
||||
def acc_cal(result_path, label_path, shape_path):
|
||||
hist = np.zeros((args.num_classes, args.num_classes))
|
||||
mask_shape = np.load(shape_path)
|
||||
prefix = "deeplabv3_data_bs_1_"
|
||||
for i in range(len(mask_shape)):
|
||||
output = os.path.join(result_path, prefix + str(i) + "_output_0.bin")
|
||||
net_out = np.fromfile(output, np.float32).reshape(args.num_classes, args.crop_size, args.crop_size)
|
||||
ori_height, ori_width = mask_shape[i][0], mask_shape[i][1]
|
||||
resize_h, resize_w = get_resized_size(ori_height, ori_width)
|
||||
probs_ = net_out[:, :resize_h, :resize_w].transpose((1, 2, 0))
|
||||
probs_ = cv2.resize(probs_, (ori_width, ori_height))
|
||||
|
||||
result_msk = probs_.argmax(axis=2)
|
||||
label = os.path.join(label_path, prefix + str(i) + ".bin")
|
||||
mask = np.fromfile(label, np.uint8).reshape(mask_shape[i])
|
||||
|
||||
hist += cal_hist(mask.flatten(), result_msk.flatten(), args.num_classes)
|
||||
|
||||
print(hist)
|
||||
iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))
|
||||
print('per-class IoU', iu)
|
||||
print('mean IoU', np.nanmean(iu))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
acc_cal(args.result_path, args.label_path, args.shape_path)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
skip_layers:"network.resnet.layer4.0.downsample.0"
|
||||
skip_fusion_layers:"network.resnet.layer4.0.downsample.0"
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""generate data and label needed for AIR model inference"""
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
|
||||
prefix = "deeplabv3_data_bs_"
|
||||
data_path = "./data"
|
||||
if os.path.exists(data_path):
|
||||
shutil.rmtree(data_path)
|
||||
os.makedirs(data_path)
|
||||
|
||||
|
||||
def get_img_size(file_name):
|
||||
img = Image.open(file_name)
|
||||
return img.size
|
||||
|
||||
|
||||
def resize_long(img, long_size=513):
|
||||
h, w, _ = img.shape
|
||||
if h > w:
|
||||
new_h = long_size
|
||||
new_w = int(1.0 * long_size * w / h)
|
||||
else:
|
||||
new_w = long_size
|
||||
new_h = int(1.0 * long_size * h / w)
|
||||
imo = cv2.resize(img, (new_w, new_h))
|
||||
return imo
|
||||
|
||||
|
||||
def pre_process(args, img_, crop_size=513):
|
||||
# resize
|
||||
img_ = resize_long(img_, crop_size)
|
||||
resize_h, resize_w, _ = img_.shape
|
||||
|
||||
# mean, std
|
||||
image_mean = np.array(args.image_mean)
|
||||
image_std = np.array(args.image_std)
|
||||
img_ = (img_ - image_mean) / image_std
|
||||
|
||||
# pad to crop_size
|
||||
pad_h = crop_size - img_.shape[0]
|
||||
pad_w = crop_size - img_.shape[1]
|
||||
if pad_h > 0 or pad_w > 0:
|
||||
img_ = cv2.copyMakeBorder(img_, 0, pad_h, 0, pad_w, cv2.BORDER_CONSTANT, value=0)
|
||||
# hwc to chw
|
||||
img_ = img_.transpose((2, 0, 1))
|
||||
return img_, resize_h, resize_w
|
||||
|
||||
|
||||
def eval_batch(args, img_lst, crop_size, index):
|
||||
batch_size = len(img_lst)
|
||||
batch_img = np.zeros((batch_size, 3, crop_size, crop_size), dtype=np.float32)
|
||||
resize_hw = []
|
||||
for l in range(batch_size):
|
||||
img_ = img_lst[l]
|
||||
img_, resize_h, resize_w = pre_process(args, img_, crop_size)
|
||||
batch_img[l] = img_
|
||||
resize_hw.append([resize_h, resize_w])
|
||||
|
||||
batch_img = np.ascontiguousarray(batch_img)
|
||||
data_dir = os.path.join(data_path, "00_data")
|
||||
if not os.path.exists(data_dir):
|
||||
os.makedirs(data_dir)
|
||||
data_file = os.path.join(data_dir, prefix + str(batch_size) + "_" + str(index) + ".bin")
|
||||
batch_img.tofile(data_file)
|
||||
|
||||
def eval_batch_scales(args, img_lst, scales, base_crop_size, index):
|
||||
sizes_ = [int((base_crop_size - 1) * sc) + 1 for sc in scales]
|
||||
return eval_batch(args, img_lst, crop_size=sizes_[0], index=index)
|
||||
|
||||
|
||||
def generate_data():
|
||||
"""
|
||||
Generate data and label needed for AIR model inference at Ascend310 platform.
|
||||
"""
|
||||
config.scales = config.scales_list[config.scales_type]
|
||||
args = config
|
||||
# data list
|
||||
with open(args.data_lst) as f:
|
||||
img_lst = f.readlines()
|
||||
|
||||
# evaluate
|
||||
batch_img_lst = []
|
||||
batch_msk_lst = []
|
||||
shape_lst = []
|
||||
for i, line in enumerate(img_lst):
|
||||
img_path, msk_path = line.strip().split(" ")
|
||||
img_path = os.path.join(args.data_root, img_path)
|
||||
msk_path = os.path.join(args.data_root, msk_path)
|
||||
org_width, org_height = get_img_size(img_path)
|
||||
shape_lst.append([org_height, org_width])
|
||||
img_ = cv2.imread(img_path)
|
||||
msk_ = cv2.imread(msk_path, cv2.IMREAD_GRAYSCALE)
|
||||
batch_img_lst.append(img_)
|
||||
batch_msk_lst.append(msk_)
|
||||
eval_batch_scales(args, batch_img_lst, scales=args.scales, base_crop_size=args.crop_size, index=i)
|
||||
label_dir = os.path.join(data_path, "01_label")
|
||||
if not os.path.exists(label_dir):
|
||||
os.makedirs(label_dir)
|
||||
label_path = os.path.join(label_dir, prefix + str(len(batch_img_lst)) + "_" + str(i) + ".bin")
|
||||
msk_.tofile(label_path)
|
||||
batch_img_lst = []
|
||||
batch_msk_lst = []
|
||||
np.save(os.path.join(data_path, "shape.npy"), shape_lst)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from model_utils.config import config
|
||||
|
||||
generate_data()
|
||||
|
|
@ -0,0 +1 @@
|
|||
ConvBatchnormFusionPass:off
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* ModelProcess
|
||||
*/
|
||||
class ModelProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief load model from file with mem
|
||||
* @param [in] modelPath: model path
|
||||
* @return result
|
||||
*/
|
||||
Result LoadModelFromFileWithMem(const char *modelPath);
|
||||
|
||||
/**
|
||||
* @brief unload model
|
||||
*/
|
||||
void Unload();
|
||||
|
||||
/**
|
||||
* @brief create model desc
|
||||
* @return result
|
||||
*/
|
||||
Result CreateDesc();
|
||||
|
||||
/**
|
||||
* @brief destroy desc
|
||||
*/
|
||||
void DestroyDesc();
|
||||
|
||||
/**
|
||||
* @brief create model input
|
||||
* @param [in] inputDataBuffer: input buffer
|
||||
* @param [in] bufferSize: input buffer size
|
||||
* @return result
|
||||
*/
|
||||
Result CreateInput(void *inputDataBuffer, size_t bufferSize);
|
||||
|
||||
/**
|
||||
* @brief destroy input resource
|
||||
*/
|
||||
void DestroyInput();
|
||||
|
||||
/**
|
||||
* @brief create output buffer
|
||||
* @return result
|
||||
*/
|
||||
Result CreateOutput();
|
||||
|
||||
/**
|
||||
* @brief destroy output resource
|
||||
*/
|
||||
void DestroyOutput();
|
||||
|
||||
/**
|
||||
* @brief model execute
|
||||
* @return result
|
||||
*/
|
||||
Result Execute();
|
||||
|
||||
/**
|
||||
* @brief dump model output result to file
|
||||
*/
|
||||
void DumpModelOutputResult(char *output_name);
|
||||
|
||||
/**
|
||||
* @brief get model output result
|
||||
*/
|
||||
void OutputModelResult();
|
||||
|
||||
private:
|
||||
uint32_t modelId_;
|
||||
size_t modelMemSize_;
|
||||
size_t modelWeightSize_;
|
||||
void *modelMemPtr_;
|
||||
void *modelWeightPtr_;
|
||||
bool loadFlag_; // model load flag
|
||||
aclmdlDesc *modelDesc_;
|
||||
aclmdlDataset *input_;
|
||||
aclmdlDataset *output_;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* SampleProcess
|
||||
*/
|
||||
class SampleProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief init reousce
|
||||
* @return result
|
||||
*/
|
||||
Result InitResource();
|
||||
|
||||
/**
|
||||
* @brief sample process
|
||||
* @return result
|
||||
*/
|
||||
Result Process(char *om_path, char *input_folder);
|
||||
|
||||
void GetAllFiles(std::string path, std::vector<std::string> *files);
|
||||
|
||||
private:
|
||||
void DestroyResource();
|
||||
|
||||
int32_t deviceId_;
|
||||
aclrtContext context_;
|
||||
aclrtStream stream_;
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args)
|
||||
#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args)
|
||||
#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args)
|
||||
|
||||
typedef enum Result {
|
||||
SUCCESS = 0,
|
||||
FAILED = 1
|
||||
} Result;
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
class Utils {
|
||||
public:
|
||||
/**
|
||||
* @brief create device buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return device buffer of file
|
||||
*/
|
||||
static void *GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize);
|
||||
|
||||
/**
|
||||
* @brief create buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return buffer of pic
|
||||
*/
|
||||
static void* ReadBinFile(std::string fileName, uint32_t *fileSize);
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""do post training quantization for Ascend310"""
|
||||
import os
|
||||
import sys
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from amct_mindspore.quantize_tool import create_quant_config
|
||||
from amct_mindspore.quantize_tool import quantize_model
|
||||
from amct_mindspore.quantize_tool import save_model
|
||||
import mindspore.nn as nn
|
||||
import mindspore.ops as ops
|
||||
from mindspore import Tensor, context
|
||||
from mindspore.train.serialization import load_checkpoint, load_param_into_net
|
||||
|
||||
|
||||
def resize_long(img, long_size=513):
|
||||
h, w, _ = img.shape
|
||||
if h > w:
|
||||
new_h = long_size
|
||||
new_w = int(1.0 * long_size * w / h)
|
||||
else:
|
||||
new_w = long_size
|
||||
new_h = int(1.0 * long_size * h / w)
|
||||
imo = cv2.resize(img, (new_w, new_h))
|
||||
return imo
|
||||
|
||||
|
||||
def pre_process(args, img_, crop_size=513):
|
||||
# resize
|
||||
img_ = resize_long(img_, crop_size)
|
||||
resize_h, resize_w, _ = img_.shape
|
||||
|
||||
# mean, std
|
||||
image_mean = np.array(args.image_mean)
|
||||
image_std = np.array(args.image_std)
|
||||
img_ = (img_ - image_mean) / image_std
|
||||
|
||||
# pad to crop_size
|
||||
pad_h = crop_size - img_.shape[0]
|
||||
pad_w = crop_size - img_.shape[1]
|
||||
if pad_h > 0 or pad_w > 0:
|
||||
img_ = cv2.copyMakeBorder(img_, 0, pad_h, 0, pad_w, cv2.BORDER_CONSTANT, value=0)
|
||||
# hwc to chw
|
||||
img_ = img_.transpose((2, 0, 1))
|
||||
return img_, resize_h, resize_w
|
||||
|
||||
|
||||
def eval_batch(args, img_lst, crop_size=513):
|
||||
batch_size = len(img_lst)
|
||||
batch_img = np.zeros((batch_size, 3, crop_size, crop_size), dtype=np.float32)
|
||||
resize_hw = []
|
||||
for l in range(batch_size):
|
||||
img_ = img_lst[l]
|
||||
img_, resize_h, resize_w = pre_process(args, img_, crop_size)
|
||||
batch_img[l] = img_
|
||||
resize_hw.append([resize_h, resize_w])
|
||||
|
||||
batch_img = np.ascontiguousarray(batch_img)
|
||||
return batch_img
|
||||
|
||||
|
||||
def eval_batch_scales(args, img_lst, scales, base_crop_size):
|
||||
sizes_ = [int((base_crop_size - 1) * sc) + 1 for sc in scales]
|
||||
return eval_batch(args, img_lst, crop_size=sizes_[0])
|
||||
|
||||
|
||||
def generate_batch_data():
|
||||
config.scales = config.scales_list[config.scales_type]
|
||||
args = config
|
||||
# data list
|
||||
with open(args.data_lst) as f:
|
||||
img_lst = f.readlines()
|
||||
|
||||
# evaluate
|
||||
batch_img_lst = []
|
||||
img_path, _ = img_lst[0].strip().split(" ")
|
||||
img_path = os.path.join(args.data_root, img_path)
|
||||
img_ = cv2.imread(img_path)
|
||||
batch_img_lst.append(img_)
|
||||
return eval_batch_scales(args, batch_img_lst, scales=args.scales, base_crop_size=args.crop_size)
|
||||
|
||||
|
||||
def quant_deeplabv3(network, dataset, input_data):
|
||||
"""
|
||||
Export post training quantization model of AIR format.
|
||||
|
||||
Args:
|
||||
network: the origin network for inference.
|
||||
dataset: the data for inference.
|
||||
input_data: the data used for constructing network. The shape and format of input data should be the same as
|
||||
actual data for inference.
|
||||
"""
|
||||
|
||||
# step2: create the quant config json file
|
||||
create_quant_config("./config.json", network, input_data, config_defination="./config.cfg")
|
||||
# There is value beyond 1e30 in this layer. So this layer will not be quantized.
|
||||
|
||||
# step3: do some network modification and return the modified network
|
||||
calibration_network = quantize_model("./config.json", network, input_data)
|
||||
calibration_network.set_train(False)
|
||||
|
||||
# step4: perform the evaluation of network to do activation calibration
|
||||
_ = calibration_network(Tensor(dataset))
|
||||
|
||||
# step5: export the air file
|
||||
save_model("results/deeplabv3_quant", calibration_network, input_data)
|
||||
print("[INFO] the quantized AIR file has been stored at: \n {}".format("results/deeplabv3_quant.air"))
|
||||
|
||||
|
||||
class BuildEvalNetwork(nn.Cell):
|
||||
def __init__(self, net, input_format="NCHW"):
|
||||
super(BuildEvalNetwork, self).__init__()
|
||||
self.network = net
|
||||
self.softmax = nn.Softmax(axis=1)
|
||||
self.transpose = ops.Transpose()
|
||||
self.format = input_format
|
||||
|
||||
def construct(self, x):
|
||||
if self.format == "NHWC":
|
||||
x = self.transpose(x, (0, 3, 1, 2))
|
||||
output = self.network(x)
|
||||
output = self.softmax(output)
|
||||
return output
|
||||
|
||||
|
||||
def run_export():
|
||||
'''run export.'''
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target=config.device_target)
|
||||
config.freeze_bn = True
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=config.device_id)
|
||||
|
||||
if config.export_model == 'deeplab_v3_s16':
|
||||
network = net_factory.nets_map['deeplab_v3_s16']('eval', config.num_classes, 16, True)
|
||||
else:
|
||||
network = net_factory.nets_map['deeplab_v3_s8']('eval', config.num_classes, 8, True)
|
||||
network = BuildEvalNetwork(network, config.input_format)
|
||||
param_dict = load_checkpoint(config.ckpt_file)
|
||||
|
||||
# load the parameter into net
|
||||
load_param_into_net(network, param_dict)
|
||||
batch_size = 1
|
||||
if config.input_format == "NHWC":
|
||||
input_data = Tensor(
|
||||
np.ones([batch_size, config.input_size, config.input_size, 3]).astype(np.float32))
|
||||
else:
|
||||
input_data = Tensor(
|
||||
np.ones([batch_size, 3, config.input_size, config.input_size]).astype(np.float32))
|
||||
batch_data = generate_batch_data()
|
||||
quant_deeplabv3(network, batch_data, input_data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from src.nets import net_factory
|
||||
from model_utils.config import config
|
||||
|
||||
run_export()
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
if [ $# -lt 4 ]; then
|
||||
echo "Usage: bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [SHAPE_PATH]"
|
||||
echo "Example: bash run_quant_infer.sh ./deeplabv3_quant.air ./00_data ./01_label ./shape.npy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_real_path(){
|
||||
if [ "${1:0:1}" == "/" ]; then
|
||||
echo "$1"
|
||||
else
|
||||
echo "$(realpath -m $PWD/$1)"
|
||||
fi
|
||||
}
|
||||
model=$(get_real_path $1)
|
||||
data_path=$(get_real_path $2)
|
||||
label_path=$(get_real_path $3)
|
||||
shape_path=$(get_real_path $4)
|
||||
|
||||
echo "air name: "$model
|
||||
echo "dataset path: "$data_path
|
||||
echo "label path: "$label_path
|
||||
echo "shape path: "$shape_path
|
||||
|
||||
export ASCEND_HOME=/usr/local/Ascend/
|
||||
if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then
|
||||
export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe
|
||||
export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp
|
||||
else
|
||||
export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/opp
|
||||
fi
|
||||
|
||||
function air_to_om()
|
||||
{
|
||||
atc --input_format=NCHW --framework=1 --model=$model --output=deeplabv3_quant --soc_version=Ascend310 --fusion_switch_file=./fusion_switch.cfg &> atc.log
|
||||
}
|
||||
|
||||
function compile_app()
|
||||
{
|
||||
bash ./src/build.sh &> build.log
|
||||
}
|
||||
|
||||
function infer()
|
||||
{
|
||||
if [ -d result ]; then
|
||||
rm -rf ./result
|
||||
fi
|
||||
mkdir result
|
||||
./out/main ./deeplabv3_quant.om $data_path &> infer.log
|
||||
}
|
||||
|
||||
function cal_acc()
|
||||
{
|
||||
python3.7 ./acc.py --result_path=./result --label_path=$label_path --shape_path=$shape_path &> acc.log
|
||||
}
|
||||
|
||||
echo "start atc================================================"
|
||||
air_to_om
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "air to om code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start compile============================================"
|
||||
compile_app
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "compile app code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start infer=============================================="
|
||||
infer
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " execute inference failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start calculate acc======================================"
|
||||
cal_acc
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "calculate accuracy failed"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
|
||||
|
||||
# CMake lowest version requirement
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
# project information
|
||||
project(InferClassification)
|
||||
# Check environment variable
|
||||
if(NOT DEFINED ENV{ASCEND_HOME})
|
||||
message(FATAL_ERROR "please define environment variable:ASCEND_HOME")
|
||||
endif()
|
||||
|
||||
# Compile options
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined")
|
||||
|
||||
# Skip build rpath
|
||||
set(CMAKE_SKIP_BUILD_RPATH True)
|
||||
|
||||
# Set output directory
|
||||
set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/../out)
|
||||
|
||||
# Set include directory and library directory
|
||||
set(FWKACL_LIB_DIR $ENV{ASCEND_HOME}/fwkacllib)
|
||||
set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib)
|
||||
set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib)
|
||||
|
||||
# Header path
|
||||
include_directories(${ACL_LIB_DIR}/include/)
|
||||
include_directories(${FWKACL_LIB_DIR}/include/)
|
||||
include_directories(${ATLAS_ACL_LIB_DIR}/include/)
|
||||
include_directories(${PROJECT_SRC_ROOT}/../inc)
|
||||
|
||||
# add host lib path
|
||||
link_directories(${ACL_LIB_DIR} ${FWKACL_LIB_DIR})
|
||||
find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${FWKACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64)
|
||||
|
||||
add_executable(main utils.cpp
|
||||
sample_process.cpp
|
||||
model_process.cpp
|
||||
main.cpp)
|
||||
|
||||
target_link_libraries(main ${acl} gflags pthread)
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
path_cur=$(cd "`dirname $0`" || exit; pwd)
|
||||
|
||||
function preparePath() {
|
||||
rm -rf $1
|
||||
mkdir -p $1
|
||||
cd $1 || exit
|
||||
}
|
||||
|
||||
function buildA300() {
|
||||
if [ ! "${ARCH_PATTERN}" ]; then
|
||||
# set ARCH_PATTERN to acllib when it was not specified by user
|
||||
export ARCH_PATTERN=acllib
|
||||
echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}"
|
||||
else
|
||||
echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib"
|
||||
export ARCH_PATTERN=${ARCH_PATTERN}/acllib
|
||||
fi
|
||||
|
||||
path_build=$path_cur/build
|
||||
preparePath $path_build
|
||||
cmake ..
|
||||
make -j
|
||||
ret=$?
|
||||
cd ..
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user
|
||||
if [ ! "${ASCEND_VERSION}" ]; then
|
||||
export ASCEND_VERSION=ascend-toolkit/latest
|
||||
echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}"
|
||||
else
|
||||
echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user"
|
||||
fi
|
||||
|
||||
buildA300
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include "../inc/sample_process.h"
|
||||
#include "../inc/utils.h"
|
||||
bool g_is_device = false;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
ERROR_LOG("usage:./main path_of_om path_of_inputFolder");
|
||||
return FAILED;
|
||||
}
|
||||
SampleProcess processSample;
|
||||
Result ret = processSample.InitResource();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample init resource failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processSample.Process(argv[1], argv[2]);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample process failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("execute sample success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/model_process.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
|
||||
ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr),
|
||||
modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) {
|
||||
}
|
||||
|
||||
ModelProcess::~ModelProcess() {
|
||||
Unload();
|
||||
DestroyDesc();
|
||||
DestroyInput();
|
||||
DestroyOutput();
|
||||
}
|
||||
|
||||
Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) {
|
||||
if (loadFlag_) {
|
||||
ERROR_LOG("has already loaded a model");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("query model failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_,
|
||||
modelMemSize_, modelWeightPtr_, modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("load model from file failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
loadFlag_ = true;
|
||||
INFO_LOG("load model %s success", modelPath);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateDesc() {
|
||||
modelDesc_ = aclmdlCreateDesc();
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("create model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlGetDesc(modelDesc_, modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("get model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("create model description success");
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyDesc() {
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) {
|
||||
input_ = aclmdlCreateDataset();
|
||||
if (input_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize);
|
||||
if (inputData == nullptr) {
|
||||
ERROR_LOG("can't create data buffer, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlAddDatasetBuffer(input_, inputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("add input dataset buffer failed");
|
||||
aclDestroyDataBuffer(inputData);
|
||||
inputData = nullptr;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyInput() {
|
||||
if (input_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i);
|
||||
aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
aclmdlDestroyDataset(input_);
|
||||
input_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateOutput() {
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("no model description, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
output_ = aclmdlCreateDataset();
|
||||
if (output_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
size_t outputSize = aclmdlGetNumOutputs(modelDesc_);
|
||||
for (size_t i = 0; i < outputSize; ++i) {
|
||||
size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i);
|
||||
|
||||
void *outputBuffer = nullptr;
|
||||
aclError ret = aclrtMalloc(&outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't create data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlAddDatasetBuffer(output_, outputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't add data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
aclDestroyDataBuffer(outputData);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("create model output success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DumpModelOutputResult(char *output_name) {
|
||||
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);
|
||||
|
||||
for (size_t i = 0; i < outputNum; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "result/" << output_name << "_output_" << i << ".bin";
|
||||
std::string outputFileName = ss.str();
|
||||
FILE *outputFile = fopen(outputFileName.c_str(), "wb");
|
||||
if (outputFile) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void* outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
(void)aclrtFreeHost(outHostData);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(outHostData, len, sizeof(char), outputFile);
|
||||
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fwrite(data, len, sizeof(char), outputFile);
|
||||
}
|
||||
fclose(outputFile);
|
||||
outputFile = nullptr;
|
||||
} else {
|
||||
ERROR_LOG("create output file [%s] failed", outputFileName.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("dump data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::OutputModelResult() {
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void *outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
float *outData = NULL;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
outData = reinterpret_cast<float*>(outHostData);
|
||||
} else {
|
||||
outData = reinterpret_cast<float*>(data);
|
||||
}
|
||||
std::map<float, unsigned int, std::greater<float> > resultMap;
|
||||
for (unsigned int j = 0; j < len / sizeof(float); ++j) {
|
||||
resultMap[*outData] = j;
|
||||
outData++;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (auto it = resultMap.begin(); it != resultMap.end(); ++it) {
|
||||
// print top 5
|
||||
if (++cnt > 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first);
|
||||
}
|
||||
if (!g_is_device) {
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("output data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyOutput() {
|
||||
if (output_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
(void)aclrtFree(data);
|
||||
(void)aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
|
||||
(void)aclmdlDestroyDataset(output_);
|
||||
output_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::Execute() {
|
||||
aclError ret = aclmdlExecute(modelId_, input_, output_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("execute model failed, modelId is %u", modelId_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("model execute success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::Unload() {
|
||||
if (!loadFlag_) {
|
||||
WARN_LOG("no model had been loaded, unload failed");
|
||||
return;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlUnload(modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("unload model failed, modelId is %u", modelId_);
|
||||
}
|
||||
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
|
||||
if (modelMemPtr_ != nullptr) {
|
||||
aclrtFree(modelMemPtr_);
|
||||
modelMemPtr_ = nullptr;
|
||||
modelMemSize_ = 0;
|
||||
}
|
||||
|
||||
if (modelWeightPtr_ != nullptr) {
|
||||
aclrtFree(modelWeightPtr_);
|
||||
modelWeightPtr_ = nullptr;
|
||||
modelWeightSize_ = 0;
|
||||
}
|
||||
|
||||
loadFlag_ = false;
|
||||
INFO_LOG("unload model success, modelId is %u", modelId_);
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/sample_process.h"
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../inc/model_process.h"
|
||||
#include "acl/acl.h"
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) {
|
||||
}
|
||||
|
||||
SampleProcess::~SampleProcess() {
|
||||
DestroyResource();
|
||||
}
|
||||
|
||||
Result SampleProcess::InitResource() {
|
||||
// ACL init
|
||||
|
||||
const char *aclConfigPath = "./src/acl.json";
|
||||
aclError ret = aclInit(aclConfigPath);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl init failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("acl init success");
|
||||
|
||||
// open device
|
||||
ret = aclrtSetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl open device %d failed", deviceId_);
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("open device %d success", deviceId_);
|
||||
|
||||
// create context (set current)
|
||||
ret = aclrtCreateContext(&context_, deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create context failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create context success");
|
||||
|
||||
// create stream
|
||||
ret = aclrtCreateStream(&stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create stream failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create stream success");
|
||||
|
||||
// get run mode
|
||||
aclrtRunMode runMode;
|
||||
ret = aclrtGetRunMode(&runMode);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl get run mode failed");
|
||||
return FAILED;
|
||||
}
|
||||
g_is_device = (runMode == ACL_DEVICE);
|
||||
INFO_LOG("get run mode success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::GetAllFiles(std::string path, std::vector<string> *files) {
|
||||
DIR *pDir = NULL;
|
||||
struct dirent* ptr;
|
||||
if (!(pDir = opendir(path.c_str()))) {
|
||||
return;
|
||||
}
|
||||
while ((ptr = readdir(pDir)) != 0) {
|
||||
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
|
||||
files->push_back(path + "/" + ptr->d_name);
|
||||
}
|
||||
}
|
||||
closedir(pDir);
|
||||
}
|
||||
|
||||
Result SampleProcess::Process(char *om_path, char *input_folder) {
|
||||
// model init
|
||||
double second_to_millisecond = 1000;
|
||||
double second_to_microsecond = 1000000;
|
||||
|
||||
double whole_cost_time = 0.0;
|
||||
struct timeval start_global = {0};
|
||||
struct timeval end_global = {0};
|
||||
double startTimeMs_global = 0.0;
|
||||
double endTimeMs_global = 0.0;
|
||||
|
||||
gettimeofday(&start_global, nullptr);
|
||||
|
||||
ModelProcess processModel;
|
||||
const char* omModelPath = om_path;
|
||||
|
||||
Result ret = processModel.LoadModelFromFileWithMem(omModelPath);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute LoadModelFromFileWithMem failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateDesc();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateDesc failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateOutput();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateOutput failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
std::vector<string> testFile;
|
||||
GetAllFiles(input_folder, &testFile);
|
||||
|
||||
if (testFile.size() == 0) {
|
||||
WARN_LOG("no input data under folder");
|
||||
}
|
||||
|
||||
double model_cost_time = 0.0;
|
||||
double edge_to_edge_model_cost_time = 0.0;
|
||||
|
||||
for (size_t index = 0; index < testFile.size(); ++index) {
|
||||
INFO_LOG("start to process file:%s", testFile[index].c_str());
|
||||
// model process
|
||||
|
||||
struct timeval time_init = {0};
|
||||
double timeval_init = 0.0;
|
||||
gettimeofday(&time_init, nullptr);
|
||||
timeval_init = (time_init.tv_sec * second_to_microsecond + time_init.tv_usec) / second_to_millisecond;
|
||||
|
||||
uint32_t devBufferSize;
|
||||
void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize);
|
||||
if (picDevBuffer == nullptr) {
|
||||
ERROR_LOG("get pic device buffer failed,index is %zu", index);
|
||||
return FAILED;
|
||||
}
|
||||
ret = processModel.CreateInput(picDevBuffer, devBufferSize);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateInput failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
struct timeval start = {0};
|
||||
struct timeval end = {0};
|
||||
double startTimeMs = 0.0;
|
||||
double endTimeMs = 0.0;
|
||||
gettimeofday(&start, nullptr);
|
||||
startTimeMs = (start.tv_sec * second_to_microsecond + start.tv_usec) / second_to_millisecond;
|
||||
|
||||
ret = processModel.Execute();
|
||||
|
||||
gettimeofday(&end, nullptr);
|
||||
endTimeMs = (end.tv_sec * second_to_microsecond + end.tv_usec) / second_to_millisecond;
|
||||
|
||||
double cost_time = endTimeMs - startTimeMs;
|
||||
INFO_LOG("model infer time: %lf ms", cost_time);
|
||||
|
||||
model_cost_time += cost_time;
|
||||
|
||||
double edge_to_edge_cost_time = endTimeMs - timeval_init;
|
||||
edge_to_edge_model_cost_time += edge_to_edge_cost_time;
|
||||
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute inference failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
int pos = testFile[index].find_last_of('/');
|
||||
std::string name = testFile[index].substr(pos+1);
|
||||
std::string outputname = name.substr(0, name.rfind("."));
|
||||
|
||||
// dump output result to file in the current directory
|
||||
processModel.DumpModelOutputResult(const_cast<char *>(outputname.c_str()));
|
||||
|
||||
// release model input buffer
|
||||
aclrtFree(picDevBuffer);
|
||||
processModel.DestroyInput();
|
||||
}
|
||||
double test_file_size = 0.0;
|
||||
test_file_size = testFile.size();
|
||||
INFO_LOG("infer dataset size:%lf", test_file_size);
|
||||
|
||||
gettimeofday(&end_global, nullptr);
|
||||
startTimeMs_global = (start_global.tv_sec * second_to_microsecond + start_global.tv_usec) / second_to_millisecond;
|
||||
endTimeMs_global = (end_global.tv_sec * second_to_microsecond + end_global.tv_usec) / second_to_millisecond;
|
||||
whole_cost_time = (endTimeMs_global - startTimeMs_global) / test_file_size;
|
||||
|
||||
model_cost_time /= test_file_size;
|
||||
INFO_LOG("model cost time per sample: %lf ms", model_cost_time);
|
||||
edge_to_edge_model_cost_time /= test_file_size;
|
||||
INFO_LOG("edge-to-edge model cost time per sample:%lf ms", edge_to_edge_model_cost_time);
|
||||
INFO_LOG("whole cost time per sample: %lf ms", whole_cost_time);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::DestroyResource() {
|
||||
aclError ret;
|
||||
if (stream_ != nullptr) {
|
||||
ret = aclrtDestroyStream(stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy stream failed");
|
||||
}
|
||||
stream_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy stream");
|
||||
|
||||
if (context_ != nullptr) {
|
||||
ret = aclrtDestroyContext(context_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy context failed");
|
||||
}
|
||||
context_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy context");
|
||||
|
||||
ret = aclrtResetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("reset device failed");
|
||||
}
|
||||
INFO_LOG("end to reset device is %d", deviceId_);
|
||||
|
||||
ret = aclFinalize();
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("finalize acl failed");
|
||||
}
|
||||
INFO_LOG("end to finalize acl");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "acl/acl.h"
|
||||
|
||||
extern bool g_is_device;
|
||||
|
||||
void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) {
|
||||
struct stat sBuf;
|
||||
int fileStatus = stat(fileName.data(), &sBuf);
|
||||
if (fileStatus == -1) {
|
||||
ERROR_LOG("failed to get file");
|
||||
return nullptr;
|
||||
}
|
||||
if (S_ISREG(sBuf.st_mode) == 0) {
|
||||
ERROR_LOG("%s is not a file, please enter a file", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream binFile(fileName, std::ifstream::binary);
|
||||
if (binFile.is_open() == false) {
|
||||
ERROR_LOG("open file %s failed", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.end);
|
||||
uint32_t binFileBufferLen = binFile.tellg();
|
||||
if (binFileBufferLen == 0) {
|
||||
ERROR_LOG("binfile is empty, filename is %s", fileName.c_str());
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.beg);
|
||||
|
||||
void* binFileBufferData = nullptr;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc for binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
if (binFileBufferData == nullptr) {
|
||||
ERROR_LOG("malloc binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen);
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
binFile.read(static_cast<char *>(binFileBufferData), binFileBufferLen);
|
||||
binFile.close();
|
||||
*fileSize = binFileBufferLen;
|
||||
return binFileBufferData;
|
||||
}
|
||||
|
||||
void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize) {
|
||||
uint32_t inputHostBuffSize = 0;
|
||||
void* inputHostBuff = Utils::ReadBinFile(fileName, &inputHostBuffSize);
|
||||
if (inputHostBuff == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!g_is_device) {
|
||||
void *inBufferDev = nullptr;
|
||||
uint32_t inBufferSize = inputHostBuffSize;
|
||||
aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u",
|
||||
inBufferSize, inputHostBuffSize);
|
||||
aclrtFree(inBufferDev);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
*fileSize = inBufferSize;
|
||||
return inBufferDev;
|
||||
} else {
|
||||
*fileSize = inputHostBuffSize;
|
||||
return inputHostBuff;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
- [Inference Process](#inference-process)
|
||||
- [Usage](#usage)
|
||||
- [result](#result)
|
||||
- [Post Training Quantization](#post-training-quantization)
|
||||
- [Model Description](#model-description)
|
||||
- [Performance](#performance)
|
||||
- [Evaluation Performance](#evaluation-performance)
|
||||
|
|
@ -701,6 +702,69 @@ Accumulating evaluation results...
|
|||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.594
|
||||
```
|
||||
|
||||
## [Post Training Quantization](#contents)
|
||||
|
||||
Relative executing script files reside in the directory "ascend310_quant_infer". Please implement following steps sequentially to complete post quantization.
|
||||
Current quantization project bases on COCO2017 dataset.
|
||||
The inference process needs about 600G hard disk space to save the reasoning results.
|
||||
|
||||
1. Generate data of .bin format required for AIR model inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
python export_bin.py --coco_root [COCO DATA PATH] --mindrecord_dir [MINDRECORD PATH] --ann_file [ANNOTATION PATH]
|
||||
```
|
||||
|
||||
2. Export quantized AIR model.
|
||||
|
||||
Post quantization of model requires special toolkits for exporting quantized AIR model. Please refer to [official website](https://www.hiascend.com/software/cann/community).
|
||||
|
||||
```shell
|
||||
python post_quant.py --coco_root [COCO DATA PATH] --mindrecord_dir [MINDRECORD PATH] --ckpt_file [CKPT_PATH]
|
||||
```
|
||||
|
||||
The quantized AIR file will be stored as "./results/maskrcnn_quant.air".
|
||||
|
||||
3. Implement inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
# Ascend310 quant inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [SHAPE_PATH] [ANNOTATION_PATH]
|
||||
```
|
||||
|
||||
Inference result is saved in current path, you can find result like this in acc.log file.
|
||||
|
||||
```bash
|
||||
Evaluate annotation type *bbox*
|
||||
Accumulating evaluation results...
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.378
|
||||
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.602
|
||||
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.407
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.240
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.420
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.481
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.311
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.500
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.528
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.367
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.572
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.657
|
||||
|
||||
Evaluate annotation type *segm*
|
||||
Accumulating evaluation results...
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.321
|
||||
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.553
|
||||
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.328
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.164
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.350
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.466
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.276
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.422
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.441
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.279
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.476
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.578
|
||||
```
|
||||
|
||||
# Model Description
|
||||
|
||||
## Performance
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
- [推理过程](#推理过程)
|
||||
- [使用方法](#使用方法)
|
||||
- [结果](#结果)
|
||||
- [训练后量化推理](#训练后量化推理)
|
||||
- [模型说明](#模型说明)
|
||||
- [性能](#性能)
|
||||
- [训练性能](#训练性能)
|
||||
|
|
@ -696,6 +697,68 @@ Accumulating evaluation results...
|
|||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.594
|
||||
```
|
||||
|
||||
## [训练后量化推理](#contents)
|
||||
|
||||
训练后量化推理的相关执行脚本文件在"ascend310_quant_infer"目录下,依次执行以下步骤实现训练后量化推理。本训练后量化工程基于COCO2017数据集。
|
||||
推理过程需要占用大约600G的硬盘空间来保存推理的结果。
|
||||
|
||||
1、生成Ascend310平台AIR模型推理需要的.bin格式数据。
|
||||
|
||||
```shell
|
||||
python export_bin.py --coco_root [COCO DATA PATH] --mindrecord_dir [MINDRECORD PATH] --ann_file [ANNOTATION PATH]
|
||||
```
|
||||
|
||||
2、导出训练后量化的AIR格式模型。
|
||||
|
||||
导出训练后量化模型需要配套的量化工具包,参考[官方地址](https://www.hiascend.com/software/cann/community)
|
||||
|
||||
```shell
|
||||
python post_quant.py --coco_root [COCO DATA PATH] --mindrecord_dir [MINDRECORD PATH] --ckpt_file [CKPT_PATH]
|
||||
```
|
||||
|
||||
导出的模型会存储在./result/maskrcnn_quant.air。
|
||||
|
||||
3、在Ascend310执行推理量化模型。
|
||||
|
||||
```shell
|
||||
# Ascend310 inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [SHAPE_PATH] [ANNOTATION_PATH]
|
||||
```
|
||||
|
||||
推理结果保存在脚本执行的当前路径,可以在acc.log中看到精度计算结果。
|
||||
|
||||
```bash
|
||||
Evaluate annotation type *bbox*
|
||||
Accumulating evaluation results...
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.378
|
||||
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.602
|
||||
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.407
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.240
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.420
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.481
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.311
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.500
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.528
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.367
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.572
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.657
|
||||
|
||||
Evaluate annotation type *segm*
|
||||
Accumulating evaluation results...
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.321
|
||||
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.553
|
||||
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.328
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.164
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.350
|
||||
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.466
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.276
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.422
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.441
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.279
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.476
|
||||
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.578
|
||||
```
|
||||
|
||||
# 模型说明
|
||||
|
||||
## 性能
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""post process for 310 inference"""
|
||||
import os
|
||||
import argparse
|
||||
import numpy as np
|
||||
from pycocotools.coco import COCO
|
||||
from util import coco_eval, bbox2result_1image, results2json, get_seg_masks
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser("maskrcnn quant postprocess")
|
||||
parser.add_argument("--shape_path", type=str, required=True, help="path to image meta directory")
|
||||
parser.add_argument("--annotation_path", type=str, required=True, help="path to instance_xxx.json")
|
||||
parser.add_argument("--result_path", type=str, required=True, help="path to inference results.")
|
||||
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
|
||||
def get_eval_result(shape_data, ann_file, result_path):
|
||||
""" Get metrics result according to the annotation file and result file"""
|
||||
max_num = 128
|
||||
result_path = result_path
|
||||
outputs = []
|
||||
|
||||
dataset_coco = COCO(ann_file)
|
||||
for index in range(len(os.listdir(shape_data))):
|
||||
prefix = "coco2017_maskrcnn_bs_1_"
|
||||
shape_file_path = os.path.join(shape_data, prefix + str(index) + ".bin")
|
||||
shape_file = np.fromfile(shape_file_path, dtype=np.float16).reshape(1, 4)
|
||||
|
||||
bbox_result_file = os.path.join(result_path, prefix + str(index) + "_output_0.bin")
|
||||
label_result_file = os.path.join(result_path, prefix + str(index) + "_output_1.bin")
|
||||
mask_result_file = os.path.join(result_path, prefix + str(index) + "_output_2.bin")
|
||||
mask_fb_result_file = os.path.join(result_path, prefix + str(index) + "_output_3.bin")
|
||||
|
||||
all_bbox = np.fromfile(bbox_result_file, dtype=np.float16).reshape(80000, 5)
|
||||
all_label = np.fromfile(label_result_file, dtype=np.int32).reshape(80000, 1)
|
||||
all_mask = np.fromfile(mask_result_file, dtype=np.bool_).reshape(80000, 1)
|
||||
all_mask_fb = np.fromfile(mask_fb_result_file, dtype=np.float16).reshape(80000, 28, 28)
|
||||
|
||||
all_bbox_squee = np.squeeze(all_bbox)
|
||||
all_label_squee = np.squeeze(all_label)
|
||||
all_mask_squee = np.squeeze(all_mask)
|
||||
all_mask_fb_squee = np.squeeze(all_mask_fb)
|
||||
|
||||
all_bboxes_tmp_mask = all_bbox_squee[all_mask_squee, :]
|
||||
all_labels_tmp_mask = all_label_squee[all_mask_squee]
|
||||
all_mask_fb_tmp_mask = all_mask_fb_squee[all_mask_squee, :, :]
|
||||
|
||||
if all_bboxes_tmp_mask.shape[0] > max_num:
|
||||
inds = np.argsort(-all_bboxes_tmp_mask[:, -1])
|
||||
inds = inds[:max_num]
|
||||
all_bboxes_tmp_mask = all_bboxes_tmp_mask[inds]
|
||||
all_labels_tmp_mask = all_labels_tmp_mask[inds]
|
||||
all_mask_fb_tmp_mask = all_mask_fb_tmp_mask[inds]
|
||||
num_classes = 81
|
||||
bbox_results = bbox2result_1image(all_bboxes_tmp_mask, all_labels_tmp_mask, num_classes)
|
||||
segm_results = get_seg_masks(all_mask_fb_tmp_mask, all_bboxes_tmp_mask, all_labels_tmp_mask, shape_file[0],
|
||||
True, num_classes)
|
||||
outputs.append((bbox_results, segm_results))
|
||||
|
||||
eval_types = ["bbox", "segm"]
|
||||
result_files = results2json(dataset_coco, outputs, "./results.pkl")
|
||||
coco_eval(result_files, eval_types, dataset_coco, single_result=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
get_eval_result(args.shape_path, args.annotation_path, args.result_path)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""generate data and label needed for AIR model inference"""
|
||||
import os
|
||||
import sys
|
||||
from mindspore import context
|
||||
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
|
||||
|
||||
|
||||
def generate_data(dataset_path):
|
||||
"""
|
||||
Generate data and label needed for AIR model inference at Ascend310 platform.
|
||||
"""
|
||||
batch_size = 1
|
||||
ds = create_maskrcnn_dataset(dataset_path, batch_size=batch_size, is_training=False)
|
||||
total = ds.get_dataset_size()
|
||||
|
||||
cur_dir = os.getcwd() + "/data"
|
||||
img_path = os.path.join(cur_dir, "00_img_data")
|
||||
if not os.path.exists(img_path):
|
||||
os.makedirs(img_path)
|
||||
meta_path = os.path.join(cur_dir, "01_meta_data")
|
||||
if not os.path.exists(meta_path):
|
||||
os.makedirs(meta_path)
|
||||
print("\n========================================\n")
|
||||
print("total images num: ", total)
|
||||
print("Processing, please wait a moment.")
|
||||
bin_prefix = "coco2017_maskrcnn_bs_1_"
|
||||
for i, data in enumerate(ds.create_dict_iterator(output_numpy=True, num_epochs=1)):
|
||||
img_data = data["image"]
|
||||
img_metas = data["image_shape"]
|
||||
file_name = bin_prefix + str(i) + ".bin"
|
||||
img_data.tofile(os.path.join(img_path, file_name))
|
||||
img_metas.tofile(os.path.join(meta_path, file_name))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from src.model_utils.config import config
|
||||
from src.dataset import data_to_mindrecord_byte_image, create_maskrcnn_dataset
|
||||
|
||||
prefix = "MaskRcnn_eval.mindrecord"
|
||||
mindrecord_dir = config.mindrecord_dir
|
||||
mindrecord_file = os.path.join(mindrecord_dir, prefix)
|
||||
if not os.path.exists(mindrecord_file):
|
||||
if not os.path.isdir(mindrecord_dir):
|
||||
os.makedirs(mindrecord_dir)
|
||||
if config.dataset == "coco":
|
||||
if os.path.isdir(config.coco_root):
|
||||
print("Create Mindrecord.")
|
||||
data_to_mindrecord_byte_image("coco", False, prefix, file_num=1)
|
||||
print("Create Mindrecord Done, at {}".format(mindrecord_dir))
|
||||
else:
|
||||
print("coco_root not exits.")
|
||||
else:
|
||||
if os.path.isdir(config.IMAGE_DIR) and os.path.exists(config.ANNO_PATH):
|
||||
print("Create Mindrecord.")
|
||||
data_to_mindrecord_byte_image("other", False, prefix, file_num=1)
|
||||
print("Create Mindrecord Done, at {}".format(mindrecord_dir))
|
||||
else:
|
||||
print("IMAGE_DIR or ANNO_PATH not exits.")
|
||||
|
||||
generate_data(mindrecord_file)
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* ModelProcess
|
||||
*/
|
||||
class ModelProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief load model from file with mem
|
||||
* @param [in] modelPath: model path
|
||||
* @return result
|
||||
*/
|
||||
Result LoadModelFromFileWithMem(const char *modelPath);
|
||||
|
||||
/**
|
||||
* @brief unload model
|
||||
*/
|
||||
void Unload();
|
||||
|
||||
/**
|
||||
* @brief create model desc
|
||||
* @return result
|
||||
*/
|
||||
Result CreateDesc();
|
||||
|
||||
/**
|
||||
* @brief destroy desc
|
||||
*/
|
||||
void DestroyDesc();
|
||||
|
||||
/**
|
||||
* @brief create model input
|
||||
* @param [in] inputDataBuffer: input buffer
|
||||
* @param [in] bufferSize: input buffer size
|
||||
* @return result
|
||||
*/
|
||||
Result CreateInput(const std::vector<void *> &inputDataBuffer, const std::vector<size_t> &bufferSize);
|
||||
|
||||
/**
|
||||
* @brief destroy input resource
|
||||
*/
|
||||
void DestroyInput();
|
||||
|
||||
/**
|
||||
* @brief create output buffer
|
||||
* @return result
|
||||
*/
|
||||
Result CreateOutput();
|
||||
|
||||
/**
|
||||
* @brief destroy output resource
|
||||
*/
|
||||
void DestroyOutput();
|
||||
|
||||
/**
|
||||
* @brief model execute
|
||||
* @return result
|
||||
*/
|
||||
Result Execute();
|
||||
|
||||
/**
|
||||
* @brief dump model output result to file
|
||||
*/
|
||||
void DumpModelOutputResult(char *output_name);
|
||||
|
||||
/**
|
||||
* @brief get model output result
|
||||
*/
|
||||
void OutputModelResult();
|
||||
|
||||
private:
|
||||
uint32_t modelId_;
|
||||
size_t modelMemSize_;
|
||||
size_t modelWeightSize_;
|
||||
void *modelMemPtr_;
|
||||
void *modelWeightPtr_;
|
||||
bool loadFlag_; // model load flag
|
||||
aclmdlDesc *modelDesc_;
|
||||
aclmdlDataset *input_;
|
||||
aclmdlDataset *output_;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* SampleProcess
|
||||
*/
|
||||
class SampleProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief init reousce
|
||||
* @return result
|
||||
*/
|
||||
Result InitResource();
|
||||
|
||||
/**
|
||||
* @brief sample process
|
||||
* @return result
|
||||
*/
|
||||
Result Process(char *om_path, char *input_folder, char *shape_folder);
|
||||
|
||||
void GetAllFiles(std::string path, std::vector<std::string> *files);
|
||||
|
||||
private:
|
||||
void DestroyResource();
|
||||
|
||||
int32_t deviceId_;
|
||||
aclrtContext context_;
|
||||
aclrtStream stream_;
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args)
|
||||
#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args)
|
||||
#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args)
|
||||
|
||||
typedef enum Result {
|
||||
SUCCESS = 0,
|
||||
FAILED = 1
|
||||
} Result;
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
class Utils {
|
||||
public:
|
||||
/**
|
||||
* @brief create device buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return device buffer of file
|
||||
*/
|
||||
static void *GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize);
|
||||
|
||||
/**
|
||||
* @brief create buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return buffer of pic
|
||||
*/
|
||||
static void* ReadBinFile(std::string fileName, uint32_t *fileSize);
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""do post training quantization for Ascend310"""
|
||||
import os
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from amct_mindspore.quantize_tool import create_quant_config
|
||||
from amct_mindspore.quantize_tool import quantize_model
|
||||
from amct_mindspore.quantize_tool import save_model
|
||||
from mindspore import Tensor, context
|
||||
from mindspore.train.serialization import load_checkpoint, load_param_into_net
|
||||
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
|
||||
|
||||
|
||||
def quant_maskrcnn(network, dataset, input_data):
|
||||
"""
|
||||
Export post training quantization model of AIR format.
|
||||
|
||||
Args:
|
||||
network: the origin network for inference.
|
||||
dataset: the data for inference.
|
||||
input_data: the data used for constructing network. The shape and format of input data should be the same as
|
||||
actual data for inference.
|
||||
"""
|
||||
|
||||
# step2: create the quant config json file
|
||||
create_quant_config("./config.json", network, *input_data)
|
||||
|
||||
# step3: do some network modification and return the modified network
|
||||
calibration_network = quantize_model("./config.json", network, *input_data)
|
||||
calibration_network.set_train(False)
|
||||
|
||||
# step4: perform the evaluation of network to do activation calibration
|
||||
for data in dataset.create_dict_iterator(num_epochs=1):
|
||||
_ = calibration_network(data["image"], data["image_shape"])
|
||||
|
||||
# step5: export the air file
|
||||
save_model("results/maskrcnn_quant", calibration_network, *input_data)
|
||||
print("[INFO] the quantized AIR file has been stored at: \n {}".format("results/maskrcnn_quant.air"))
|
||||
|
||||
|
||||
def export_maskrcnn():
|
||||
""" export_maskrcnn """
|
||||
config.test_batch_size = 1
|
||||
config.batch_size = config.test_batch_size
|
||||
net = MaskRcnn_Infer(config=config)
|
||||
param_dict = load_checkpoint(config.ckpt_file)
|
||||
param_dict_new = {}
|
||||
for key, value in param_dict.items():
|
||||
param_dict_new["network." + key] = value
|
||||
load_param_into_net(net, param_dict_new)
|
||||
net.set_train(False)
|
||||
|
||||
img = Tensor(np.zeros([config.batch_size, 3, config.img_height, config.img_width], np.float16))
|
||||
img_metas = Tensor(np.zeros([config.batch_size, 4], np.float16))
|
||||
input_data = [img, img_metas]
|
||||
|
||||
mindrecord_file = os.path.join(config.mindrecord_dir, "MaskRcnn_eval.mindrecord")
|
||||
ds = create_maskrcnn_dataset(mindrecord_file, batch_size=config.batch_size, is_training=False)
|
||||
dataset = ds.take(1)
|
||||
quant_maskrcnn(net, dataset, input_data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from src.model_utils.config import config
|
||||
from src.maskrcnn.mask_rcnn_r50 import MaskRcnn_Infer
|
||||
from src.dataset import create_maskrcnn_dataset
|
||||
|
||||
export_maskrcnn()
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
if [ $# -lt 4 ]; then
|
||||
echo "Usage: bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [SHAPE_PATH] [ANNOTATION_PATH]"
|
||||
echo "Example: bash run_quant_infer.sh ./maskrcnn_quant.air ./00_img_data ./01_meta_data ./instances_val2017.json"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_real_path(){
|
||||
if [ "${1:0:1}" == "/" ]; then
|
||||
echo "$1"
|
||||
else
|
||||
echo "$(realpath -m $PWD/$1)"
|
||||
fi
|
||||
}
|
||||
model=$(get_real_path $1)
|
||||
data_path=$(get_real_path $2)
|
||||
shape_path=$(get_real_path $3)
|
||||
annotation_path=$(get_real_path $4)
|
||||
|
||||
echo "air name: "$model
|
||||
echo "dataset path: "$data_path
|
||||
echo "shape path: "$shape_path
|
||||
echo "annotation path: "$annotation_path
|
||||
|
||||
export ASCEND_HOME=/usr/local/Ascend/
|
||||
if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then
|
||||
export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe
|
||||
export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp
|
||||
else
|
||||
export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/opp
|
||||
fi
|
||||
|
||||
function air_to_om()
|
||||
{
|
||||
atc --input_format=NCHW --framework=1 --model=$model --output=maskrcnn_quant --soc_version=Ascend310 &> atc.log
|
||||
}
|
||||
|
||||
function compile_app()
|
||||
{
|
||||
bash ./src/build.sh &> build.log
|
||||
}
|
||||
|
||||
function infer()
|
||||
{
|
||||
if [ -d result ]; then
|
||||
rm -rf ./result
|
||||
fi
|
||||
mkdir result
|
||||
./out/main ./maskrcnn_quant.om $data_path $shape_path &> infer.log
|
||||
}
|
||||
|
||||
function cal_acc()
|
||||
{
|
||||
python3.7 ./acc.py --result_path=./result --shape_path=$shape_path --annotation_path=$annotation_path &> acc.log
|
||||
}
|
||||
|
||||
echo "start atc================================================"
|
||||
air_to_om
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "air to om code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start compile============================================"
|
||||
compile_app
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "compile app code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start infer=============================================="
|
||||
infer
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " execute inference failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start calculate acc======================================"
|
||||
cal_acc
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "calculate accuracy failed"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
|
||||
|
||||
# CMake lowest version requirement
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
# project information
|
||||
project(InferClassification)
|
||||
# Check environment variable
|
||||
if(NOT DEFINED ENV{ASCEND_HOME})
|
||||
message(FATAL_ERROR "please define environment variable:ASCEND_HOME")
|
||||
endif()
|
||||
|
||||
# Compile options
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined")
|
||||
|
||||
# Skip build rpath
|
||||
set(CMAKE_SKIP_BUILD_RPATH True)
|
||||
|
||||
# Set output directory
|
||||
set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/../out)
|
||||
|
||||
# Set include directory and library directory
|
||||
set(FWKACL_LIB_DIR $ENV{ASCEND_HOME}/fwkacllib)
|
||||
set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib)
|
||||
set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib)
|
||||
|
||||
# Header path
|
||||
include_directories(${ACL_LIB_DIR}/include/)
|
||||
include_directories(${FWKACL_LIB_DIR}/include/)
|
||||
include_directories(${ATLAS_ACL_LIB_DIR}/include/)
|
||||
include_directories(${PROJECT_SRC_ROOT}/../inc)
|
||||
|
||||
# add host lib path
|
||||
link_directories(${ACL_LIB_DIR} ${FWKACL_LIB_DIR})
|
||||
find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${FWKACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64)
|
||||
|
||||
add_executable(main utils.cpp
|
||||
sample_process.cpp
|
||||
model_process.cpp
|
||||
main.cpp)
|
||||
|
||||
target_link_libraries(main ${acl} gflags pthread)
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
path_cur=$(cd "`dirname $0`" || exit; pwd)
|
||||
|
||||
function preparePath() {
|
||||
rm -rf $1
|
||||
mkdir -p $1
|
||||
cd $1 || exit
|
||||
}
|
||||
|
||||
function buildA300() {
|
||||
if [ ! "${ARCH_PATTERN}" ]; then
|
||||
# set ARCH_PATTERN to acllib when it was not specified by user
|
||||
export ARCH_PATTERN=acllib
|
||||
echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}"
|
||||
else
|
||||
echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib"
|
||||
export ARCH_PATTERN=${ARCH_PATTERN}/acllib
|
||||
fi
|
||||
|
||||
path_build=$path_cur/build
|
||||
preparePath $path_build
|
||||
cmake ..
|
||||
make -j
|
||||
ret=$?
|
||||
cd ..
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user
|
||||
if [ ! "${ASCEND_VERSION}" ]; then
|
||||
export ASCEND_VERSION=ascend-toolkit/latest
|
||||
echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}"
|
||||
else
|
||||
echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user"
|
||||
fi
|
||||
|
||||
buildA300
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include "../inc/sample_process.h"
|
||||
#include "../inc/utils.h"
|
||||
bool g_is_device = false;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 4) {
|
||||
ERROR_LOG("usage:./main path_of_om path_of_inputFolder path_of_shapeFolder");
|
||||
return FAILED;
|
||||
}
|
||||
SampleProcess processSample;
|
||||
Result ret = processSample.InitResource();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample init resource failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processSample.Process(argv[1], argv[2], argv[3]);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample process failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("execute sample success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/model_process.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
|
||||
ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr),
|
||||
modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) {
|
||||
}
|
||||
|
||||
ModelProcess::~ModelProcess() {
|
||||
Unload();
|
||||
DestroyDesc();
|
||||
DestroyInput();
|
||||
DestroyOutput();
|
||||
}
|
||||
|
||||
Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) {
|
||||
if (loadFlag_) {
|
||||
ERROR_LOG("has already loaded a model");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("query model failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_,
|
||||
modelMemSize_, modelWeightPtr_, modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("load model from file failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
loadFlag_ = true;
|
||||
INFO_LOG("load model %s success", modelPath);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateDesc() {
|
||||
modelDesc_ = aclmdlCreateDesc();
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("create model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlGetDesc(modelDesc_, modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("get model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("create model description success");
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyDesc() {
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateInput(const std::vector<void *> &inputDataBuffer, const std::vector<size_t> &bufferSize) {
|
||||
input_ = aclmdlCreateDataset();
|
||||
if (input_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
for (size_t i = 0; i < inputDataBuffer.size(); ++i) {
|
||||
aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer[i], bufferSize[i]);
|
||||
if (inputData == nullptr) {
|
||||
ERROR_LOG("can't create data buffer, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlAddDatasetBuffer(input_, inputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("add input dataset buffer failed");
|
||||
aclDestroyDataBuffer(inputData);
|
||||
inputData = nullptr;
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyInput() {
|
||||
if (input_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i);
|
||||
aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
aclmdlDestroyDataset(input_);
|
||||
input_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateOutput() {
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("no model description, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
output_ = aclmdlCreateDataset();
|
||||
if (output_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
size_t outputSize = aclmdlGetNumOutputs(modelDesc_);
|
||||
for (size_t i = 0; i < outputSize; ++i) {
|
||||
size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i);
|
||||
|
||||
void *outputBuffer = nullptr;
|
||||
aclError ret = aclrtMalloc(&outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't create data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlAddDatasetBuffer(output_, outputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't add data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
aclDestroyDataBuffer(outputData);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("create model output success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DumpModelOutputResult(char *output_name) {
|
||||
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);
|
||||
|
||||
for (size_t i = 0; i < outputNum; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "result/" << output_name << "_output_" << i << ".bin";
|
||||
std::string outputFileName = ss.str();
|
||||
FILE *outputFile = fopen(outputFileName.c_str(), "wb");
|
||||
if (outputFile) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void* outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
(void)aclrtFreeHost(outHostData);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(outHostData, len, sizeof(char), outputFile);
|
||||
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fwrite(data, len, sizeof(char), outputFile);
|
||||
}
|
||||
fclose(outputFile);
|
||||
outputFile = nullptr;
|
||||
} else {
|
||||
ERROR_LOG("create output file [%s] failed", outputFileName.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("dump data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::OutputModelResult() {
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void *outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
float *outData = NULL;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
outData = reinterpret_cast<float*>(outHostData);
|
||||
} else {
|
||||
outData = reinterpret_cast<float*>(data);
|
||||
}
|
||||
std::map<float, unsigned int, std::greater<float> > resultMap;
|
||||
for (unsigned int j = 0; j < len / sizeof(float); ++j) {
|
||||
resultMap[*outData] = j;
|
||||
outData++;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (auto it = resultMap.begin(); it != resultMap.end(); ++it) {
|
||||
// print top 5
|
||||
if (++cnt > 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first);
|
||||
}
|
||||
if (!g_is_device) {
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("output data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyOutput() {
|
||||
if (output_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
(void)aclrtFree(data);
|
||||
(void)aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
|
||||
(void)aclmdlDestroyDataset(output_);
|
||||
output_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::Execute() {
|
||||
aclError ret = aclmdlExecute(modelId_, input_, output_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("execute model failed, modelId is %u", modelId_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("model execute success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::Unload() {
|
||||
if (!loadFlag_) {
|
||||
WARN_LOG("no model had been loaded, unload failed");
|
||||
return;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlUnload(modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("unload model failed, modelId is %u", modelId_);
|
||||
}
|
||||
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
|
||||
if (modelMemPtr_ != nullptr) {
|
||||
aclrtFree(modelMemPtr_);
|
||||
modelMemPtr_ = nullptr;
|
||||
modelMemSize_ = 0;
|
||||
}
|
||||
|
||||
if (modelWeightPtr_ != nullptr) {
|
||||
aclrtFree(modelWeightPtr_);
|
||||
modelWeightPtr_ = nullptr;
|
||||
modelWeightSize_ = 0;
|
||||
}
|
||||
|
||||
loadFlag_ = false;
|
||||
INFO_LOG("unload model success, modelId is %u", modelId_);
|
||||
}
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/sample_process.h"
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../inc/model_process.h"
|
||||
#include "acl/acl.h"
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) {
|
||||
}
|
||||
|
||||
SampleProcess::~SampleProcess() {
|
||||
DestroyResource();
|
||||
}
|
||||
|
||||
Result SampleProcess::InitResource() {
|
||||
// ACL init
|
||||
|
||||
const char *aclConfigPath = "./src/acl.json";
|
||||
aclError ret = aclInit(aclConfigPath);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl init failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("acl init success");
|
||||
|
||||
// open device
|
||||
ret = aclrtSetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl open device %d failed", deviceId_);
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("open device %d success", deviceId_);
|
||||
|
||||
// create context (set current)
|
||||
ret = aclrtCreateContext(&context_, deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create context failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create context success");
|
||||
|
||||
// create stream
|
||||
ret = aclrtCreateStream(&stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create stream failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create stream success");
|
||||
|
||||
// get run mode
|
||||
aclrtRunMode runMode;
|
||||
ret = aclrtGetRunMode(&runMode);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl get run mode failed");
|
||||
return FAILED;
|
||||
}
|
||||
g_is_device = (runMode == ACL_DEVICE);
|
||||
INFO_LOG("get run mode success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::GetAllFiles(std::string path, std::vector<string> *files) {
|
||||
DIR *pDir = NULL;
|
||||
struct dirent* ptr;
|
||||
if (!(pDir = opendir(path.c_str()))) {
|
||||
return;
|
||||
}
|
||||
while ((ptr = readdir(pDir)) != 0) {
|
||||
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
|
||||
files->push_back(path + "/" + ptr->d_name);
|
||||
}
|
||||
}
|
||||
closedir(pDir);
|
||||
}
|
||||
|
||||
Result SampleProcess::Process(char *om_path, char *input_folder, char *shape_folder) {
|
||||
// model init
|
||||
double second_to_millisecond = 1000;
|
||||
double second_to_microsecond = 1000000;
|
||||
|
||||
double whole_cost_time = 0.0;
|
||||
struct timeval start_global = {0};
|
||||
struct timeval end_global = {0};
|
||||
double startTimeMs_global = 0.0;
|
||||
double endTimeMs_global = 0.0;
|
||||
|
||||
gettimeofday(&start_global, nullptr);
|
||||
|
||||
ModelProcess processModel;
|
||||
const char* omModelPath = om_path;
|
||||
|
||||
Result ret = processModel.LoadModelFromFileWithMem(omModelPath);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute LoadModelFromFileWithMem failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateDesc();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateDesc failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateOutput();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateOutput failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
std::vector<string> testFile;
|
||||
GetAllFiles(input_folder, &testFile);
|
||||
std::vector<string> shapeFile;
|
||||
GetAllFiles(shape_folder, &shapeFile);
|
||||
|
||||
if (testFile.size() !=shapeFile.size()) {
|
||||
ERROR_LOG("number of data files is not equal to shape file");
|
||||
}
|
||||
|
||||
double model_cost_time = 0.0;
|
||||
double edge_to_edge_model_cost_time = 0.0;
|
||||
|
||||
for (size_t index = 0; index < testFile.size(); ++index) {
|
||||
INFO_LOG("start to process data file:%s", testFile[index].c_str());
|
||||
INFO_LOG("start to process shape file:%s", shapeFile[index].c_str());
|
||||
// model process
|
||||
|
||||
struct timeval time_init = {0};
|
||||
double timeval_init = 0.0;
|
||||
gettimeofday(&time_init, nullptr);
|
||||
timeval_init = (time_init.tv_sec * second_to_microsecond + time_init.tv_usec) / second_to_millisecond;
|
||||
|
||||
uint32_t devBufferSize;
|
||||
void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize);
|
||||
if (picDevBuffer == nullptr) {
|
||||
ERROR_LOG("get pic device buffer failed, index is %zu", index);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
uint32_t devBufferShapeSize;
|
||||
void *shapeDevBuffer = Utils::GetDeviceBufferOfFile(shapeFile[index], &devBufferShapeSize);
|
||||
if (shapeDevBuffer == nullptr) {
|
||||
ERROR_LOG("get shape device buffer failed, index is %zu", index);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
std::vector<void *> inputBuffers({picDevBuffer, shapeDevBuffer});
|
||||
std::vector<size_t> inputSizes({devBufferSize, devBufferShapeSize});
|
||||
|
||||
ret = processModel.CreateInput(inputBuffers, inputSizes);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateInput failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
struct timeval start = {0};
|
||||
struct timeval end = {0};
|
||||
gettimeofday(&start, nullptr);
|
||||
double startTimeMs = (start.tv_sec * second_to_microsecond + start.tv_usec) / second_to_millisecond;
|
||||
|
||||
ret = processModel.Execute();
|
||||
|
||||
gettimeofday(&end, nullptr);
|
||||
double endTimeMs = (end.tv_sec * second_to_microsecond + end.tv_usec) / second_to_millisecond;
|
||||
|
||||
double cost_time = endTimeMs - startTimeMs;
|
||||
INFO_LOG("model infer time: %lf ms", cost_time);
|
||||
|
||||
model_cost_time += cost_time;
|
||||
|
||||
double edge_to_edge_cost_time = endTimeMs - timeval_init;
|
||||
edge_to_edge_model_cost_time += edge_to_edge_cost_time;
|
||||
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute inference failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
int pos = testFile[index].find_last_of('/');
|
||||
std::string name = testFile[index].substr(pos+1);
|
||||
std::string outputname = name.substr(0, name.rfind("."));
|
||||
|
||||
// dump output result to file in the current directory
|
||||
processModel.DumpModelOutputResult(const_cast<char *>(outputname.c_str()));
|
||||
|
||||
// release model input buffer
|
||||
aclrtFree(picDevBuffer);
|
||||
processModel.DestroyInput();
|
||||
}
|
||||
double test_file_size = testFile.size();
|
||||
INFO_LOG("infer dataset size:%lf", test_file_size);
|
||||
|
||||
gettimeofday(&end_global, nullptr);
|
||||
startTimeMs_global = (start_global.tv_sec * second_to_microsecond + start_global.tv_usec) / second_to_millisecond;
|
||||
endTimeMs_global = (end_global.tv_sec * second_to_microsecond + end_global.tv_usec) / second_to_millisecond;
|
||||
whole_cost_time = (endTimeMs_global - startTimeMs_global) / test_file_size;
|
||||
|
||||
model_cost_time /= test_file_size;
|
||||
INFO_LOG("model cost time per sample: %lf ms", model_cost_time);
|
||||
edge_to_edge_model_cost_time /= test_file_size;
|
||||
INFO_LOG("edge-to-edge model cost time per sample:%lf ms", edge_to_edge_model_cost_time);
|
||||
INFO_LOG("whole cost time per sample: %lf ms", whole_cost_time);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::DestroyResource() {
|
||||
aclError ret;
|
||||
if (stream_ != nullptr) {
|
||||
ret = aclrtDestroyStream(stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy stream failed");
|
||||
}
|
||||
stream_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy stream");
|
||||
|
||||
if (context_ != nullptr) {
|
||||
ret = aclrtDestroyContext(context_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy context failed");
|
||||
}
|
||||
context_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy context");
|
||||
|
||||
ret = aclrtResetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("reset device failed");
|
||||
}
|
||||
INFO_LOG("end to reset device is %d", deviceId_);
|
||||
|
||||
ret = aclFinalize();
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("finalize acl failed");
|
||||
}
|
||||
INFO_LOG("end to finalize acl");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "acl/acl.h"
|
||||
|
||||
extern bool g_is_device;
|
||||
|
||||
void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) {
|
||||
struct stat sBuf;
|
||||
int fileStatus = stat(fileName.data(), &sBuf);
|
||||
if (fileStatus == -1) {
|
||||
ERROR_LOG("failed to get file");
|
||||
return nullptr;
|
||||
}
|
||||
if (S_ISREG(sBuf.st_mode) == 0) {
|
||||
ERROR_LOG("%s is not a file, please enter a file", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream binFile(fileName, std::ifstream::binary);
|
||||
if (binFile.is_open() == false) {
|
||||
ERROR_LOG("open file %s failed", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.end);
|
||||
uint32_t binFileBufferLen = binFile.tellg();
|
||||
if (binFileBufferLen == 0) {
|
||||
ERROR_LOG("binfile is empty, filename is %s", fileName.c_str());
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.beg);
|
||||
|
||||
void* binFileBufferData = nullptr;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc for binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
if (binFileBufferData == nullptr) {
|
||||
ERROR_LOG("malloc binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen);
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
binFile.read(static_cast<char *>(binFileBufferData), binFileBufferLen);
|
||||
binFile.close();
|
||||
*fileSize = binFileBufferLen;
|
||||
return binFileBufferData;
|
||||
}
|
||||
|
||||
void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize) {
|
||||
uint32_t inputHostBuffSize = 0;
|
||||
void* inputHostBuff = Utils::ReadBinFile(fileName, &inputHostBuffSize);
|
||||
if (inputHostBuff == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!g_is_device) {
|
||||
void *inBufferDev = nullptr;
|
||||
uint32_t inBufferSize = inputHostBuffSize;
|
||||
aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u",
|
||||
inBufferSize, inputHostBuffSize);
|
||||
aclrtFree(inBufferDev);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
*fileSize = inBufferSize;
|
||||
return inBufferDev;
|
||||
} else {
|
||||
*fileSize = inputHostBuffSize;
|
||||
return inputHostBuff;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""coco eval for maskrcnn"""
|
||||
import json
|
||||
import numpy as np
|
||||
import mmcv
|
||||
from pycocotools.coco import COCO
|
||||
from pycocotools.cocoeval import COCOeval
|
||||
from pycocotools import mask as maskUtils
|
||||
|
||||
|
||||
_init_value = np.array(0.0)
|
||||
summary_init = {
|
||||
'Precision/mAP': _init_value,
|
||||
'Precision/mAP@.50IOU': _init_value,
|
||||
'Precision/mAP@.75IOU': _init_value,
|
||||
'Precision/mAP (small)': _init_value,
|
||||
'Precision/mAP (medium)': _init_value,
|
||||
'Precision/mAP (large)': _init_value,
|
||||
'Recall/AR@1': _init_value,
|
||||
'Recall/AR@10': _init_value,
|
||||
'Recall/AR@100': _init_value,
|
||||
'Recall/AR@100 (small)': _init_value,
|
||||
'Recall/AR@100 (medium)': _init_value,
|
||||
'Recall/AR@100 (large)': _init_value,
|
||||
}
|
||||
|
||||
|
||||
def coco_eval(result_files, result_types, coco, max_dets=(100, 300, 1000), single_result=False):
|
||||
"""coco eval for maskrcnn"""
|
||||
anns = json.load(open(result_files['bbox']))
|
||||
if not anns:
|
||||
return summary_init
|
||||
if mmcv.is_str(coco):
|
||||
coco = COCO(coco)
|
||||
assert isinstance(coco, COCO)
|
||||
|
||||
for res_type in result_types:
|
||||
result_file = result_files[res_type]
|
||||
assert result_file.endswith('.json')
|
||||
|
||||
coco_dets = coco.loadRes(result_file)
|
||||
gt_img_ids = coco.getImgIds()
|
||||
det_img_ids = coco_dets.getImgIds()
|
||||
iou_type = 'bbox' if res_type == 'proposal' else res_type
|
||||
cocoEval = COCOeval(coco, coco_dets, iou_type)
|
||||
if res_type == 'proposal':
|
||||
cocoEval.params.useCats = 0
|
||||
cocoEval.params.maxDets = list(max_dets)
|
||||
|
||||
tgt_ids = gt_img_ids if not single_result else det_img_ids
|
||||
|
||||
if single_result:
|
||||
res_dict = dict()
|
||||
for id_i in tgt_ids:
|
||||
cocoEval = COCOeval(coco, coco_dets, iou_type)
|
||||
if res_type == 'proposal':
|
||||
cocoEval.params.useCats = 0
|
||||
cocoEval.params.maxDets = list(max_dets)
|
||||
|
||||
cocoEval.params.imgIds = [id_i]
|
||||
cocoEval.evaluate()
|
||||
cocoEval.accumulate()
|
||||
cocoEval.summarize()
|
||||
res_dict.update({coco.imgs[id_i]['file_name']: cocoEval.stats[1]})
|
||||
|
||||
cocoEval = COCOeval(coco, coco_dets, iou_type)
|
||||
if res_type == 'proposal':
|
||||
cocoEval.params.useCats = 0
|
||||
cocoEval.params.maxDets = list(max_dets)
|
||||
|
||||
cocoEval.params.imgIds = tgt_ids
|
||||
cocoEval.evaluate()
|
||||
cocoEval.accumulate()
|
||||
cocoEval.summarize()
|
||||
|
||||
summary_metrics = {
|
||||
'Precision/mAP': cocoEval.stats[0],
|
||||
'Precision/mAP@.50IOU': cocoEval.stats[1],
|
||||
'Precision/mAP@.75IOU': cocoEval.stats[2],
|
||||
'Precision/mAP (small)': cocoEval.stats[3],
|
||||
'Precision/mAP (medium)': cocoEval.stats[4],
|
||||
'Precision/mAP (large)': cocoEval.stats[5],
|
||||
'Recall/AR@1': cocoEval.stats[6],
|
||||
'Recall/AR@10': cocoEval.stats[7],
|
||||
'Recall/AR@100': cocoEval.stats[8],
|
||||
'Recall/AR@100 (small)': cocoEval.stats[9],
|
||||
'Recall/AR@100 (medium)': cocoEval.stats[10],
|
||||
'Recall/AR@100 (large)': cocoEval.stats[11],
|
||||
}
|
||||
|
||||
return summary_metrics
|
||||
|
||||
|
||||
def xyxy2xywh(bbox):
|
||||
"""convert format of coordinate point"""
|
||||
_bbox = bbox.tolist()
|
||||
return [
|
||||
_bbox[0],
|
||||
_bbox[1],
|
||||
_bbox[2] - _bbox[0] + 1,
|
||||
_bbox[3] - _bbox[1] + 1,
|
||||
]
|
||||
|
||||
def bbox2result_1image(bboxes, labels, num_classes):
|
||||
"""Convert detection results to a list of numpy arrays.
|
||||
|
||||
Args:
|
||||
bboxes (Tensor): shape (n, 5)
|
||||
labels (Tensor): shape (n, )
|
||||
num_classes (int): class number, including background class
|
||||
|
||||
Returns:
|
||||
list(ndarray): bbox results of each class
|
||||
"""
|
||||
if bboxes.shape[0] == 0:
|
||||
result = [np.zeros((0, 5), dtype=np.float32) for i in range(num_classes - 1)]
|
||||
else:
|
||||
result = [bboxes[labels == i, :] for i in range(num_classes - 1)]
|
||||
|
||||
return result
|
||||
|
||||
def proposal2json(dataset, results):
|
||||
"""convert proposal to json mode"""
|
||||
img_ids = dataset.getImgIds()
|
||||
json_results = []
|
||||
dataset_len = dataset.get_dataset_size()*2
|
||||
for idx in range(dataset_len):
|
||||
img_id = img_ids[idx]
|
||||
bboxes = results[idx]
|
||||
for i in range(bboxes.shape[0]):
|
||||
data = dict()
|
||||
data['image_id'] = img_id
|
||||
data['bbox'] = xyxy2xywh(bboxes[i])
|
||||
data['score'] = float(bboxes[i][4])
|
||||
data['category_id'] = 1
|
||||
json_results.append(data)
|
||||
return json_results
|
||||
|
||||
def det2json(dataset, results):
|
||||
"""convert det to json mode"""
|
||||
cat_ids = dataset.getCatIds()
|
||||
img_ids = dataset.getImgIds()
|
||||
json_results = []
|
||||
dataset_len = len(img_ids)
|
||||
for idx in range(dataset_len):
|
||||
img_id = img_ids[idx]
|
||||
if idx == len(results): break
|
||||
result = results[idx]
|
||||
for label, result_label in enumerate(result):
|
||||
bboxes = result_label
|
||||
for i in range(bboxes.shape[0]):
|
||||
data = dict()
|
||||
data['image_id'] = img_id
|
||||
data['bbox'] = xyxy2xywh(bboxes[i])
|
||||
data['score'] = float(bboxes[i][4])
|
||||
data['category_id'] = cat_ids[label]
|
||||
json_results.append(data)
|
||||
return json_results
|
||||
|
||||
def segm2json(dataset, results):
|
||||
"""convert segm to json mode"""
|
||||
cat_ids = dataset.getCatIds()
|
||||
img_ids = dataset.getImgIds()
|
||||
bbox_json_results = []
|
||||
segm_json_results = []
|
||||
|
||||
dataset_len = len(img_ids)
|
||||
assert dataset_len == len(results)
|
||||
for idx in range(dataset_len):
|
||||
img_id = img_ids[idx]
|
||||
if idx == len(results): break
|
||||
det, seg = results[idx]
|
||||
for label, det_label in enumerate(det):
|
||||
bboxes = det_label
|
||||
for i in range(bboxes.shape[0]):
|
||||
data = dict()
|
||||
data['image_id'] = img_id
|
||||
data['bbox'] = xyxy2xywh(bboxes[i])
|
||||
data['score'] = float(bboxes[i][4])
|
||||
data['category_id'] = cat_ids[label]
|
||||
bbox_json_results.append(data)
|
||||
|
||||
if len(seg) == 2:
|
||||
segms = seg[0][label]
|
||||
mask_score = seg[1][label]
|
||||
else:
|
||||
segms = seg[label]
|
||||
mask_score = [bbox[4] for bbox in bboxes]
|
||||
for i in range(bboxes.shape[0]):
|
||||
data = dict()
|
||||
data['image_id'] = img_id
|
||||
data['score'] = float(mask_score[i])
|
||||
data['category_id'] = cat_ids[label]
|
||||
segms[i]['counts'] = segms[i]['counts'].decode()
|
||||
data['segmentation'] = segms[i]
|
||||
segm_json_results.append(data)
|
||||
return bbox_json_results, segm_json_results
|
||||
|
||||
def results2json(dataset, results, out_file):
|
||||
"""convert result convert to json mode"""
|
||||
result_files = dict()
|
||||
if isinstance(results[0], list):
|
||||
json_results = det2json(dataset, results)
|
||||
result_files['bbox'] = '{}.{}.json'.format(out_file, 'bbox')
|
||||
result_files['proposal'] = '{}.{}.json'.format(out_file, 'bbox')
|
||||
mmcv.dump(json_results, result_files['bbox'])
|
||||
elif isinstance(results[0], tuple):
|
||||
json_results = segm2json(dataset, results)
|
||||
result_files['bbox'] = '{}.{}.json'.format(out_file, 'bbox')
|
||||
result_files['segm'] = '{}.{}.json'.format(out_file, 'segm')
|
||||
mmcv.dump(json_results[0], result_files['bbox'])
|
||||
mmcv.dump(json_results[1], result_files['segm'])
|
||||
elif isinstance(results[0], np.ndarray):
|
||||
json_results = proposal2json(dataset, results)
|
||||
result_files['proposal'] = '{}.{}.json'.format(out_file, 'proposal')
|
||||
mmcv.dump(json_results, result_files['proposal'])
|
||||
else:
|
||||
raise TypeError('invalid type of results')
|
||||
return result_files
|
||||
|
||||
def get_seg_masks(mask_pred, det_bboxes, det_labels, img_meta, rescale, num_classes):
|
||||
"""Get segmentation masks from mask_pred and bboxes"""
|
||||
mask_pred = mask_pred.astype(np.float32)
|
||||
|
||||
cls_segms = [[] for _ in range(num_classes - 1)]
|
||||
bboxes = det_bboxes[:, :4]
|
||||
labels = det_labels + 1
|
||||
|
||||
ori_shape = img_meta[:2].astype(np.int32)
|
||||
scale_factor = img_meta[2:].astype(np.int32)
|
||||
|
||||
if rescale:
|
||||
img_h, img_w = ori_shape[:2]
|
||||
else:
|
||||
img_h = np.round(ori_shape[0] * scale_factor[0]).astype(np.int32)
|
||||
img_w = np.round(ori_shape[1] * scale_factor[1]).astype(np.int32)
|
||||
|
||||
for i in range(bboxes.shape[0]):
|
||||
bbox = (bboxes[i, :] / 1.0).astype(np.int32)
|
||||
label = labels[i]
|
||||
w = max(bbox[2] - bbox[0] + 1, 1)
|
||||
h = max(bbox[3] - bbox[1] + 1, 1)
|
||||
w = min(w, img_w - bbox[0])
|
||||
h = min(h, img_h - bbox[1])
|
||||
if w <= 0 or h <= 0:
|
||||
print("there is invalid proposal bbox, index={} bbox={} w={} h={}".format(i, bbox, w, h))
|
||||
w = max(w, 1)
|
||||
h = max(h, 1)
|
||||
mask_pred_ = mask_pred[i, :, :]
|
||||
im_mask = np.zeros((img_h, img_w), dtype=np.uint8)
|
||||
bbox_mask = mmcv.imresize(mask_pred_, (w, h))
|
||||
mask_thr_binary = 0.5
|
||||
bbox_mask = (bbox_mask > mask_thr_binary).astype(np.uint8)
|
||||
im_mask[bbox[1]:bbox[1] + h, bbox[0]:bbox[0] + w] = bbox_mask
|
||||
|
||||
rle = maskUtils.encode(
|
||||
np.array(im_mask[:, :, np.newaxis], order='F'))[0]
|
||||
cls_segms[label - 1].append(rle)
|
||||
|
||||
return cls_segms
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
- [How to use](#how-to-use)
|
||||
- [Inference](#inference)
|
||||
- [Running on Ascend 310](#running-on-ascend-310)
|
||||
- [Post Training Quantization](#post-training-quantization)
|
||||
- [Continue Training on the Pretrained Model](#continue-training-on-the-pretrained-model)
|
||||
- [Transfer training](#transfer-training)
|
||||
- [Description of Random Situation](#description-of-random-situation)
|
||||
|
|
@ -526,6 +527,40 @@ Inference result is saved in current path, you can find result in acc.log file.
|
|||
Cross valid dice coeff is: 0.9054352151297033
|
||||
```
|
||||
|
||||
##### [Post Training Quantization](#contents)
|
||||
|
||||
Relative executing script files reside in the directory "ascend310_quant_infer". Please implement following steps sequentially to complete post quantization.
|
||||
Current quantization project bases on ISBI dataset.
|
||||
|
||||
1. Generate data of .bin format required for AIR model inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
python export_bin.py --config_path [YMAL CONFIG PATH] --data_path [DATA DIR] --result_path [RESULT PATH]
|
||||
```
|
||||
|
||||
2. Export quantized AIR model.
|
||||
|
||||
Post quantization of model requires special toolkits for exporting quantized AIR model. Please refer to [official website](https://www.hiascend.com/software/cann/community).
|
||||
|
||||
```shell
|
||||
python post_quant.py --config_path [YMAL CONFIG PATH] --data_path [DATASET PATH] --checkpoint_file_path [CKPT_PATH]
|
||||
```
|
||||
|
||||
The quantized AIR file will be stored as "./results/unet_quant.air".
|
||||
|
||||
3. Implement inference at Ascend310 platform.
|
||||
|
||||
```shell
|
||||
# Ascend310 quant inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]
|
||||
```
|
||||
|
||||
Inference result is saved in current path, you can find result like this in acc.log file.
|
||||
|
||||
```bash
|
||||
Cross valid dice coeff is: 0.9139793866877975
|
||||
```
|
||||
|
||||
#### Continue Training on the Pretrained Model
|
||||
|
||||
Set options `resume` to True in `*.yaml`, and set `resume_ckpt` to the path of your checkpoint. e.g.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
- [用法](#用法-1)
|
||||
- [推理](#推理)
|
||||
- [Ascend 310环境运行](#ascend-310环境运行)
|
||||
- [训练后量化推理](#训练后量化推理)
|
||||
- [继续训练预训练模型](#继续训练预训练模型)
|
||||
- [迁移学习](#迁移学习)
|
||||
- [随机情况说明](#随机情况说明)
|
||||
|
|
@ -520,6 +521,39 @@ bash run_infer_310.sh [NETWORK] [MINDIR_PATH] [DEVICE_ID] [NEED_PREPROCESS]
|
|||
Cross valid dice coeff is: 0.9054352151297033
|
||||
```
|
||||
|
||||
##### [训练后量化推理](#contents)
|
||||
|
||||
训练后量化推理的相关执行脚本文件在"ascend310_quant_infer"目录下,依次执行以下步骤实现训练后量化推理。本训练后量化工程基于ISBI数据集。
|
||||
|
||||
1、生成Ascend310平台AIR模型推理需要的.bin格式数据。
|
||||
|
||||
```shell
|
||||
python export_bin.py --config_path [YMAL CONFIG PATH] --data_path [DATA DIR] --result_path [RESULT PATH]
|
||||
```
|
||||
|
||||
2、导出训练后量化的AIR格式模型。
|
||||
|
||||
导出训练后量化模型需要配套的量化工具包,参考[官方地址](https://www.hiascend.com/software/cann/community)
|
||||
|
||||
```shell
|
||||
python post_quant.py --config_path [YMAL CONFIG PATH] --data_path [DATASET PATH] --checkpoint_file_path [CKPT_PATH]
|
||||
```
|
||||
|
||||
导出的模型会存储在./result/unet_quant.air。
|
||||
|
||||
3、在Ascend310执行推理量化模型。
|
||||
|
||||
```shell
|
||||
# Ascend310 inference
|
||||
bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]
|
||||
```
|
||||
|
||||
推理结果保存在脚本执行的当前路径,可以在acc.log中看到精度计算结果。
|
||||
|
||||
```bash
|
||||
Cross valid dice coeff is: 0.9139793866877975
|
||||
```
|
||||
|
||||
#### 继续训练预训练模型
|
||||
|
||||
在`config.py`里将`resume`设置成True,并将`resume_ckpt`设置成对应的权重文件路径,例如:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""postprocess for 310 inference"""
|
||||
import os
|
||||
import argparse
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
import mindspore.nn as nn
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser("unet quant postprocess")
|
||||
parser.add_argument("--result_path", type=str, required=True, help="path to inference results.")
|
||||
parser.add_argument("--label_path", type=str, required=True, help="path to label.npy.")
|
||||
parser.add_argument("--input_path", type=str, required=True, help="path to input data.")
|
||||
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
class dice_coeff(nn.Metric):
|
||||
"""Unet Metric, return dice coefficient and IOU."""
|
||||
|
||||
def __init__(self, print_res=True, show_eval=False):
|
||||
super(dice_coeff, self).__init__()
|
||||
self.clear()
|
||||
self.show_eval = show_eval
|
||||
self.print_res = print_res
|
||||
self.img_num = 0
|
||||
# network config
|
||||
self.include_background = True
|
||||
self.eval_resize = False
|
||||
self.num_classes = 2
|
||||
|
||||
def clear(self):
|
||||
self._dice_coeff_sum = 0
|
||||
self._iou_sum = 0
|
||||
self._samples_num = 0
|
||||
self.img_num = 0
|
||||
|
||||
def update(self, *inputs):
|
||||
if len(inputs) != 2:
|
||||
raise ValueError('Need 2 inputs (y_predict, y), but got {}'.format(len(inputs)))
|
||||
y = self._convert_data(inputs[1])
|
||||
self._samples_num += y.shape[0]
|
||||
y = y.transpose(0, 2, 3, 1)
|
||||
b, h, w, c = y.shape
|
||||
if b != 1:
|
||||
raise ValueError('Batch size should be 1 when in evaluation.')
|
||||
y = y.reshape((h, w, c))
|
||||
start_index = 0
|
||||
if not self.include_background:
|
||||
y = y[:, :, 1:]
|
||||
start_index = 1
|
||||
|
||||
y_softmax = np.squeeze(self._convert_data(inputs[0]), axis=0)
|
||||
if self.eval_resize:
|
||||
y_pred = []
|
||||
for i in range(start_index, self.num_classes):
|
||||
y_pred.append(cv2.resize(np.uint8(y_softmax[:, :, i] * 255), (w, h)) / 255)
|
||||
y_pred = np.stack(y_pred, axis=-1)
|
||||
else:
|
||||
y_pred = y_softmax
|
||||
if not self.include_background:
|
||||
y_pred = y_softmax[:, :, start_index:]
|
||||
|
||||
y_pred = y_pred.astype(np.float32)
|
||||
inter = np.dot(y_pred.flatten(), y.flatten())
|
||||
union = np.dot(y_pred.flatten(), y_pred.flatten()) + np.dot(y.flatten(), y.flatten())
|
||||
|
||||
single_dice_coeff = 2 * float(inter) / float(union + 1e-6)
|
||||
single_iou = single_dice_coeff / (2 - single_dice_coeff)
|
||||
if self.print_res:
|
||||
print("single dice coeff is: {}, IOU is: {}".format(single_dice_coeff, single_iou))
|
||||
self._dice_coeff_sum += single_dice_coeff
|
||||
self._iou_sum += single_iou
|
||||
|
||||
def eval(self):
|
||||
if self._samples_num == 0:
|
||||
raise RuntimeError('Total samples num must not be 0.')
|
||||
return (self._dice_coeff_sum / float(self._samples_num), self._iou_sum / float(self._samples_num))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
metrics = dice_coeff()
|
||||
# eval_activate = "softmax"
|
||||
|
||||
label_list = np.load(args.label_path)
|
||||
for j in range(len(os.listdir(args.input_path))):
|
||||
file_name = os.path.join(args.result_path, "ISBI_test_bs_1_" + str(j) + "_output_0.bin")
|
||||
rst_out = np.fromfile(file_name, np.float32).reshape(1, 388, 388, 2)
|
||||
label = label_list[j]
|
||||
metrics.update(rst_out, label)
|
||||
eval_score = metrics.eval()
|
||||
print("==================== Cross valid dice coeff is:", eval_score[0])
|
||||
print("==================== Cross valid dice IOU is:", eval_score[1])
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""unet 310 infer preprocess dataset"""
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import numpy as np
|
||||
|
||||
|
||||
def generate_data(data_dir, result_path, cross_valid_ind=1):
|
||||
"""
|
||||
Generate data and label needed for AIR model inference at Ascend310 platform.
|
||||
"""
|
||||
|
||||
_, valid_dataset = create_dataset(data_dir, 1, 1, False, cross_valid_ind, False, do_crop=config.crop,
|
||||
img_size=config.image_size)
|
||||
labels_list = []
|
||||
img_path = os.path.join(result_path, "00_data")
|
||||
if os.path.exists(img_path):
|
||||
shutil.rmtree(img_path)
|
||||
os.makedirs(img_path)
|
||||
|
||||
for i, data in enumerate(valid_dataset):
|
||||
file_name = "ISBI_test_bs_1_" + str(i) + ".bin"
|
||||
file_path = os.path.join(img_path, file_name)
|
||||
data[0].asnumpy().tofile(file_path)
|
||||
labels_list.append(data[1].asnumpy())
|
||||
np.save(os.path.join(result_path, "label.npy"), labels_list)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.path.append("..")
|
||||
from src.data_loader import create_dataset
|
||||
from src.model_utils.config import config
|
||||
|
||||
generate_data(data_dir=config.data_path, cross_valid_ind=config.cross_valid_ind, result_path=config.result_path)
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* ModelProcess
|
||||
*/
|
||||
class ModelProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~ModelProcess();
|
||||
|
||||
/**
|
||||
* @brief load model from file with mem
|
||||
* @param [in] modelPath: model path
|
||||
* @return result
|
||||
*/
|
||||
Result LoadModelFromFileWithMem(const char *modelPath);
|
||||
|
||||
/**
|
||||
* @brief unload model
|
||||
*/
|
||||
void Unload();
|
||||
|
||||
/**
|
||||
* @brief create model desc
|
||||
* @return result
|
||||
*/
|
||||
Result CreateDesc();
|
||||
|
||||
/**
|
||||
* @brief destroy desc
|
||||
*/
|
||||
void DestroyDesc();
|
||||
|
||||
/**
|
||||
* @brief create model input
|
||||
* @param [in] inputDataBuffer: input buffer
|
||||
* @param [in] bufferSize: input buffer size
|
||||
* @return result
|
||||
*/
|
||||
Result CreateInput(void *inputDataBuffer, size_t bufferSize);
|
||||
|
||||
/**
|
||||
* @brief destroy input resource
|
||||
*/
|
||||
void DestroyInput();
|
||||
|
||||
/**
|
||||
* @brief create output buffer
|
||||
* @return result
|
||||
*/
|
||||
Result CreateOutput();
|
||||
|
||||
/**
|
||||
* @brief destroy output resource
|
||||
*/
|
||||
void DestroyOutput();
|
||||
|
||||
/**
|
||||
* @brief model execute
|
||||
* @return result
|
||||
*/
|
||||
Result Execute();
|
||||
|
||||
/**
|
||||
* @brief dump model output result to file
|
||||
*/
|
||||
void DumpModelOutputResult(char *output_name);
|
||||
|
||||
/**
|
||||
* @brief get model output result
|
||||
*/
|
||||
void OutputModelResult();
|
||||
|
||||
private:
|
||||
uint32_t modelId_;
|
||||
size_t modelMemSize_;
|
||||
size_t modelWeightSize_;
|
||||
void *modelMemPtr_;
|
||||
void *modelWeightPtr_;
|
||||
bool loadFlag_; // model load flag
|
||||
aclmdlDesc *modelDesc_;
|
||||
aclmdlDataset *input_;
|
||||
aclmdlDataset *output_;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../inc/utils.h"
|
||||
#include "acl/acl.h"
|
||||
|
||||
/**
|
||||
* SampleProcess
|
||||
*/
|
||||
class SampleProcess {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~SampleProcess();
|
||||
|
||||
/**
|
||||
* @brief init reousce
|
||||
* @return result
|
||||
*/
|
||||
Result InitResource();
|
||||
|
||||
/**
|
||||
* @brief sample process
|
||||
* @return result
|
||||
*/
|
||||
Result Process(char *om_path, char *input_folder);
|
||||
|
||||
void GetAllFiles(std::string path, std::vector<std::string> *files);
|
||||
|
||||
private:
|
||||
void DestroyResource();
|
||||
|
||||
int32_t deviceId_;
|
||||
aclrtContext context_;
|
||||
aclrtStream stream_;
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args)
|
||||
#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args)
|
||||
#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args)
|
||||
|
||||
typedef enum Result {
|
||||
SUCCESS = 0,
|
||||
FAILED = 1
|
||||
} Result;
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
class Utils {
|
||||
public:
|
||||
/**
|
||||
* @brief create device buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return device buffer of file
|
||||
*/
|
||||
static void *GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize);
|
||||
|
||||
/**
|
||||
* @brief create buffer of file
|
||||
* @param [in] fileName: file name
|
||||
* @param [out] fileSize: size of file
|
||||
* @return buffer of pic
|
||||
*/
|
||||
static void* ReadBinFile(std::string fileName, uint32_t *fileSize);
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
"""do post training quantization for Ascend310"""
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from amct_mindspore.quantize_tool import create_quant_config
|
||||
from amct_mindspore.quantize_tool import quantize_model
|
||||
from amct_mindspore.quantize_tool import save_model
|
||||
from mindspore import Tensor, context
|
||||
from mindspore.train.model import Model
|
||||
from mindspore.train.serialization import load_checkpoint, load_param_into_net
|
||||
|
||||
def quant_unet(network, dataset, input_data):
|
||||
"""
|
||||
Export post training quantization model of AIR format.
|
||||
|
||||
Args:
|
||||
network: the origin network for inference.
|
||||
dataset: the data for inference.
|
||||
input_data: the data used for constructing network. The shape and format of input data should be the same as
|
||||
actual data for inference.
|
||||
"""
|
||||
|
||||
# step2: create the quant config json file
|
||||
create_quant_config("./config.json", network, input_data)
|
||||
|
||||
# step3: do some network modification and return the modified network
|
||||
calibration_network = quantize_model("./config.json", network, input_data)
|
||||
calibration_network.set_train(False)
|
||||
|
||||
# step4: perform the evaluation of network to do activation calibration
|
||||
model = Model(calibration_network, loss_fn=TempLoss(), metrics={"dice_coff": dice_coeff()})
|
||||
_ = model.eval(dataset, dataset_sink_mode=False)
|
||||
|
||||
# step5: export the air file
|
||||
save_model("results/unet_quant", calibration_network, input_data)
|
||||
print("[INFO] the quantized AIR file has been stored at: \n {}".format("results/unet_quant.air"))
|
||||
|
||||
|
||||
def run_export():
|
||||
"""run export."""
|
||||
if config.model_name == 'unet_medical':
|
||||
net = UNetMedical(n_channels=config.num_channels, n_classes=config.num_classes)
|
||||
else:
|
||||
raise ValueError("post training quantization currently does not support model: {}".format(config.model_name))
|
||||
# return a parameter dict for model
|
||||
param_dict = load_checkpoint(config.checkpoint_file_path)
|
||||
# load the parameter into net
|
||||
load_param_into_net(net, param_dict)
|
||||
net = UnetEval(net, eval_activate="softmax")
|
||||
batch_size = 1
|
||||
input_data = Tensor(np.ones([batch_size, config.num_channels, config.height, config.width]).astype(np.float32))
|
||||
_, valid_dataset = create_dataset(config.data_path, 1, batch_size, False, 1, False, do_crop=config.crop,
|
||||
img_size=config.image_size)
|
||||
dataset = valid_dataset.take(1)
|
||||
quant_unet(net, dataset, input_data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.append("..")
|
||||
from src.data_loader import create_dataset
|
||||
from src.unet_medical import UNetMedical
|
||||
from src.utils import UnetEval, TempLoss, dice_coeff
|
||||
from src.model_utils.config import config
|
||||
from src.model_utils.device_adapter import get_device_id
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=get_device_id())
|
||||
|
||||
run_export()
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Usage: bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]"
|
||||
echo "Example: bash run_quant_infer.sh ./unet_quant.air ./data ./label_ids.npy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_real_path(){
|
||||
if [ "${1:0:1}" == "/" ]; then
|
||||
echo "$1"
|
||||
else
|
||||
echo "$(realpath -m $PWD/$1)"
|
||||
fi
|
||||
}
|
||||
model=$(get_real_path $1)
|
||||
data_path=$(get_real_path $2)
|
||||
label_path=$(get_real_path $3)
|
||||
|
||||
echo "air name: "$model
|
||||
echo "dataset path: "$data_path
|
||||
echo "label path: "$label_path
|
||||
|
||||
export ASCEND_HOME=/usr/local/Ascend/
|
||||
if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then
|
||||
export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe
|
||||
export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp
|
||||
else
|
||||
export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH
|
||||
export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH
|
||||
export ASCEND_OPP_PATH=$ASCEND_HOME/opp
|
||||
fi
|
||||
|
||||
function air_to_om()
|
||||
{
|
||||
atc --input_format=NCHW --framework=1 --model=$model --output=unet_quant --soc_version=Ascend310 &> atc.log
|
||||
}
|
||||
|
||||
function compile_app()
|
||||
{
|
||||
bash ./src/build.sh &> build.log
|
||||
}
|
||||
|
||||
function infer()
|
||||
{
|
||||
if [ -d result ]; then
|
||||
rm -rf ./result
|
||||
fi
|
||||
mkdir result
|
||||
./out/main ./unet_quant.om $data_path &> infer.log
|
||||
}
|
||||
|
||||
function cal_acc()
|
||||
{
|
||||
python3.7 ./acc.py --result_path=./result --label_path=$label_path --input_path=$data_path &> acc.log
|
||||
}
|
||||
|
||||
echo "start atc================================================"
|
||||
air_to_om
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "air to om code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start compile============================================"
|
||||
compile_app
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "compile app code failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start infer=============================================="
|
||||
infer
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " execute inference failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "start calculate acc======================================"
|
||||
cal_acc
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "calculate accuracy failed"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
|
||||
|
||||
# CMake lowest version requirement
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
# project information
|
||||
project(InferClassification)
|
||||
# Check environment variable
|
||||
if(NOT DEFINED ENV{ASCEND_HOME})
|
||||
message(FATAL_ERROR "please define environment variable:ASCEND_HOME")
|
||||
endif()
|
||||
|
||||
# Compile options
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined")
|
||||
|
||||
# Skip build rpath
|
||||
set(CMAKE_SKIP_BUILD_RPATH True)
|
||||
|
||||
# Set output directory
|
||||
set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/../out)
|
||||
|
||||
# Set include directory and library directory
|
||||
set(FWKACL_LIB_DIR $ENV{ASCEND_HOME}/fwkacllib)
|
||||
set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib)
|
||||
set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib)
|
||||
|
||||
# Header path
|
||||
include_directories(${ACL_LIB_DIR}/include/)
|
||||
include_directories(${FWKACL_LIB_DIR}/include/)
|
||||
include_directories(${ATLAS_ACL_LIB_DIR}/include/)
|
||||
include_directories(${PROJECT_SRC_ROOT}/../inc)
|
||||
|
||||
# add host lib path
|
||||
link_directories(${ACL_LIB_DIR} ${FWKACL_LIB_DIR})
|
||||
find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${FWKACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64)
|
||||
|
||||
add_executable(main utils.cpp
|
||||
sample_process.cpp
|
||||
model_process.cpp
|
||||
main.cpp)
|
||||
|
||||
target_link_libraries(main ${acl} gflags pthread)
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# 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.
|
||||
# ============================================================================
|
||||
path_cur=$(cd "`dirname $0`" || exit; pwd)
|
||||
|
||||
function preparePath() {
|
||||
rm -rf $1
|
||||
mkdir -p $1
|
||||
cd $1 || exit
|
||||
}
|
||||
|
||||
function buildA300() {
|
||||
if [ ! "${ARCH_PATTERN}" ]; then
|
||||
# set ARCH_PATTERN to acllib when it was not specified by user
|
||||
export ARCH_PATTERN=acllib
|
||||
echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}"
|
||||
else
|
||||
echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib"
|
||||
export ARCH_PATTERN=${ARCH_PATTERN}/acllib
|
||||
fi
|
||||
|
||||
path_build=$path_cur/build
|
||||
preparePath $path_build
|
||||
cmake ..
|
||||
make -j
|
||||
ret=$?
|
||||
cd ..
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user
|
||||
if [ ! "${ASCEND_VERSION}" ]; then
|
||||
export ASCEND_VERSION=ascend-toolkit/latest
|
||||
echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}"
|
||||
else
|
||||
echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user"
|
||||
fi
|
||||
|
||||
buildA300
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include "../inc/sample_process.h"
|
||||
#include "../inc/utils.h"
|
||||
bool g_is_device = false;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
ERROR_LOG("usage:./main path_of_om path_of_inputFolder");
|
||||
return FAILED;
|
||||
}
|
||||
SampleProcess processSample;
|
||||
Result ret = processSample.InitResource();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample init resource failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processSample.Process(argv[1], argv[2]);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("sample process failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("execute sample success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/model_process.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
|
||||
ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr),
|
||||
modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) {
|
||||
}
|
||||
|
||||
ModelProcess::~ModelProcess() {
|
||||
Unload();
|
||||
DestroyDesc();
|
||||
DestroyInput();
|
||||
DestroyOutput();
|
||||
}
|
||||
|
||||
Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) {
|
||||
if (loadFlag_) {
|
||||
ERROR_LOG("has already loaded a model");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("query model failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_,
|
||||
modelMemSize_, modelWeightPtr_, modelWeightSize_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("load model from file failed, model file is %s", modelPath);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
loadFlag_ = true;
|
||||
INFO_LOG("load model %s success", modelPath);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateDesc() {
|
||||
modelDesc_ = aclmdlCreateDesc();
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("create model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlGetDesc(modelDesc_, modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("get model description failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("create model description success");
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyDesc() {
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) {
|
||||
input_ = aclmdlCreateDataset();
|
||||
if (input_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize);
|
||||
if (inputData == nullptr) {
|
||||
ERROR_LOG("can't create data buffer, create input failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlAddDatasetBuffer(input_, inputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("add input dataset buffer failed");
|
||||
aclDestroyDataBuffer(inputData);
|
||||
inputData = nullptr;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyInput() {
|
||||
if (input_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i);
|
||||
aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
aclmdlDestroyDataset(input_);
|
||||
input_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::CreateOutput() {
|
||||
if (modelDesc_ == nullptr) {
|
||||
ERROR_LOG("no model description, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
output_ = aclmdlCreateDataset();
|
||||
if (output_ == nullptr) {
|
||||
ERROR_LOG("can't create dataset, create output failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
size_t outputSize = aclmdlGetNumOutputs(modelDesc_);
|
||||
for (size_t i = 0; i < outputSize; ++i) {
|
||||
size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i);
|
||||
|
||||
void *outputBuffer = nullptr;
|
||||
aclError ret = aclrtMalloc(&outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't create data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = aclmdlAddDatasetBuffer(output_, outputData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("can't add data buffer, create output failed");
|
||||
aclrtFree(outputBuffer);
|
||||
aclDestroyDataBuffer(outputData);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("create model output success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::DumpModelOutputResult(char *output_name) {
|
||||
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);
|
||||
|
||||
for (size_t i = 0; i < outputNum; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "result/" << output_name << "_output_" << i << ".bin";
|
||||
std::string outputFileName = ss.str();
|
||||
FILE *outputFile = fopen(outputFileName.c_str(), "wb");
|
||||
if (outputFile) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void* outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
(void)aclrtFreeHost(outHostData);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(outHostData, len, sizeof(char), outputFile);
|
||||
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fwrite(data, len, sizeof(char), outputFile);
|
||||
}
|
||||
fclose(outputFile);
|
||||
outputFile = nullptr;
|
||||
} else {
|
||||
ERROR_LOG("create output file [%s] failed", outputFileName.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("dump data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::OutputModelResult() {
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);
|
||||
|
||||
void *outHostData = NULL;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
float *outData = NULL;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&outHostData, len);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
outData = reinterpret_cast<float*>(outHostData);
|
||||
} else {
|
||||
outData = reinterpret_cast<float*>(data);
|
||||
}
|
||||
std::map<float, unsigned int, std::greater<float> > resultMap;
|
||||
for (unsigned int j = 0; j < len / sizeof(float); ++j) {
|
||||
resultMap[*outData] = j;
|
||||
outData++;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (auto it = resultMap.begin(); it != resultMap.end(); ++it) {
|
||||
// print top 5
|
||||
if (++cnt > 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first);
|
||||
}
|
||||
if (!g_is_device) {
|
||||
ret = aclrtFreeHost(outHostData);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG("output data success");
|
||||
return;
|
||||
}
|
||||
|
||||
void ModelProcess::DestroyOutput() {
|
||||
if (output_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
|
||||
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
|
||||
void* data = aclGetDataBufferAddr(dataBuffer);
|
||||
(void)aclrtFree(data);
|
||||
(void)aclDestroyDataBuffer(dataBuffer);
|
||||
}
|
||||
|
||||
(void)aclmdlDestroyDataset(output_);
|
||||
output_ = nullptr;
|
||||
}
|
||||
|
||||
Result ModelProcess::Execute() {
|
||||
aclError ret = aclmdlExecute(modelId_, input_, output_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("execute model failed, modelId is %u", modelId_);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
INFO_LOG("model execute success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void ModelProcess::Unload() {
|
||||
if (!loadFlag_) {
|
||||
WARN_LOG("no model had been loaded, unload failed");
|
||||
return;
|
||||
}
|
||||
|
||||
aclError ret = aclmdlUnload(modelId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("unload model failed, modelId is %u", modelId_);
|
||||
}
|
||||
|
||||
if (modelDesc_ != nullptr) {
|
||||
(void)aclmdlDestroyDesc(modelDesc_);
|
||||
modelDesc_ = nullptr;
|
||||
}
|
||||
|
||||
if (modelMemPtr_ != nullptr) {
|
||||
aclrtFree(modelMemPtr_);
|
||||
modelMemPtr_ = nullptr;
|
||||
modelMemSize_ = 0;
|
||||
}
|
||||
|
||||
if (modelWeightPtr_ != nullptr) {
|
||||
aclrtFree(modelWeightPtr_);
|
||||
modelWeightPtr_ = nullptr;
|
||||
modelWeightSize_ = 0;
|
||||
}
|
||||
|
||||
loadFlag_ = false;
|
||||
INFO_LOG("unload model success, modelId is %u", modelId_);
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/sample_process.h"
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../inc/model_process.h"
|
||||
#include "acl/acl.h"
|
||||
#include "../inc/utils.h"
|
||||
extern bool g_is_device;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) {
|
||||
}
|
||||
|
||||
SampleProcess::~SampleProcess() {
|
||||
DestroyResource();
|
||||
}
|
||||
|
||||
Result SampleProcess::InitResource() {
|
||||
// ACL init
|
||||
|
||||
const char *aclConfigPath = "./src/acl.json";
|
||||
aclError ret = aclInit(aclConfigPath);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl init failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("acl init success");
|
||||
|
||||
// open device
|
||||
ret = aclrtSetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl open device %d failed", deviceId_);
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("open device %d success", deviceId_);
|
||||
|
||||
// create context (set current)
|
||||
ret = aclrtCreateContext(&context_, deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create context failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create context success");
|
||||
|
||||
// create stream
|
||||
ret = aclrtCreateStream(&stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl create stream failed");
|
||||
return FAILED;
|
||||
}
|
||||
INFO_LOG("create stream success");
|
||||
|
||||
// get run mode
|
||||
aclrtRunMode runMode;
|
||||
ret = aclrtGetRunMode(&runMode);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("acl get run mode failed");
|
||||
return FAILED;
|
||||
}
|
||||
g_is_device = (runMode == ACL_DEVICE);
|
||||
INFO_LOG("get run mode success");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::GetAllFiles(std::string path, std::vector<string> *files) {
|
||||
DIR *pDir = NULL;
|
||||
struct dirent* ptr;
|
||||
if (!(pDir = opendir(path.c_str()))) {
|
||||
return;
|
||||
}
|
||||
while ((ptr = readdir(pDir)) != 0) {
|
||||
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
|
||||
files->push_back(path + "/" + ptr->d_name);
|
||||
}
|
||||
}
|
||||
closedir(pDir);
|
||||
}
|
||||
|
||||
Result SampleProcess::Process(char *om_path, char *input_folder) {
|
||||
// model init
|
||||
double second_to_millisecond = 1000;
|
||||
double second_to_microsecond = 1000000;
|
||||
|
||||
double whole_cost_time = 0.0;
|
||||
struct timeval start_global = {0};
|
||||
struct timeval end_global = {0};
|
||||
double startTimeMs_global = 0.0;
|
||||
double endTimeMs_global = 0.0;
|
||||
|
||||
gettimeofday(&start_global, nullptr);
|
||||
|
||||
ModelProcess processModel;
|
||||
const char* omModelPath = om_path;
|
||||
|
||||
Result ret = processModel.LoadModelFromFileWithMem(omModelPath);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute LoadModelFromFileWithMem failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateDesc();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateDesc failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ret = processModel.CreateOutput();
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateOutput failed");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
std::vector<string> testFile;
|
||||
GetAllFiles(input_folder, &testFile);
|
||||
|
||||
if (testFile.size() == 0) {
|
||||
WARN_LOG("no input data under folder");
|
||||
}
|
||||
|
||||
double model_cost_time = 0.0;
|
||||
double edge_to_edge_model_cost_time = 0.0;
|
||||
|
||||
for (size_t index = 0; index < testFile.size(); ++index) {
|
||||
INFO_LOG("start to process file:%s", testFile[index].c_str());
|
||||
// model process
|
||||
|
||||
struct timeval time_init = {0};
|
||||
double timeval_init = 0.0;
|
||||
gettimeofday(&time_init, nullptr);
|
||||
timeval_init = (time_init.tv_sec * second_to_microsecond + time_init.tv_usec) / second_to_millisecond;
|
||||
|
||||
uint32_t devBufferSize;
|
||||
void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize);
|
||||
if (picDevBuffer == nullptr) {
|
||||
ERROR_LOG("get pic device buffer failed,index is %zu", index);
|
||||
return FAILED;
|
||||
}
|
||||
ret = processModel.CreateInput(picDevBuffer, devBufferSize);
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute CreateInput failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
struct timeval start = {0};
|
||||
struct timeval end = {0};
|
||||
double startTimeMs = 0.0;
|
||||
double endTimeMs = 0.0;
|
||||
gettimeofday(&start, nullptr);
|
||||
startTimeMs = (start.tv_sec * second_to_microsecond + start.tv_usec) / second_to_millisecond;
|
||||
|
||||
ret = processModel.Execute();
|
||||
|
||||
gettimeofday(&end, nullptr);
|
||||
endTimeMs = (end.tv_sec * second_to_microsecond + end.tv_usec) / second_to_millisecond;
|
||||
|
||||
double cost_time = endTimeMs - startTimeMs;
|
||||
INFO_LOG("model infer time: %lf ms", cost_time);
|
||||
|
||||
model_cost_time += cost_time;
|
||||
|
||||
double edge_to_edge_cost_time = endTimeMs - timeval_init;
|
||||
edge_to_edge_model_cost_time += edge_to_edge_cost_time;
|
||||
|
||||
if (ret != SUCCESS) {
|
||||
ERROR_LOG("execute inference failed");
|
||||
aclrtFree(picDevBuffer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
int pos = testFile[index].find_last_of('/');
|
||||
std::string name = testFile[index].substr(pos+1);
|
||||
std::string outputname = name.substr(0, name.rfind("."));
|
||||
|
||||
// dump output result to file in the current directory
|
||||
processModel.DumpModelOutputResult(const_cast<char *>(outputname.c_str()));
|
||||
|
||||
// release model input buffer
|
||||
aclrtFree(picDevBuffer);
|
||||
processModel.DestroyInput();
|
||||
}
|
||||
double test_file_size = 0.0;
|
||||
test_file_size = testFile.size();
|
||||
INFO_LOG("infer dataset size:%lf", test_file_size);
|
||||
|
||||
gettimeofday(&end_global, nullptr);
|
||||
startTimeMs_global = (start_global.tv_sec * second_to_microsecond + start_global.tv_usec) / second_to_millisecond;
|
||||
endTimeMs_global = (end_global.tv_sec * second_to_microsecond + end_global.tv_usec) / second_to_millisecond;
|
||||
whole_cost_time = (endTimeMs_global - startTimeMs_global) / test_file_size;
|
||||
|
||||
model_cost_time /= test_file_size;
|
||||
INFO_LOG("model cost time per sample: %lf ms", model_cost_time);
|
||||
edge_to_edge_model_cost_time /= test_file_size;
|
||||
INFO_LOG("edge-to-edge model cost time per sample:%lf ms", edge_to_edge_model_cost_time);
|
||||
INFO_LOG("whole cost time per sample: %lf ms", whole_cost_time);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void SampleProcess::DestroyResource() {
|
||||
aclError ret;
|
||||
if (stream_ != nullptr) {
|
||||
ret = aclrtDestroyStream(stream_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy stream failed");
|
||||
}
|
||||
stream_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy stream");
|
||||
|
||||
if (context_ != nullptr) {
|
||||
ret = aclrtDestroyContext(context_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("destroy context failed");
|
||||
}
|
||||
context_ = nullptr;
|
||||
}
|
||||
INFO_LOG("end to destroy context");
|
||||
|
||||
ret = aclrtResetDevice(deviceId_);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("reset device failed");
|
||||
}
|
||||
INFO_LOG("end to reset device is %d", deviceId_);
|
||||
|
||||
ret = aclFinalize();
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("finalize acl failed");
|
||||
}
|
||||
INFO_LOG("end to finalize acl");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* 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 "../inc/utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "acl/acl.h"
|
||||
|
||||
extern bool g_is_device;
|
||||
|
||||
void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) {
|
||||
struct stat sBuf;
|
||||
int fileStatus = stat(fileName.data(), &sBuf);
|
||||
if (fileStatus == -1) {
|
||||
ERROR_LOG("failed to get file");
|
||||
return nullptr;
|
||||
}
|
||||
if (S_ISREG(sBuf.st_mode) == 0) {
|
||||
ERROR_LOG("%s is not a file, please enter a file", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream binFile(fileName, std::ifstream::binary);
|
||||
if (binFile.is_open() == false) {
|
||||
ERROR_LOG("open file %s failed", fileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.end);
|
||||
uint32_t binFileBufferLen = binFile.tellg();
|
||||
if (binFileBufferLen == 0) {
|
||||
ERROR_LOG("binfile is empty, filename is %s", fileName.c_str());
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binFile.seekg(0, binFile.beg);
|
||||
|
||||
void* binFileBufferData = nullptr;
|
||||
aclError ret = ACL_ERROR_NONE;
|
||||
if (!g_is_device) {
|
||||
ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc for binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
if (binFileBufferData == nullptr) {
|
||||
ERROR_LOG("malloc binFileBufferData failed");
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen);
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
binFile.read(static_cast<char *>(binFileBufferData), binFileBufferLen);
|
||||
binFile.close();
|
||||
*fileSize = binFileBufferLen;
|
||||
return binFileBufferData;
|
||||
}
|
||||
|
||||
void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize) {
|
||||
uint32_t inputHostBuffSize = 0;
|
||||
void* inputHostBuff = Utils::ReadBinFile(fileName, &inputHostBuffSize);
|
||||
if (inputHostBuff == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!g_is_device) {
|
||||
void *inBufferDev = nullptr;
|
||||
uint32_t inBufferSize = inputHostBuffSize;
|
||||
aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE);
|
||||
if (ret != ACL_ERROR_NONE) {
|
||||
ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u",
|
||||
inBufferSize, inputHostBuffSize);
|
||||
aclrtFree(inBufferDev);
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
return nullptr;
|
||||
}
|
||||
aclrtFreeHost(inputHostBuff);
|
||||
*fileSize = inBufferSize;
|
||||
return inBufferDev;
|
||||
} else {
|
||||
*fileSize = inputHostBuffSize;
|
||||
return inputHostBuff;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Usage: bash run_quant_infer.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH]"
|
||||
echo "Example: bash run_quant_infer.sh ./vgg_quant.air ./00_data ./cifar10_label_ids.npy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue