Browse Source

ctpn and naml 310 inference code

tags/v1.2.0-rc1
yuzhenhua 4 years ago
parent
commit
1761776fe9
22 changed files with 2515 additions and 1 deletions
  1. +47
    -0
      model_zoo/official/cv/ctpn/README.md
  2. +14
    -0
      model_zoo/official/cv/ctpn/ascend310_infer/CMakeLists.txt
  3. +23
    -0
      model_zoo/official/cv/ctpn/ascend310_infer/build.sh
  4. +32
    -0
      model_zoo/official/cv/ctpn/ascend310_infer/inc/utils.h
  5. +152
    -0
      model_zoo/official/cv/ctpn/ascend310_infer/src/main.cc
  6. +130
    -0
      model_zoo/official/cv/ctpn/ascend310_infer/src/utils.cc
  7. +51
    -0
      model_zoo/official/cv/ctpn/export.py
  8. +108
    -0
      model_zoo/official/cv/ctpn/postprocess.py
  9. +123
    -0
      model_zoo/official/cv/ctpn/scripts/run_infer_310.sh
  10. +10
    -0
      model_zoo/official/cv/ctpn/src/ctpn.py
  11. +17
    -1
      model_zoo/official/recommend/naml/README.md
  12. +64
    -0
      model_zoo/official/recommend/naml/ascend310_infer/CMakeLists.txt
  13. +23
    -0
      model_zoo/official/recommend/naml/ascend310_infer/build.sh
  14. +94
    -0
      model_zoo/official/recommend/naml/ascend310_infer/inc/model_process.h
  15. +71
    -0
      model_zoo/official/recommend/naml/ascend310_infer/inc/sample_process.h
  16. +51
    -0
      model_zoo/official/recommend/naml/ascend310_infer/inc/utils.h
  17. +84
    -0
      model_zoo/official/recommend/naml/ascend310_infer/src/main.cpp
  18. +598
    -0
      model_zoo/official/recommend/naml/ascend310_infer/src/model_process.cpp
  19. +354
    -0
      model_zoo/official/recommend/naml/ascend310_infer/src/sample_process.cpp
  20. +246
    -0
      model_zoo/official/recommend/naml/ascend310_infer/src/utils.cpp
  21. +100
    -0
      model_zoo/official/recommend/naml/postprocess.py
  22. +123
    -0
      model_zoo/official/recommend/naml/script/run_infer_310.sh

+ 47
- 0
model_zoo/official/cv/ctpn/README.md View File

@@ -72,11 +72,13 @@ Here we used 6 datasets for training, and 1 datasets for Evaluation.
.
└─ctpn
├── README.md # network readme
├──ascend310_infer #application for 310 inference
├── eval.py # eval net
├── scripts
│   ├── eval_res.sh # calculate precision and recall
│   ├── run_distribute_train_ascend.sh # launch distributed training with ascend platform(8p)
│   ├── run_eval_ascend.sh # launch evaluating with ascend platform
│ ├──run_infer_310.sh # shell script for 310 inference
│   └── run_standalone_train_ascend.sh # launch standalone training with ascend platform(1p)
├── src
│   ├── CTPN
@@ -102,6 +104,8 @@ Here we used 6 datasets for training, and 1 datasets for Evaluation.
│   ├── detector.py # detect box
│   ├── get_successions.py # get succession proposal
│   └── utils.py # some functions which is commonly used
├──postprogress.py # post process for 310 inference
├──export.py # script to export AIR,MINDIR model
└── train.py # train net

```
@@ -239,6 +243,49 @@ Evaluation result will be stored in the example path, you can find result like t
{"precision": 0.90791, "recall": 0.86118, "hmean": 0.88393}
```

## Model Export

```shell
python export.py --ckpt_file [CKPT_PATH] --device_target [DEVICE_TARGET] --file_format[EXPORT_FORMAT]
```

`EXPORT_FORMAT` should be in ["AIR", "MINDIR"]

## [Inference process](#contents)

### Usage

Before performing inference, the air file must bu exported by export script on the Ascend910 environment.

```shell
# Ascend310 inference
bash run_infer_310.sh [MODEL_PATH] [DATA_PATH] [ANN_FILE_PATH] [DEVICE_ID]]
```

After inference, you can get a archive file named submit.zip.To evalulate it, you can use the scripts provided by the ICDAR2013 network, you can download the Deteval scripts from the [link](https://rrc.cvc.uab.es/?com=downloads&action=download&ch=2&f=aHR0cHM6Ly9ycmMuY3ZjLnVhYi5lcy9zdGFuZGFsb25lcy9zY3JpcHRfdGVzdF9jaDJfdDFfZTItMTU3Nzk4MzA2Ny56aXA=)
After download the scripts, unzip it and put it under ctpn/scripts and use eval_res.sh to get the result.You will get files as below:

```text
gt.zip
readme.txt
rrc_evalulation_funcs_1_1.py
script.py
```

Then you can run the scripts/eval_res.sh to calculate the evalulation result.

```base
bash eval_res.sh
```

### Result

Evaluation result will be stored in the example path, you can find result like the followings in `log`.

```text
{"precision": 0.88913, "recall": 0.86082, "hmean": 0.87475}
```

# [Model description](#contents)

## [Performance](#contents)


+ 14
- 0
model_zoo/official/cv/ctpn/ascend310_infer/CMakeLists.txt View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.14.1)
project(Ascend310Infer)
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")
set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/)
option(MINDSPORE_PATH "mindspore install path" "")
include_directories(${MINDSPORE_PATH})
include_directories(${MINDSPORE_PATH}/include)
include_directories(${PROJECT_SRC_ROOT})
find_library(MS_LIB libmindspore.so ${MINDSPORE_PATH}/lib)
file(GLOB_RECURSE MD_LIB ${MINDSPORE_PATH}/_c_dataengine*)

add_executable(main src/main.cc src/utils.cc)
target_link_libraries(main ${MS_LIB} ${MD_LIB} gflags)

+ 23
- 0
model_zoo/official/cv/ctpn/ascend310_infer/build.sh View File

@@ -0,0 +1,23 @@
#!/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 [ ! -d out ]; then
mkdir out
fi
cd out
cmake .. \
-DMINDSPORE_PATH="`pip show mindspore-ascend | grep Location | awk '{print $2"/mindspore"}' | xargs realpath`"
make

+ 32
- 0
model_zoo/official/cv/ctpn/ascend310_infer/inc/utils.h View File

@@ -0,0 +1,32 @@
/**
* 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.
*/

#ifndef MINDSPORE_INFERENCE_UTILS_H_
#define MINDSPORE_INFERENCE_UTILS_H_

#include <sys/stat.h>
#include <dirent.h>
#include <vector>
#include <string>
#include <memory>
#include "include/api/types.h"

std::vector<std::string> GetAllFiles(std::string_view dirName);
DIR *OpenDir(std::string_view dirName);
std::string RealPath(std::string_view path);
mindspore::MSTensor ReadFileToTensor(const std::string &file);
int WriteResult(const std::string& imageFile, const std::vector<mindspore::MSTensor> &outputs);
#endif

+ 152
- 0
model_zoo/official/cv/ctpn/ascend310_infer/src/main.cc View File

