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