@@ -0,0 +1,152 @@
/**
* 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 <sys/time.h>
#include <gflags/gflags.h>
#include <dirent.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <iosfwd>
#include <vector>
#include <fstream>

#include "../inc/utils.h"
#include "minddata/dataset/include/execute.h"
#include "minddata/dataset/include/transforms.h"
#include "minddata/dataset/include/vision.h"
#include "minddata/dataset/include/vision_ascend.h"
#include "include/api/types.h"
#include "include/api/model.h"
#include "include/api/serialization.h"
#include "include/api/context.h"

using mindspore::GlobalContext;
using mindspore::Serialization;
using mindspore::Model;
using mindspore::ModelContext;
using mindspore::Status;
using mindspore::ModelType;
using mindspore::GraphCell;
using mindspore::kSuccess;
using mindspore::MSTensor;
using mindspore::DataType;
using mindspore::dataset::Execute;
using mindspore::dataset::TensorTransform;
using mindspore::dataset::vision::Decode;
using mindspore::dataset::vision::Resize;
using mindspore::dataset::vision::Normalize;
using mindspore::dataset::vision::HWC2CHW;

using mindspore::dataset::transforms::TypeCast;


DEFINE_string(model_path, "", "model path");
DEFINE_string(dataset_path, ".", "dataset path");
DEFINE_int32(input_width, 960, "input width");
DEFINE_int32(input_height, 576, "inputheight");
DEFINE_int32(device_id, 0, "device id");
DEFINE_string(precision_mode, "allow_fp32_to_fp16", "precision mode");
DEFINE_string(op_select_impl_mode, "", "op select impl mode");
DEFINE_string(aipp_path, "./aipp.cfg", "aipp path");
DEFINE_string(device_target, "Ascend310", "device target");

int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (RealPath(FLAGS_model_path).empty()) {
std::cout << "Invalid model" << std::endl;
return 1;
}

GlobalContext::SetGlobalDeviceTarget(FLAGS_device_target);
GlobalContext::SetGlobalDeviceID(FLAGS_device_id);

auto graph = Serialization::LoadModel(FLAGS_model_path, ModelType::kMindIR);

Model model((GraphCell(graph)));
Status ret = model.Build();
if (ret != kSuccess) {
std::cout << "ERROR Build failed." << std::endl;
return 1;
}

auto all_files = GetAllFiles(FLAGS_dataset_path);
if (all_files.empty()) {
std::cout << "ERROR: no input data." << std::endl;
return 1;
}

std::shared_ptr<TensorTransform> decode(new Decode());
std::shared_ptr<TensorTransform> resize(new Resize({576, 960}));
std::shared_ptr<TensorTransform> normalize(new Normalize({123.675, 116.28, 103.53}, {58.395, 57.12, 57.375}));
std::shared_ptr<TensorTransform> hwc2chw(new HWC2CHW());
std::shared_ptr<TensorTransform> typeCast(new TypeCast("float16"));

mindspore::dataset::Execute transformDecode(decode);
mindspore::dataset::Execute transform({resize, normalize, hwc2chw});
mindspore::dataset::Execute transformCast(typeCast);

std::map<double, double> costTime_map;

size_t size = all_files.size();
for (size_t i = 0; i < size; ++i) {
struct timeval start;
struct timeval end;
double startTime_ms;
double endTime_ms;
std::vector<MSTensor> inputs;
std::vector<MSTensor> outputs;

std::cout << "Start predict input files:" << all_files[i] << std::endl;
mindspore::MSTensor image = ReadFileToTensor(all_files[i]);

transformDecode(image, &image);
std::vector<int64_t> shape = image.Shape();
transform(image, &image);
transformCast(image, &image);

inputs.emplace_back(image);

gettimeofday(&start, NULL);
model.Predict(inputs, &outputs);
gettimeofday(&end, NULL);

startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000;
endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000;
costTime_map.insert(std::pair<double, double>(startTime_ms, endTime_ms));
WriteResult(all_files[i], outputs);
}
double average = 0.0;
int infer_cnt = 0;
char tmpCh[256] = {0};
for (auto iter = costTime_map.begin(); iter != costTime_map.end(); iter++) {
double diff = 0.0;
diff = iter->second - iter->first;
average += diff;
infer_cnt++;
}

average = average/infer_cnt;

snprintf(tmpCh, sizeof(tmpCh), "NN inference cost average time: %4.3f ms of infer_count %d\n", average, infer_cnt);
std::cout << "NN inference cost average time: "<< average << "ms of infer_count " << infer_cnt << std::endl;
std::string file_name = "./time_Result" + std::string("/test_perform_static.txt");
std::ofstream file_stream(file_name.c_str(), std::ios::trunc);
file_stream << tmpCh;
file_stream.close();
costTime_map.clear();
return 0;
}

+ 130
- 0
model_zoo/official/cv/ctpn/ascend310_infer/src/utils.cc View File

@@ -0,0 +1,130 @@
/**
* 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 <fstream>
#include <algorithm>
#include <iostream>

using mindspore::MSTensor;
using mindspore::DataType;

std::vector<std::string> GetAllFiles(std::string_view dirName) {
struct dirent *filename;
DIR *dir = OpenDir(dirName);
if (dir == nullptr) {
return {};
}
std::vector<std::string> res;
while ((filename = readdir(dir)) != nullptr) {
std::string dName = std::string(filename->d_name);
if (dName == "." || dName == ".." || filename->d_type != DT_REG) {
continue;
}
res.emplace_back(std::string(dirName) + "/" + filename->d_name);
}
std::sort(res.begin(), res.end());
for (auto &f : res) {
std::cout << "image file: " << f << std::endl;
}
return res;
}

int WriteResult(const std::string& imageFile, const std::vector<MSTensor> &outputs) {
std::string homePath = "./result_Files";
for (size_t i = 0; i < outputs.size(); ++i) {
size_t outputSize;
std::shared_ptr<const void> netOutput;
netOutput = outputs[i].Data();
outputSize = outputs[i].DataSize();
int pos = imageFile.rfind('/');
std::string fileName(imageFile, pos + 1);
fileName.replace(fileName.find('.'), fileName.size() - fileName.find('.'), '_' + std::to_string(i) + ".bin");
std::string outFileName = homePath + "/" + fileName;
FILE * outputFile = fopen(outFileName.c_str(), "wb");
fwrite(netOutput.get(), outputSize, sizeof(char), outputFile);
fclose(outputFile);
outputFile = nullptr;
}
return 0;
}

mindspore::MSTensor ReadFileToTensor(const std::string &file) {
if (file.empty()) {
std::cout << "Pointer file is nullptr" << std::endl;
return mindspore::MSTensor();
}

std::ifstream ifs(file);
if (!ifs.good()) {
std::cout << "File: " << file << " is not exist" << std::endl;
return mindspore::MSTensor();
}

if (!ifs.is_open()) {
std::cout << "File: " << file << "open failed" << std::endl;
return mindspore::MSTensor();
}

ifs.seekg(0, std::ios::end);
size_t size = ifs.tellg();
mindspore::MSTensor buffer(file, mindspore::DataType::kNumberTypeUInt8, {static_cast<int64_t>(size)}, nullptr, size);

ifs.seekg(0, std::ios::beg);
ifs.read(reinterpret_cast<char *>(buffer.MutableData()), size);
ifs.close();

return buffer;
}


DIR *OpenDir(std::string_view dirName) {
if (dirName.empty()) {
std::cout << " dirName is null ! " << std::endl;
return nullptr;
}
std::string realPath = RealPath(dirName);
struct stat s;
lstat(realPath.c_str(), &s);
if (!S_ISDIR(s.st_mode)) {
std::cout << "dirName is not a valid directory !" << std::endl;
return nullptr;
}
DIR *dir;
dir = opendir(realPath.c_str());
if (dir == nullptr) {
std::cout << "Can not open dir " << dirName << std::endl;
return nullptr;
}
std::cout << "Successfully opened the dir " << dirName << std::endl;
return dir;
}

std::string RealPath(std::string_view path) {
char realPathMem[PATH_MAX] = {0};
char *realPathRet = nullptr;
realPathRet = realpath(path.data(), realPathMem);

if (realPathRet == nullptr) {
std::cout << "File: " << path << " is not exist.";
return "";
}

std::string realPath(realPathMem);
std::cout << path << " realpath is: " << realPath << std::endl;
return realPath;
}

+ 51
- 0
model_zoo/official/cv/ctpn/export.py View File

@@ -0,0 +1,51 @@
# 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.
# ============================================================================
"""export checkpoint file into air, onnx, mindir models"""
import argparse
import numpy as np

import mindspore as ms
from mindspore import Tensor, load_checkpoint, load_param_into_net, export, context

from src.ctpn import CTPN_Infer
from src.config import config

parser = argparse.ArgumentParser(description='fasterrcnn_export')
parser.add_argument("--device_id", type=int, default=0, help="Device id")
parser.add_argument("--file_name", type=str, default="ctpn", help="output file name.")
parser.add_argument("--file_format", type=str, choices=["AIR", "MINDIR"], default="MINDIR", help="file format")
parser.add_argument("--device_target", type=str, choices=["Ascend", "GPU", "CPU"], default="Ascend",
help="device target")
parser.add_argument('--ckpt_file', type=str, default='', help='ctpn ckpt file.')
args = parser.parse_args()

context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target)
if args.device_target == "Ascend":
context.set_context(device_id=args.device_id)

if __name__ == '__main__':
net = CTPN_Infer(config=config)

param_dict = load_checkpoint(args.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)

img = Tensor(np.zeros([config.test_batch_size, 3, config.img_height, config.img_width]), ms.float16)

export(net, img, file_name=args.file_name, file_format=args.file_format)

+ 108
- 0
model_zoo/official/cv/ctpn/postprocess.py View File

@@ -0,0 +1,108 @@
# 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.
# ============================================================================

"""Evaluation for CTPN"""
import os
import argparse
import numpy as np

from src.text_connector.detector import detect

parser = argparse.ArgumentParser(description="CTPN evaluation")
parser.add_argument("--dataset_path", type=str, default="", help="Dataset path.")
parser.add_argument("--result_path", type=str, default="", help="Image path.")
parser.add_argument("--label_path", type=str, default="", help="label path.")
args_opt = parser.parse_args()

def get_pred(img_file, result_path):
file_name = img_file.split('.')[0]
proposal_file = os.path.join(result_path, file_name + "_0.bin")
mask_file = os.path.join(result_path, file_name + "_1.bin")
proposal = np.fromfile(proposal_file, dtype=np.float16).reshape(1000, 5)
proposal_mask = np.fromfile(mask_file, dtype=np.int8).reshape(1000)

return proposal, proposal_mask

def get_img_metas(imgSize):
org_width, org_height = imgSize
h_scale = 576 / org_height
w_scale = 960 / org_width

return np.array([576, 960, h_scale, w_scale])

def get_gt_box(img_file, label_path):
label_file = os.path.join(label_path, img_file.replace("jpg", "txt"))
file = open(label_file)
lines = file.readlines()
gt_boxs = []
for line in lines:
label_info = line.split(",")
print(label_info)
gt_boxs.append([int(label_info[0]), int(label_info[1]), int(label_info[2]), int(label_info[3])])
#print(line)
#print(gt_boxs)

return gt_boxs
def ctpn_infer_test(dataset_path='', result_path='', label_path=''):
output_dir = "./output/"
output_img_dir = "./output_img/"
img_files = os.listdir(dataset_path)

for file in img_files:
print("processing image: ", file)
from PIL import Image, ImageDraw
img = Image.open(dataset_path + '/' + file)
proposal, proposal_mask = get_pred(file, result_path)

img_size = img.size
img_metas = get_img_metas(img_size)
all_box_tmp = proposal
all_mask_tmp = np.expand_dims(proposal_mask, axis=1)

using_boxes_mask = all_box_tmp * all_mask_tmp
textsegs = using_boxes_mask[:, 0:4].astype(np.float32)
scores = using_boxes_mask[:, 4].astype(np.float32)
shape = img_metas[:2].astype(np.int32)

bboxes = detect(textsegs, scores[:, np.newaxis], shape)

draw = ImageDraw.Draw(img)
image_h = img_metas[2]
image_w = img_metas[3]
gt_boxs = get_gt_box(file, label_path)
for gt_box in gt_boxs:
gt_x1 = gt_box[0]
gt_y1 = gt_box[1]
gt_x2 = gt_box[2]
gt_y2 = gt_box[3]
draw.line([(gt_x1, gt_y1), (gt_x1, gt_y2), (gt_x2, gt_y2), (gt_x2, gt_y1), (gt_x1, gt_y1)],\
fill='green', width=2)
file_name = "res_" + file.replace("jpg", "txt")
output_file = os.path.join(output_dir, file_name)
f = open(output_file, 'w')
for bbox in bboxes:
x1 = bbox[0] / image_w
y1 = bbox[1] / image_h
x2 = bbox[2] / image_w
y2 = bbox[3] / image_h
draw.line([(x1, y1), (x1, y2), (x2, y2), (x2, y1), (x1, y1)], fill='red', width=2)
str_tmp = str(int(x1)) + "," + str(int(y1)) + "," + str(int(x2)) + "," + str(int(y2))
f.write(str_tmp)
f.write("\n")
f.close()
img.save(output_img_dir + file)

if __name__ == '__main__':
ctpn_infer_test(args_opt.dataset_path, args_opt.result_path, args_opt.label_path)

+ 123
- 0
model_zoo/official/cv/ctpn/scripts/run_infer_310.sh View File

@@ -0,0 +1,123 @@
#!/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 || $# -gt 4 ]]; then
echo "Usage: sh run_infer_310.sh [MODEL_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID]
DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero"
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)

if [ $# == 4 ]; then
device_id=$4
elif [ $# == 3 ]; then
if [ -z $device_id ]; then
device_id=0
else
device_id=$device_id
fi
fi

echo $model
echo $data_path
echo $label_path
echo $device_id

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 compile_app()
{
cd ../ascend310_infer
if [ -f "Makefile" ]; then
make clean
fi
sh build.sh &> build.log

if [ $? -ne 0 ]; then
echo "compile app code failed"
exit 1
fi
cd -
}

function infer()
{
if [ -d result_Files ]; then
rm -rf ./result_Files
fi
if [ -d time_Result ]; then
rm -rf ./time_Result
fi
mkdir result_Files
mkdir time_Result
../ascend310_infer/out/main --model_path=$model --dataset_path=$data_path --device_id=$device_id &> infer.log

if [ $? -ne 0 ]; then
echo "execute inference failed"
exit 1
fi
}

function cal_acc()
{
if [ -d output ]; then
rm -rf ./output
fi
if [ -d output_img ]; then
rm -rf ./output_img
fi
mkdir output
mkdir output_img
python ../postprocess.py --dataset_path=$data_path --result_path=result_Files --label_path=$label_path &> acc.log
if [ $? -ne 0 ]; then
echo "calculate accuracy failed"
exit 1
fi
if [ -f "ubmit.zip" ]; then
rm -f submit.zip
fi
cd output
zip -r ../submit.zip *.txt
cd -
}

compile_app
infer
cal_acc

+ 10
- 0
model_zoo/official/cv/ctpn/src/ctpn.py View File

@@ -146,3 +146,13 @@ class CTPN(nn.Cell):
def get_anchors(self, featmap_size):
anchors = self.anchor_generator.grid_anchors(featmap_size)
return Tensor(anchors, mstype.float16)

class CTPN_Infer(nn.Cell):
def __init__(self, config):
super(CTPN_Infer, self).__init__()
self.network = CTPN(config, is_training=False)
self.network.set_train(False)

def construct(self, img_data):
output = self.network(img_data, None, None, None, None)
return output

+ 17
- 1
model_zoo/official/recommend/naml/README.md View File

@@ -55,6 +55,7 @@ You can download the dataset and put the directory in structure as follows:
├── scripts
│ ├──run_train.sh # shell script for training
│ ├──run_eval.sh # shell script for evaluation
│ ├──run_infer_310.sh # shell script for 310 inference
├── src
│ ├──option.py # parse args
│ ├──callback.py # callback file
@@ -62,9 +63,11 @@ You can download the dataset and put the directory in structure as follows:
│ ├──naml.py # NAML architecture
│ ├──config.py # config file
│ ├──utils.py # utils to load ckpt_file for fine tune or incremental learn
├──ascend310_infer #application for 310 inference
├── train.py # training script
├── eval.py # evaluation script
├── export.py # export mindir script
└──postprogress.py # post process for 310 inference
```

## [Training process](#contents)
@@ -95,7 +98,7 @@ bash run_eval.sh [PLATFORM] [DEVICE_ID] [DATASET] [DATASET_PATH] [CHECKPOINT_PAT
python export.py --platform [PLATFORM] --checkpoint_path [CHECKPOINT_PATH] --file_format [EXPORT_FORMAT] --batch_size [BATCH_SIZE]
```

- `EXPORT_FORMAT` should be in ["AIR", "ONNX", "MINDIR"]
- `EXPORT_FORMAT` should be in ["AIR", "MINDIR"]

# [Model Description](#contents)

@@ -130,6 +133,19 @@ python export.py --platform [PLATFORM] --checkpoint_path [CHECKPOINT_PATH] --fil
| outputs | probability |
| Accuracy | AUC: 0.66 |

### Inference on Ascend310 Performance

| Parameters | Ascend |
| ------------------- | --------------------------- |
| Model Version | NAML |
| Resource | Ascend 310 |
| Uploaded Date | 03/13/2021 (month/day/year) |
| MindSpore Version | 1.2.0 |
| Dataset | MINDlarge |
| batch_size | 64 |
| outputs | probability |
| Accuracy | AUC: 0.667 |

# [Description of Random Situation](#contents)

<!-- In dataset.py, we set the seed inside “create_dataset" function. We also use random seed in train.py. -->


+ 64
- 0
model_zoo/official/recommend/naml/ascend310_infer/CMakeLists.txt View File

@@ -0,0 +1,64 @@
# Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.

# CMake lowest version requirement
cmake_minimum_required(VERSION 3.5.1)

# project information
project(ACL_RESNET50)

find_package(gflags REQUIRED)
include_directories(${gflags_INCLUDE_DIR})

# Compile options
add_compile_options(-std=c++11 -g -O0)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../out")
set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O0 -g -Wall")

set(INC_PATH $ENV{DDK_PATH})

if(NOT DEFINED ENV{DDK_PATH})
set(INC_PATH "/usr/local/Ascend")
message(STATUS "set default INC_PATH: ${INC_PATH}")
else()
message(STATUS "env INC_PATH: ${INC_PATH}")
endif()

set(LIB_PATH $ENV{NPU_HOST_LIB})

if(NOT DEFINED ENV{NPU_HOST_LIB})
set(LIB_PATH "/usr/local/Ascend/acllib/lib64/stub/")
message(STATUS "set default LIB_PATH: ${LIB_PATH}")
else()
message(STATUS "env LIB_PATH: ${LIB_PATH}")
endif()

# Header path
include_directories(
${INC_PATH}/acllib/include/
../include/
)

if(target STREQUAL "Simulator_Function")
add_compile_options(-DFUNC_SIM)
endif()

# add host lib path
link_directories(
${LIB_PATH}
)

add_executable(main
./src/utils.cpp
./src/model_process.cpp
./src/sample_process.cpp
./src/main.cpp)

if(target STREQUAL "Simulator_Function")
target_link_libraries(main funcsim)
else()
target_link_libraries(main ascendcl stdc++ gflags)
endif()

install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

+ 23
- 0
model_zoo/official/recommend/naml/ascend310_infer/build.sh View File

@@ -0,0 +1,23 @@
#!/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 [ ! -d out ]; then
mkdir out
fi
cd out
export CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0
cmake .. -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE
make

+ 94
- 0
model_zoo/official/recommend/naml/ascend310_infer/inc/model_process.h View File

@@ -0,0 +1,94 @@
/**
* 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 <map>
#include <vector>
#include <string>
#include "./utils.h"
#include "acl/acl.h"

class ModelProcess {
public:
ModelProcess() = default;
ModelProcess(const std::string &inputDataPath, const std::string &idFilePath, uint32_t batchSize);

~ModelProcess();

Result LoadModelFromFileWithMem(const char *modelPath);

void Unload();

Result CreateDesc();

void DestroyDesc();

void DestroyInput();

Result CreateOutput();

void DestroyOutput();

Result Execute(uint32_t index);

void DumpModelOutputResult(std::string fileName);

void OutputModelResult();
Result CreateInput();
Result CpyFileToDevice(std::string fileName, uint32_t inputNum);
void CpyOutputFromDeviceToHost(uint32_t index, uint32_t batchSize);
std::map<int, void*> GetResult();
std::vector<uint32_t> GetOutputSize();
std::vector<uint32_t> GetInputSize();
Result ExecuteWithFile(uint32_t fileNum);
Result CpyDataToDevice(void *data, uint32_t len, uint32_t inputNum);
std::string GetInputDataPath();
std::string GetCostTimeInfo();
void DestroyResource();
std::vector<std::vector<void *>> ReadInputFiles(std::vector<std::vector<std::string>> inputFiles,
size_t inputSize, std::vector<std::vector<uint32_t>> *fileSize);
Result ReadIdFiles();
Result InitResource();
uint32_t ReadFiles();

private:
uint32_t modelId_;
std::map<double, double> costTime_map_;
size_t modelMemSize_;
size_t modelWeightSize_;
void *modelMemPtr_;
void *modelWeightPtr_;
uint32_t batchSize_;
bool loadFlag_; // model load flag
aclmdlDesc *modelDesc_;
aclmdlDataset *input_;
uint32_t inputNum_;
std::vector<uint32_t> inputBuffSize_;
aclmdlDataset *output_;
uint32_t outputNum_;
std::vector<uint32_t> outputBuffSize_;

std::map<int, void*> result_;
std::vector<void*> resultMem_;
std::vector<void*> fileBuffMem_;
std::string inputDataPath_;
std::string idFilePath_;
std::vector<std::vector<void *>> fileBuff_;
std::vector<std::vector<uint32_t>> fileSize_;
std::vector<std::vector<int>> ids_;
};


+ 71
- 0
model_zoo/official/recommend/naml/ascend310_infer/inc/sample_process.h View File

@@ -0,0 +1,71 @@
/**
* 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 <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>

#include "acl/acl.h"
#include "./utils.h"
#include "./model_process.h"

class SampleProcess {
public:
SampleProcess();
SampleProcess(uint32_t deviceId, uint32_t threadNum);

~SampleProcess();

Result InitResource();

Result Process(const std::vector<std::string> &omPaths,
const std::vector<std::string> &inputDataPaths,
const std::vector<std::string> &inputIdPaths,
const std::string &browsedNewsPath,
uint32_t batchSize);
Result CreateModelProcessInstance(std::vector<std::string> omPaths, std::vector<std::string> inputDataPaths,
std::vector<std::string> inputIdPaths, uint32_t batchSize);
Result GetPred(uint32_t fileNum);
int WriteResult(const std::string& imageFile, std::vector<float> result, uint32_t size);
std::vector<std::string> GetModelExecCostTimeInfo();
std::vector<std::vector<std::vector<int>>> ReadHistory(std::vector<std::string> historyFile, uint32_t batchSize);
Result ReadBrowsedFile(const std::string &browsedNewsPath, std::vector<std::string> userIdFiles,
std::vector<std::vector<int>> *usersIds, std::vector<std::vector<int>> *candidateNewsIds);
uint32_t ReadBrowsedData(const std::string &browsedNewsPath);
void GetResult(uint32_t startPos, uint32_t endPos,
std::map<int, void*> newsEncodeResult,
std::map<int, void*> userEncodeResult);

private:
void DestroyResource();

int32_t deviceId_;
aclrtContext context_;
aclrtStream stream_;
std::map<int, std::shared_ptr<ModelProcess>> modelProcessContainer_;
std::map<double, double> secondModelCostTime_map_;
std::map<double, double> thirdModelCostTime_map_;
std::map<double, double> totalCostTime_map_;
std::vector<std::vector<int>> usersIds_;
std::vector<std::vector<int>> candidateNewsIds_;
std::vector<std::string> userIdFiles_;
uint32_t threadNum_;
std::mutex mtx_;
};


+ 51
- 0
model_zoo/official/recommend/naml/ascend310_infer/inc/utils.h View File

@@ -0,0 +1,51 @@
/**
* 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 <dirent.h>
#include <iostream>
#include <vector>
#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;

class Utils {
public:
static void *GetDeviceBufferOfFile(std::string fileName, uint32_t *fileSize);

static void *ReadBinFile(std::string fileName, uint32_t *fileSize);

static std::vector <std::vector<std::string>> GetAllInputData(std::string dir_name);

static DIR *OpenDir(std::string dir_name);

static std::string RealPath(std::string path);

static std::vector <std::string> GetAllBins(std::string dir_name);

static Result ReadFileToVector(std::string newsIdFileName, uint32_t batchSize, std::vector<int> *newsId);
static Result ReadFileToVector(std::string newsIdFileName, std::vector<int> *newsId);
static Result ReadFileToVector(std::string newsIdFileName, uint32_t batchSize, uint32_t count,
std::vector<std::vector<int>> *newsId);
};
#pragma once

+ 84
- 0
model_zoo/official/recommend/naml/ascend310_infer/src/main.cpp View File

@@ -0,0 +1,84 @@
/**
* 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 <gflags/gflags.h>
#include <string>
#include <iostream>
#include <memory>
#include <fstream>
#include "../inc/utils.h"
#include "../inc/sample_process.h"

bool g_isDevice = false;

DEFINE_string(news_om_path, "../model/relu_double_geir.om", "om model path.");
DEFINE_string(user_om_path, "../model/relu_double_geir.om", "om model path.");
DEFINE_string(news_dataset_path, "../data", "input data dir");
DEFINE_string(user_dataset_path, "../data", "input data dir");
DEFINE_string(newsid_data_path, "../data", "input data dir");
DEFINE_string(userid_data_path, "../data", "input data dir");
DEFINE_string(browsed_news_path, "../data", "input data dir");
DEFINE_int32(batch_size, 16, "batch size");
DEFINE_int32(device_id, 0, "device id");
DEFINE_int32(thread_num, 8, "thread num");

int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "news OM File Path :" << FLAGS_news_om_path << std::endl;
std::cout << "user OM File Path :" << FLAGS_user_om_path << std::endl;
std::cout << "news Dataset Path :" << FLAGS_news_dataset_path << std::endl;
std::cout << "user Dataset Path :" << FLAGS_user_dataset_path << std::endl;
std::cout << "browsed_news_path Path :" << FLAGS_browsed_news_path << std::endl;
std::cout << "batch size :" << FLAGS_batch_size << std::endl;
std::cout << "device id :" << FLAGS_device_id << std::endl;
std::cout << "thread num :" << FLAGS_thread_num << std::endl;

std::vector<std::string> omPaths;
std::vector<std::string> datasetPaths;
std::vector<std::string> idsPaths;
omPaths.emplace_back(FLAGS_news_om_path);
omPaths.emplace_back(FLAGS_user_om_path);
datasetPaths.emplace_back(FLAGS_news_dataset_path);
datasetPaths.emplace_back(FLAGS_user_dataset_path);
idsPaths.emplace_back(FLAGS_newsid_data_path);
idsPaths.emplace_back(FLAGS_userid_data_path);

SampleProcess processSample(FLAGS_device_id, FLAGS_thread_num);
Result ret = processSample.InitResource();
if (ret != SUCCESS) {
ERROR_LOG("sample init resource failed");
return FAILED;
}

ret = processSample.Process(omPaths, datasetPaths, idsPaths, FLAGS_browsed_news_path, FLAGS_batch_size);
if (ret != SUCCESS) {
ERROR_LOG("sample process failed");
return FAILED;
}

std::vector<std::string> costTime = processSample.GetModelExecCostTimeInfo();
std::string file_name = "./time_Result" + std::string("/test_perform_static.txt");
std::ofstream file_stream(file_name.c_str(), std::ios::trunc);
for (auto cost : costTime) {
std::cout << cost << std::endl;
file_stream << cost << std::endl;
}

file_stream.close();

INFO_LOG("execute sample success");
return SUCCESS;
}

+ 598
- 0
model_zoo/official/recommend/naml/ascend310_infer/src/model_process.cpp View File

@@ -0,0 +1,598 @@
/**
* 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 <sys/time.h>
#include <iostream>
#include <fstream>
#include <map>
#include <sstream>
#include <algorithm>
#include "../inc/utils.h"
#include "../inc/model_process.h"

extern bool g_isDevice;

ModelProcess::ModelProcess(const std::string &inputDataPath, const std::string &idFilePath, uint32_t batchSize):
modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr),
modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), output_(nullptr),
inputDataPath_(inputDataPath), input_(nullptr), batchSize_(batchSize),
idFilePath_(idFilePath), inputNum_(0), outputNum_(0) {
}

ModelProcess::~ModelProcess() {
Unload();
DestroyResource();
}

Result ModelProcess::InitResource() {
Result ret = CreateDesc();
if (ret != SUCCESS) {
ERROR_LOG("create model description failed");
return FAILED;
}

ret = CreateOutput();
if (ret != SUCCESS) {
ERROR_LOG("create model output failed");
return FAILED;
}

ret = CreateInput();
if (ret != SUCCESS) {
ERROR_LOG("create model input failed");
return FAILED;
}

ret = ReadIdFiles();
if (ret != SUCCESS) {
ERROR_LOG("read id files failed");
return FAILED;
}
}
void ModelProcess::DestroyResource() {
DestroyDesc();
DestroyInput();
DestroyOutput();
for (auto addr : resultMem_) {
if (addr != nullptr) {
aclrtFreeHost(addr);
}
}

for (auto addr : fileBuffMem_) {
if (addr != nullptr) {
aclrtFreeHost(addr);
}
}
return;
}

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() {
if (modelDesc_ == nullptr) {
ERROR_LOG("no model description, create output failed");
return FAILED;
}

input_ = aclmdlCreateDataset();
if (input_ == nullptr) {
ERROR_LOG("can't create dataset, create input failed");
return FAILED;
}

size_t inputSize = aclmdlGetNumInputs(modelDesc_);
inputNum_ = inputSize;
for (size_t i = 0; i < inputSize; ++i) {
size_t buffer_size = aclmdlGetInputSizeByIndex(modelDesc_, i);
inputBuffSize_.emplace_back(buffer_size);

void *inputBuffer = nullptr;
aclError ret = aclrtMalloc(&inputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("can't malloc buffer, size is %zu, create input failed", buffer_size);
return FAILED;
}

aclDataBuffer* inputData = aclCreateDataBuffer(inputBuffer, buffer_size);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("can't create data buffer, create input failed");
aclrtFree(inputBuffer);
return FAILED;
}

ret = aclmdlAddDatasetBuffer(input_, inputData);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("can't add data buffer, create output failed");
aclrtFree(inputBuffer);
aclDestroyDataBuffer(inputData);
return FAILED;
}
}

INFO_LOG("create model input success");
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_);
outputNum_ = outputSize;
for (size_t i = 0; i < outputSize; ++i) {
size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i);
outputBuffSize_.emplace_back(buffer_size);

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(std::string fileName) {
std::size_t dex = fileName.find_last_of(".");
std::string outputFile = fileName.erase(dex);
std::string Path = "../result_Files";

// stringstream ss;
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);
static int executeNum = 0;
for (size_t i = 0; i < outputNum; ++i) {
std::stringstream ss;
ss << Path <<"/output" << "_" << i << "_in_" << outputFile << ".bin";
std::string outputFileName = ss.str();
FILE *file = fopen(outputFileName.c_str(), "wb");
if (file) {
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
void* data = aclGetDataBufferAddr(dataBuffer);
uint32_t len = aclGetDataBufferSizeV2(dataBuffer);

void* outHostData = NULL;
aclError ret = ACL_ERROR_NONE;
if (!g_isDevice) {
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), file);

ret = aclrtFreeHost(outHostData);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret);
return;
}
} else {
fwrite(data, len, sizeof(char), file);
}
fclose(file);
file = 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_isDevice) {
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_isDevice) {
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::CpyFileToDevice(std::string fileName, uint32_t inputNum) {
uint32_t inputHostBuffSize = 0;
void* inputHostBuff = Utils::ReadBinFile(fileName, &inputHostBuffSize);
if (inputHostBuff == nullptr) {
return FAILED;
}
aclDataBuffer *inBufferDev = aclmdlGetDatasetBuffer(input_, inputNum);
void*p_batchDst = aclGetDataBufferAddr(inBufferDev);
aclrtMemset(p_batchDst, inputHostBuffSize, 0, inputHostBuffSize);
aclError ret = aclrtMemcpy(p_batchDst, inputHostBuffSize, 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",
inputHostBuffSize, inputHostBuffSize);
aclrtFreeHost(inputHostBuff);
return FAILED;
}
aclrtFreeHost(inputHostBuff);
return SUCCESS;
}

Result ModelProcess::CpyDataToDevice(void *data, uint32_t len, uint32_t inputNum) {
if (len != inputBuffSize_[inputNum]) {
return FAILED;
}
aclDataBuffer *inBufferDev = aclmdlGetDatasetBuffer(input_, inputNum);
void*p_batchDst = aclGetDataBufferAddr(inBufferDev);
aclrtMemset(p_batchDst, len, 0, len);
aclError ret = aclrtMemcpy(p_batchDst, len, data, len, 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",
len, len);
return FAILED;
}
return SUCCESS;
}

void ModelProcess::CpyOutputFromDeviceToHost(uint32_t index, uint32_t batchSize) {
size_t outputNum = aclmdlGetDatasetNumBuffers(output_);

for (size_t i = 0; i < outputNum; ++i) {
aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
void* data = aclGetDataBufferAddr(dataBuffer);
uint32_t bufferSize = aclGetDataBufferSizeV2(dataBuffer);

void* outHostData = NULL;
aclError ret = ACL_ERROR_NONE;
ret = aclrtMallocHost(&outHostData, bufferSize);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret);
return;
}
resultMem_.emplace_back(outHostData);
ret = aclrtMemcpy(outHostData, bufferSize, data, bufferSize, ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret);
(void)aclrtFreeHost(outHostData);
return;
}

uint32_t len = (uint32_t)bufferSize/batchSize;
for (size_t j = 0; j < batchSize; j++) {
result_.emplace(ids_[index][j], reinterpret_cast<uint8_t *>(outHostData) + (j * len));
}
}
return;
}

std::vector<std::vector<void *>> ModelProcess::ReadInputFiles(std::vector<std::vector<std::string>> inputFiles,
size_t inputSize,
std::vector<std::vector<uint32_t>> *fileSize) {
size_t fileNum = inputFiles[0].size();
std::vector<std::vector<void *>> buff(fileNum);
if (inputFiles.size() != inputSize) {
std::cout << "the num of input file is incorrect" << std::endl;
return buff;
}

void* inputHostBuff;
uint32_t inputHostBuffSize = 0;
for (int i = 0; i < inputSize; ++i) {
for (int j = 0; j < fileNum; ++j) {
inputHostBuff = Utils::ReadBinFile(inputFiles[i][j], &inputHostBuffSize);
buff[i].emplace_back(inputHostBuff);
fileBuffMem_.emplace_back(inputHostBuff);
(*fileSize)[i].emplace_back(inputHostBuffSize);
}
}

return buff;
}

Result ModelProcess::ReadIdFiles() {
std::vector<std::string> idFiles = Utils::GetAllBins(idFilePath_);

for (int i = 0; i < idFiles.size(); ++i) {
std::vector<int> ids;
Utils::ReadFileToVector(idFiles[i], batchSize_, &ids);
ids_.emplace_back(ids);
}
return SUCCESS;
}

uint32_t ModelProcess::ReadFiles() {
size_t inputSize = aclmdlGetNumInputs(modelDesc_);
std::vector<std::vector<uint32_t>> fileSize(inputSize);
std::vector<std::vector<std::string>> inputFiles = Utils::GetAllInputData(inputDataPath_);

fileBuff_ = ReadInputFiles(inputFiles, inputSize, &fileSize);
uint32_t fileNum = inputFiles[0].size();
fileSize_ = fileSize;
return fileNum;
}

Result ModelProcess::ExecuteWithFile(uint32_t fileNum) {
for (size_t index = 0; index < fileNum; ++index) {
struct timeval start;
struct timeval end;
double startTime_ms;
double endTime_ms;
gettimeofday(&start, NULL);
void* picDevBuffer = nullptr;
int pathIndex = 0;
for (auto i = 0; i < inputNum_; ++i) {
CpyDataToDevice(fileBuff_[i][index], fileSize_[i][index], i);
}

aclError ret = aclmdlExecute(modelId_, input_, output_);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("execute model failed, modelId is %u", modelId_);
return FAILED;
}

CpyOutputFromDeviceToHost(index, batchSize_);
gettimeofday(&end, NULL);
startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000;
endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000;
costTime_map_.insert(std::pair<double, double>(startTime_ms, endTime_ms));
}
return SUCCESS;
}

Result ModelProcess::Execute(uint32_t index) {
struct timeval start;
struct timeval end;
double startTime_ms;
double endTime_ms;

gettimeofday(&start, NULL);
aclError ret = aclmdlExecute(modelId_, input_, output_);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("execute model failed, modelId is %u", modelId_);
return FAILED;
}

CpyOutputFromDeviceToHost(index, batchSize_);
gettimeofday(&end, NULL);
startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000;
endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000;
costTime_map_.insert(std::pair<double, double>(startTime_ms, endTime_ms));
return SUCCESS;
}

std::map<int, void*> ModelProcess::GetResult() {
return result_;
}

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_);
}

std::vector<uint32_t> ModelProcess::GetInputSize() {
return inputBuffSize_;
}

std::vector<uint32_t> ModelProcess::GetOutputSize() {
return outputBuffSize_;
}

std::string ModelProcess::GetInputDataPath() {
return inputDataPath_;
}

std::string ModelProcess::GetCostTimeInfo() {
double average = 0.0;
int infer_cnt = 0;
char tmpCh[256] = {0};
for (auto iter = costTime_map_.begin(); iter != costTime_map_.end(); iter++) {
double diff = 0.0;
diff = iter->second - iter->first;
average += diff;
infer_cnt++;
}
average = average/infer_cnt;
snprintf(tmpCh, sizeof(tmpCh), "first model latency %4.3f ms; count %d\n", average, infer_cnt);

return std::string(tmpCh);
}

+ 354
- 0
model_zoo/official/recommend/naml/ascend310_infer/src/sample_process.cpp View File

@@ -0,0 +1,354 @@
/**
* 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 <dirent.h>
#include <sys/time.h>
#include <time.h>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <unordered_map>
#include <iterator>
#include <thread>

#include "acl/acl.h"
#include "../inc/utils.h"
#include "../inc/model_process.h"
#include "../inc/sample_process.h"

extern bool g_isDevice;

SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr), threadNum_(0) {}

SampleProcess::SampleProcess(uint32_t deviceId, uint32_t threadNum):
deviceId_(deviceId), threadNum_(threadNum), context_(nullptr), stream_(nullptr) {}

SampleProcess::~SampleProcess() {
DestroyResource();
}

Result SampleProcess::InitResource() {
aclError ret = aclInit(nullptr);
if (ret != ACL_ERROR_NONE) {
ERROR_LOG("acl init failed");
return FAILED;
}
INFO_LOG("acl init success");

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_isDevice = (runMode == ACL_DEVICE);
INFO_LOG("get run mode success");

return SUCCESS;
}

Result SampleProcess::CreateModelProcessInstance(std::vector<std::string> omPaths,
std::vector<std::string> inputDataPaths,
std::vector<std::string> inputIdPaths,
uint32_t batchSize) {
for (int i = 0; i < omPaths.size(); ++i) {
std::cout << "om_path : " << omPaths[i] << std::endl;
auto processModel = std::make_shared<ModelProcess>(inputDataPaths[i], inputIdPaths[i], batchSize);
Result ret = processModel->LoadModelFromFileWithMem(omPaths[i].c_str());
if (ret != SUCCESS) {
ERROR_LOG("load model from file failed");
return FAILED;
}

ret = processModel->InitResource();
if (ret != SUCCESS) {
ERROR_LOG("create model description failed");
return FAILED;
}

modelProcessContainer_.emplace(i, processModel);
}

return SUCCESS;
}

std::vector<std::vector<std::vector<int>>> SampleProcess::ReadHistory(std::vector<std::string> historyFile,
uint32_t batchSize) {
std::vector<std::vector<std::vector<int>>> allHistory;
for (auto &file : historyFile) {
std::vector<std::vector<int>> history(batchSize, std::vector<int>(50));
Utils::ReadFileToVector(file, batchSize, 50, &history);
allHistory.emplace_back(history);
}

return allHistory;
}

Result SampleProcess::Process(const std::vector<std::string> &omPaths,
const std::vector<std::string> &inputDataPaths,
const std::vector<std::string> &inputIdPaths,
const std::string &browsedNewsPath,
uint32_t batchSize) {
struct timeval totalStart;
struct timeval totalEnd;

CreateModelProcessInstance(omPaths, inputDataPaths, inputIdPaths, batchSize);

uint32_t fileNum = modelProcessContainer_[0]->ReadFiles();
std::string historyDir = modelProcessContainer_[1]->GetInputDataPath() + "/00_history_data";
std::vector<std::string> historyFile = Utils::GetAllBins(historyDir);

size_t historySize = historyFile.size();
std::vector<std::vector<std::vector<int>>> allHistory = ReadHistory(historyFile, batchSize);

uint32_t browsedFileNum = ReadBrowsedData(browsedNewsPath);

gettimeofday(&totalStart, NULL);
modelProcessContainer_[0]->ExecuteWithFile(fileNum);

std::map<int, void*> result = modelProcessContainer_[0]->GetResult();

std::vector<uint32_t> model1OutputBuffSize = modelProcessContainer_[0]->GetOutputSize();
std::vector<uint32_t> inputBuffSize = modelProcessContainer_[1]->GetInputSize();

uint32_t singleDatsSize = model1OutputBuffSize[0] / batchSize;
void* browedNews = NULL;
aclrtMallocHost(&browedNews, inputBuffSize[0]);

struct timeval start;
struct timeval end;
double startTime_ms;
double endTime_ms;
for (int i = 0; i < historySize; ++i) {
gettimeofday(&start, NULL);
for (int j = 0; j < 16; ++j) {
for (int k = 0; k < 50; ++k) {
auto it = result.find(allHistory[i][j][k]);
if (it != result.end()) {
aclrtMemcpy(reinterpret_cast<uint8_t *>(browedNews) + (j*50 + k) * singleDatsSize, singleDatsSize,
result[allHistory[i][j][k]], singleDatsSize, ACL_MEMCPY_HOST_TO_HOST);
}
}
}
modelProcessContainer_[1]->CpyDataToDevice(browedNews, inputBuffSize[0], 0);
modelProcessContainer_[1]->Execute(i);
gettimeofday(&end, NULL);
startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000;
endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000;
secondModelCostTime_map_.insert(std::pair<double, double>(startTime_ms, endTime_ms));
}

GetPred(browsedFileNum);
gettimeofday(&totalEnd, NULL);
startTime_ms = (1.0 * totalStart.tv_sec * 1000000 + totalStart.tv_usec) / 1000;
endTime_ms = (1.0 * totalEnd.tv_sec * 1000000 + totalEnd.tv_usec) / 1000;
totalCostTime_map_.insert(std::pair<double, double>(startTime_ms, endTime_ms));
aclrtFreeHost(browedNews);
return SUCCESS;
}

Result SampleProcess::ReadBrowsedFile(const std::string &browsedNewsPath,
std::vector<std::string> userIdFiles,
std::vector<std::vector<int>> *usersIds,
std::vector<std::vector<int>> *candidateNewsIds) {
std::vector<int> candidateNewsId;
std::vector<int> usersId;
for (auto file : userIdFiles) {
candidateNewsId.clear();
usersId.clear();
std::size_t pos = file.rfind("/");
std::string name = file.substr(pos);

std::string newsIdFileName = browsedNewsPath + "/01_candidate_nid_data" + name;

Utils::ReadFileToVector(file, &usersId);
Utils::ReadFileToVector(newsIdFileName, &candidateNewsId);

usersIds->emplace_back(usersId);
candidateNewsIds->emplace_back(candidateNewsId);
}
return SUCCESS;
}

uint32_t SampleProcess::ReadBrowsedData(const std::string &browsedNewsPath) {
userIdFiles_ = Utils::GetAllBins(browsedNewsPath + "/00_user_id_data");
ReadBrowsedFile(browsedNewsPath, userIdFiles_, &usersIds_, &candidateNewsIds_);
uint32_t fileNum = userIdFiles_.size();

return fileNum;
}

Result SampleProcess::GetPred(uint32_t fileNum) {
std::map<int, void*> newsEncodeResult = modelProcessContainer_[0]->GetResult();
std::map<int, void*> userEncodeResult = modelProcessContainer_[1]->GetResult();

uint32_t perThreadNum = fileNum / threadNum_;
std::vector<std::thread> threads;

for (int i = 0; i < threadNum_; ++i) {
if (i != threadNum_ - 1) {
threads.emplace_back(std::thread(&SampleProcess::GetResult, this,
i * perThreadNum, (i+1) * perThreadNum,
newsEncodeResult,
userEncodeResult));
} else {
threads.emplace_back(std::thread(&SampleProcess::GetResult, this,
i * perThreadNum,
fileNum,
newsEncodeResult,
userEncodeResult));
}
}
for (int i = 0; i < threads.size(); ++i) {
threads[i].join();
}

return SUCCESS;
}
void SampleProcess::GetResult(uint32_t startPos, uint32_t endPos,
std::map<int, void*> newsEncodeResult,
std::map<int, void*> userEncodeResult) {
for (int i = startPos; i < endPos; ++i) {
std::vector<std::vector<float>> newsCandidate;
std::vector<float> userEncodeIds(400);
for (int j = 0; j < candidateNewsIds_[i].size(); ++j) {
std::vector<float> newsResults(400);
float *newsResult = reinterpret_cast<float *>(newsEncodeResult[candidateNewsIds_[i][j]]);
std::copy(newsResult, newsResult + 400, newsResults.begin());
newsCandidate.emplace_back(newsResults);
}
float *userResult = reinterpret_cast<float *>(userEncodeResult[usersIds_[i][0]]);
std::copy(userResult, userResult + 400, userEncodeIds.begin());

std::vector<float> predResult;
for (int j = 0; j < newsCandidate.size(); ++j) {
float dotMulResult = 0;
for (int k = 0; k < 400; ++k) {
dotMulResult += newsCandidate[j][k] * userEncodeIds[k];
}
predResult.emplace_back(dotMulResult);
}
mtx_.lock();
WriteResult(userIdFiles_[i], predResult, predResult.size() * 4);
mtx_.unlock();
}

return;
}

int SampleProcess::WriteResult(const std::string& imageFile, std::vector<float> result, uint32_t size) {
std::string homePath = "./result_Files/";
std::size_t pos = imageFile.rfind("/");
std::string name = imageFile.substr(pos);
for (size_t i = 0; i < 1; ++i) {
std::string outFileName = homePath + "/" + name;
try {
FILE * outputFile = fopen(outFileName.c_str(), "wb");
fwrite(static_cast<void*>(&result[0]), size, sizeof(char), outputFile);
fclose(outputFile);
outputFile = nullptr;
} catch (std::exception &e) {
std::cout << "write result file " << outFileName << " failed, error info: " << e.what() << std::endl;
std::exit(1);
}
}
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");
}

std::vector<std::string> SampleProcess::GetModelExecCostTimeInfo() {
std::vector<std::string> result;

result.emplace_back(modelProcessContainer_[0]->GetCostTimeInfo());
double secondModelAverage = 0.0;
int infer_cnt = 0;
char tmpCh[256] = {0};
for (auto iter = secondModelCostTime_map_.begin(); iter != secondModelCostTime_map_.end(); iter++) {
double diff = 0.0;
diff = iter->second - iter->first;
secondModelAverage += diff;
infer_cnt++;
}
secondModelAverage = secondModelAverage / infer_cnt;
snprintf(tmpCh, sizeof(tmpCh), "second model inference cost average time: %4.3f ms of infer_count %d\n",
secondModelAverage, infer_cnt);
result.emplace_back(tmpCh);

double totalCostTime;
totalCostTime = totalCostTime_map_.begin()->second - totalCostTime_map_.begin()->first;
snprintf(tmpCh, sizeof(tmpCh), "total inference cost time: %4.3f ms; count %d\n", totalCostTime, infer_cnt);
result.emplace_back(tmpCh);

return result;
}

+ 246
- 0
model_zoo/official/recommend/naml/ascend310_infer/src/utils.cpp View File

@@ -0,0 +1,246 @@
/**
* 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 <sys/stat.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <algorithm>
#include "acl/acl.h"
#include "../inc/utils.h"

extern bool g_isDevice;

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;
if (!g_isDevice) {
aclrtMallocHost(&binFileBufferData, binFileBufferLen);
if (binFileBufferData == nullptr) {
ERROR_LOG("malloc binFileBufferData failed");
binFile.close();
return nullptr;
}
} else {
aclError 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_isDevice) {
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;
}
}

std::vector<std::vector<std::string>> Utils::GetAllInputData(std::string dir_name) {
DIR *dir = OpenDir(dir_name);
if (dir == nullptr) {
return {};
}
struct dirent *filename;

std::vector<std::string> sub_dirs;
while ((filename = readdir(dir)) != nullptr) {
std::string d_name = std::string(filename->d_name);
if (d_name == "." || d_name == ".." || d_name.empty() || d_name[0] != '0') {
continue;
}

std::string dir_path = RealPath(std::string(dir_name) + "/" + filename->d_name);
struct stat s;
lstat(dir_path.c_str(), &s);
if (!S_ISDIR(s.st_mode)) {
continue;
}

sub_dirs.emplace_back(dir_path);
}
std::sort(sub_dirs.begin(), sub_dirs.end());

std::vector<std::vector<std::string>> result(sub_dirs.size());

std::transform(sub_dirs.begin(), sub_dirs.end(), result.begin(), GetAllBins);

return result;
}

DIR *Utils::OpenDir(std::string dir_name) {
// check the parameter !
if (dir_name.empty()) {
std::cout << " dir_name is null ! " << std::endl;
return nullptr;
}

std::string real_path = RealPath(dir_name);

// check if dir_name is a valid dir
struct stat s;
lstat(real_path.c_str(), &s);
if (!S_ISDIR(s.st_mode)) {
std::cout << "dir_name is not a valid directory !" << std::endl;
return nullptr;
}

DIR *dir;
dir = opendir(real_path.c_str());
if (dir == nullptr) {
std::cout << "Can not open dir " << dir_name << std::endl;
return nullptr;
}
std::cout << "Successfully opened the dir " << dir_name << std::endl;
return dir;
}

std::string Utils::RealPath(std::string path) {
char real_path_mem[PATH_MAX] = {0};
char *real_path_ret = nullptr;
real_path_ret = realpath(path.data(), real_path_mem);

if (real_path_ret == nullptr) {
std::cout << "File: " << path << " is not exist.";
return "";
}

std::string real_path(real_path_mem);
std::cout << path << " realpath is: " << real_path << std::endl;
return real_path;
}

std::vector<std::string> Utils::GetAllBins(std::string dir_name) {
struct dirent *filename;
DIR *dir = OpenDir(dir_name);
if (dir == nullptr) {
return {};
}

std::vector<std::string> res;
while ((filename = readdir(dir)) != nullptr) {
std::string d_name = std::string(filename->d_name);
if (d_name == "." || d_name == ".." || d_name.size() <= 3 || d_name.substr(d_name.size() - 4) != ".bin" ||
filename->d_type != DT_REG) {
continue;
}
res.emplace_back(std::string(dir_name) + "/" + filename->d_name);
}

std::sort(res.begin(), res.end());

return res;
}

Result Utils::ReadFileToVector(std::string newsIdFileName, std::vector<int> *newsId) {
int id;

std::ifstream in(newsIdFileName, std::ios::in | std::ios::binary);
while (in.read(reinterpret_cast<char *>(&id), sizeof(id))) {
newsId->emplace_back(id);
}
in.close();

return SUCCESS;
}

Result Utils::ReadFileToVector(std::string newsIdFileName, uint32_t batchSize, std::vector<int> *newsId) {
int id;

std::ifstream in(newsIdFileName, std::ios::in | std::ios::binary);
for (int i = 0; i < batchSize; ++i) {
in.read(reinterpret_cast<char *>(&id), sizeof(id));
newsId->emplace_back(id);
}
in.close();

return SUCCESS;
}

Result Utils::ReadFileToVector(std::string fileName, uint32_t batchSize,
uint32_t count, std::vector<std::vector<int>> *newsId) {
int id;

std::ifstream in(fileName, std::ios::in | std::ios::binary);
for (int i = 0; i < batchSize; ++i) {
for (int j = 0; j < count; ++j) {
in.read(reinterpret_cast<char *>(&id), sizeof(id));
(*newsId)[i][j] = id;
}
}
in.close();

return SUCCESS;
}

+ 100
- 0
model_zoo/official/recommend/naml/postprocess.py View File

@@ -0,0 +1,100 @@
# 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
#
# less 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.
# ============================================================================
"""Evaluation for NAML"""
import os
import argparse
import numpy as np
from sklearn.metrics import roc_auc_score
parser = argparse.ArgumentParser(description="")
parser.add_argument("--result_path", type=str, default="", help="Device id")
parser.add_argument("--label_path", type=str, default="", help="output file name.")
args = parser.parse_args()
def AUC(y_true, y_pred):
return roc_auc_score(y_true, y_pred)
def MRR(y_true, y_pred):
index = np.argsort(y_pred)[::-1]
y_true = np.take(y_true, index)
score = y_true / (np.arange(len(y_true)) + 1)
return np.sum(score) / np.sum(y_true)
def DCG(y_true, y_pred, n):
index = np.argsort(y_pred)[::-1]
y_true = np.take(y_true, index[:n])
score = (2 ** y_true - 1) / np.log2(np.arange(len(y_true)) + 2)
return np.sum(score)
def nDCG(y_true, y_pred, n):
return DCG(y_true, y_pred, n) / DCG(y_true, y_true, n)
class NAMLMetric:
"""
Metric method
"""
def __init__(self):
super(NAMLMetric, self).__init__()
self.AUC_list = []
self.MRR_list = []
self.nDCG5_list = []
self.nDCG10_list = []
def clear(self):
"""Clear the internal evaluation result."""
self.AUC_list = []
self.MRR_list = []
self.nDCG5_list = []
self.nDCG10_list = []
def update(self, predict, y_true):
predict = predict.flatten()
y_true = y_true.flatten()
# predict = np.interp(predict, (predict.min(), predict.max()), (0, 1))
self.AUC_list.append(AUC(y_true, predict))
self.MRR_list.append(MRR(y_true, predict))
self.nDCG5_list.append(nDCG(y_true, predict, 5))
self.nDCG10_list.append(nDCG(y_true, predict, 10))
def eval(self):
auc = np.mean(self.AUC_list)
print('AUC:', auc)
print('MRR:', np.mean(self.MRR_list))
print('nDCG@5:', np.mean(self.nDCG5_list))
print('nDCG@10:', np.mean(self.nDCG10_list))
return auc
def get_metric(result_path, label_path, metric):
"""get accuracy"""
result_files = os.listdir(result_path)
for file in result_files:
result_file = os.path.join(result_path, file)
pred = np.fromfile(result_file, dtype=np.float32)
label_file = os.path.join(label_path, file)
label = np.fromfile(label_file, dtype=np.int32)
if np.nan in pred:
continue
metric.update(pred, label)
auc = metric.eval()
return auc
if __name__ == "__main__":
naml_metric = NAMLMetric()
get_metric(args.result_path, args.label_path, naml_metric)

+ 123
- 0
model_zoo/official/recommend/naml/script/run_infer_310.sh View File

@@ -0,0 +1,123 @@
#!/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 8 || $# -gt 9 ]]; then
echo "Usage: sh run_infer_310.sh [NEWS_MODEL] [USER_MODEL] [NEWS_DATASET_PATH] [USER_DATASET_PATH] [NEWS_ID_PATH] [USER_ID_PATH] [BROWSED_NEWS_PATH] [SOC_VERSION] [DEVICE_ID]
DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero"
exit 1
fi

get_real_path(){
if [ "${1:0:1}" == "/" ]; then
echo "$1"
else
echo "$(realpath -m $PWD/$1)"
fi
}

news_model=$(get_real_path $1)
user_model=$(get_real_path $2)
news_dataset_path=$(get_real_path $3)
user_dataset_path=$(get_real_path $4)
news_id_path=$(get_real_path $5)
user_id_path=$(get_real_path $6)
browsed_news_path=$(get_real_path $7)
soc_version=$8

if [ $# == 9 ]; then
device_id=$9
elif [ $# == 8 ]; then
if [ -z $device_id ]; then
device_id=0
else
device_id=$device_id
fi
fi

echo $news_model
echo $user_model
echo $news_dataset_path
echo $news_id_path
echo $user_id_path
echo $browsed_news_path
echo $soc_version
echo $device_id

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 --framework=1 --model=$news_model --output=news_encoder --soc_version=$soc_version
atc --framework=1 --model=$user_model --output=user_encoder --soc_version=$soc_version
}

function compile_app()
{
cd ../ascend310_infer
if [ -f "Makefile" ]; then
make clean
fi
sh build.sh &> build.log

if [ $? -ne 0 ]; then
echo "compile app code failed"
exit 1
fi
cd -
}

function infer()
{
if [ -d result_Files ]; then
rm -rf ./result_Files
fi
if [ -d time_Result ]; then
rm -rf ./time_Result
fi
mkdir result_Files
mkdir time_Result
../ascend310_infer/out/main --news_om_path news_encoder.om --user_om_path user_encoder.om --news_dataset_path $news_dataset_path --user_dataset_path $user_dataset_path --newsid_data_path $news_id_path --userid_data_path $user_id_path --browsed_news_path $browsed_news_path &> infer.log
if [ $? -ne 0 ]; then
echo "execute inference failed"
exit 1
fi
}

function cal_acc()
{
python3 ../postprocess.py --result_path=./result_Files --label_path=$browsed_news_path/02_labels_data &> acc.log
if [ $? -ne 0 ]; then
echo "calculate accuracy failed"
exit 1
fi
}

air_to_om
compile_app
infer
cal_acc

Loading…
Cancel
Save