diff --git a/official/recommend/naml/MINDlarge_config.yaml b/official/recommend/naml/MINDlarge_config.yaml index 965bf76907a428719959b91a5d3e7185ce3f821c..8cc54af7896163f51ae531d23829138c9181e6af 100644 --- a/official/recommend/naml/MINDlarge_config.yaml +++ b/official/recommend/naml/MINDlarge_config.yaml @@ -43,14 +43,14 @@ category_embedding_dim: 112 query_vector_dim: 208 n_filters: 400 window_size: 3 -checkpoint_path: "" -batch_size: 64 +checkpoint_path: "naml/naml_large_new.ckpt" +batch_size: 16 # train option beta1: 0.9 beta2: 0.999 epsilon: 0.00000001 # 1e-8 -neg_sample: 4 +neg_sample: -1 #when training, neg_sample=4, when test, neg_sample=-1 mixed: True sink_mode: True weight_decay: True @@ -63,9 +63,14 @@ eval_neg_sample: -1 # export option export_file_dir: "./" -file_format: "AIR" +file_format: "MINDIR" export_neg_sample: -1 +# infer option +preprocess_path: "./" +result_path: "./" +label_path: "./" + --- # Help description for each configuration diff --git a/official/recommend/naml/README.md b/official/recommend/naml/README.md index 19799418d8a34207964c6cbd2c7dbe658589d479..95481ff1f51a56ab49606fa04a53f82cd51414b9 100644 --- a/official/recommend/naml/README.md +++ b/official/recommend/naml/README.md @@ -53,11 +53,11 @@ You can download the dataset and put the directory in structure as follows: 鈹溾攢鈹€ naml 鈹溾攢鈹€ README.md # descriptions about NAML 鈹溾攢鈹€ model_utils - 鈹� 鈹溾攢鈹€__init__.py // module init file - 鈹� 鈹溾攢鈹€config.py // Parse arguments - 鈹� 鈹溾攢鈹€device_adapter.py // Device adapter for ModelArts - 鈹� 鈹溾攢鈹€local_adapter.py // Local adapter - 鈹� 鈹溾攢鈹€moxing_adapter.py // Moxing adapter for ModelArts + 鈹� 鈹溾攢鈹€__init__.py # module init file + 鈹� 鈹溾攢鈹€config.py # Parse arguments + 鈹� 鈹溾攢鈹€device_adapter.py # Device adapter for ModelArts + 鈹� 鈹溾攢鈹€local_adapter.py # Local adapter + 鈹� 鈹溾攢鈹€moxing_adapter.py # Moxing adapter for ModelArts 鈹溾攢鈹€ scripts 鈹� 鈹溾攢鈹€run_distribute_train.sh # shell script for distribute training 鈹� 鈹溾攢鈹€run_train.sh # shell script for training @@ -76,7 +76,8 @@ You can download the dataset and put the directory in structure as follows: 鈹溾攢鈹€ train.py # training script 鈹溾攢鈹€ eval.py # evaluation script 鈹溾攢鈹€ export.py # export mindir script - 鈹斺攢鈹€ postprogress.py # post process for 310 inference + 鈹溾攢鈹€ preprocess.py # preprocess input data + 鈹斺攢鈹€ postprocess.py # post process for 310 inference ``` ## [Training process](#contents) @@ -200,6 +201,17 @@ python export.py --platform [PLATFORM] --checkpoint_path [CHECKPOINT_PATH] --fil - `EXPORT_FORMAT` should be in ["AIR", "MINDIR"] +## [Infer on Ascend310](#contents) + +```shell +# Ascend310 inference +bash run_infer_310.sh [NEWS_MODEL] [USER_MODEL] [DEVICE_ID] +``` + +- `NEWS_MODEL` specifies path of news "MINDIR" OR "AIR" model. +- `USER_MODEL` specifies path of user "MINDIR" OR "AIR" model. +- `DEVICE_ID` is optional, default value is 0. + # [Model Description](#contents) ## [Performance](#contents) @@ -239,12 +251,12 @@ python export.py --platform [PLATFORM] --checkpoint_path [CHECKPOINT_PATH] --fil | ------------------- | --------------------------- | | Model Version | NAML | | Resource | Ascend 310 | -| Uploaded Date | 03/13/2021 (month/day/year) | -| MindSpore Version | 1.2.0 | +| Uploaded Date | 12/10/2021 (month/day/year) | +| MindSpore Version | 1.6.0 | | Dataset | MINDlarge | -| batch_size | 64 | +| batch_size | 16 | | outputs | probability | -| Accuracy | AUC: 0.667 | +| Accuracy | AUC: 0.6669 | # [Description of Random Situation](#contents) diff --git a/official/recommend/naml/ascend310_infer/CMakeLists.txt b/official/recommend/naml/ascend310_infer/CMakeLists.txt index 7788a4b7139e3959446a04acc91983e01678234b..ee3c85447340e0449ff2b70ed24f60a17e07b2b6 100644 --- a/official/recommend/naml/ascend310_infer/CMakeLists.txt +++ b/official/recommend/naml/ascend310_infer/CMakeLists.txt @@ -1,72 +1,14 @@ -# 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/ -) - -# add host lib path -link_directories( - ${LIB_PATH} -) - -# Set output directory +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}/) - -# Set include directory and library directory -set(ACL_LIB_DIR $ENV{ASCEND_HOME}/fwkacllib) -set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/fwkacllib) -# Header path -include_directories(${ACL_LIB_DIR}/include/) -include_directories(${ATLAS_ACL_LIB_DIR}/include/) -include_directories(${PROJECT_SRC_ROOT}/../inc) - -# add host lib path -link_directories(${ACL_LIB_DIR}) -find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64) -find_library(stdc libstdc++.so.6 /usr/) - -add_executable(main - ./src/utils.cpp - ./src/model_process.cpp - ./src/sample_process.cpp - ./src/main.cpp) - -target_link_libraries(main ${acl} ${stdc} gflags) - -install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +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) diff --git a/official/recommend/naml/ascend310_infer/build.sh b/official/recommend/naml/ascend310_infer/build.sh index 595d13821b2342a7372c15a4bf34f99a917e2e42..285514e19f2a1878a7bf8f0eed3c99fbc73868c4 100644 --- a/official/recommend/naml/ascend310_infer/build.sh +++ b/official/recommend/naml/ascend310_infer/build.sh @@ -13,11 +13,17 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ - -if [ ! -d out ]; then - mkdir out +if [ -d out ]; then + rm -rf out fi + +mkdir out cd out || exit -export CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0 -cmake .. -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE + +if [ -f "Makefile" ]; then + make clean +fi + +cmake .. \ + -DMINDSPORE_PATH="`pip3.7 show mindspore-ascend | grep Location | awk '{print $2"/mindspore"}' | xargs realpath`" make diff --git a/official/recommend/naml/ascend310_infer/inc/model_process.h b/official/recommend/naml/ascend310_infer/inc/model_process.h deleted file mode 100644 index d8fcf004765fbf34ff8811f6e6e2fd08da3652eb..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/inc/model_process.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * 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_MODEL_ZOO_NAML_MODEL_PROCESS_H_ -#define MINDSPORE_MODEL_ZOO_NAML_MODEL_PROCESS_H_ -#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 OutputModelResult(); - Result CreateInput(); - Result CpyFileToDevice(std::string fileName, uint32_t inputNum); - void CpyOutputFromDeviceToHost(uint32_t index); - 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::string inputDataPath_; - std::string idFilePath_; - std::vector<std::vector<void *>> fileBuff_; - std::vector<std::vector<uint32_t>> fileSize_; - std::vector<std::vector<int>> ids_; -}; - -#endif diff --git a/official/recommend/naml/ascend310_infer/inc/sample_process.h b/official/recommend/naml/ascend310_infer/inc/sample_process.h deleted file mode 100644 index 015c3c5654303e27aa1d5ff81e9b3ab8a8ef4073..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/inc/sample_process.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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_MODEL_ZOO_NAML_SAMPLE_PROCESS_H_ -#define MINDSPORE_MODEL_ZOO_NAML_SAMPLE_PROCESS_H_ - -#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(const std::vector<std::string> &omPaths, - const std::vector<std::string> &inputDataPaths, - const std::vector<std::string> &inputIdPaths, uint32_t batchSize, - std::map<int, std::shared_ptr<ModelProcess>> *modelProcessContainer); - Result GetPred(std::map<int, std::shared_ptr<ModelProcess>> *modelProcessContainer, 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<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_; - std::vector<std::string> time_cost_; - uint32_t threadNum_; - std::mutex mtx_; -}; - -#endif diff --git a/official/recommend/naml/ascend310_infer/inc/utils.h b/official/recommend/naml/ascend310_infer/inc/utils.h index a0172259e13f38a39cbbbbfcf46853d0f9cfe5bd..abeb8fcbf11a042e6fefafa5868166d975e44dfb 100644 --- a/official/recommend/naml/ascend310_infer/inc/utils.h +++ b/official/recommend/naml/ascend310_infer/inc/utils.h @@ -14,43 +14,19 @@ * limitations under the License. */ -#ifndef MINDSPORE_MODEL_ZOO_NAML_UTILS_H_ -#define MINDSPORE_MODEL_ZOO_NAML_UTILS_H_ +#ifndef MINDSPORE_INFERENCE_UTILS_H_ +#define MINDSPORE_INFERENCE_UTILS_H_ -#pragma once +#include <sys/stat.h> #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 - +#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 diff --git a/official/recommend/naml/ascend310_infer/src/main.cc b/official/recommend/naml/ascend310_infer/src/main.cc new file mode 100644 index 0000000000000000000000000000000000000000..1f96d335cfa43075937e04bde0b75affa6d0bdd3 --- /dev/null +++ b/official/recommend/naml/ascend310_infer/src/main.cc @@ -0,0 +1,351 @@ +/** + * 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 <string.h> +#include <iostream> +#include <algorithm> + +#include <string> +#include <iosfwd> +#include <vector> +#include <fstream> +#include <sstream> + +#include "include/api/model.h" +#include "include/api/context.h" +#include "include/api/types.h" +#include "include/api/serialization.h" +#include "include/dataset/execute.h" +#include "include/dataset/vision.h" +#include "inc/utils.h" + +using mindspore::Context; +using mindspore::Serialization; +using mindspore::Model; +using mindspore::Status; +using mindspore::MSTensor; +using mindspore::dataset::Execute; +using mindspore::ModelType; +using mindspore::GraphCell; +using mindspore::kSuccess; + +//***** bs=16 *****// +DEFINE_string(news_mindir, "./", "om model path."); +DEFINE_string(user_mindir, "./", "om model path."); +DEFINE_int32(batch_size, 16, "batch size"); +DEFINE_int32(device_id, 0, "device id"); +DEFINE_string(base_path, "./", "dataset base path."); + +std::vector<std::string> news_input0_0_files; +auto context = std::make_shared<Context>(); + +struct timeval total_start; +struct timeval total_end; +std::map<double, double> model0_cost_time; +std::map<double, double> model1_cost_time; + +int InitModel(const std::string &model_path, Model *model) { + mindspore::Graph graph; + Serialization::Load(model_path, ModelType::kMindIR, &graph); + Status ret = model->Build(GraphCell(graph), context); + if (ret != kSuccess) { + std::cout << "ERROR: Build model failed." << std::endl; + return 1; + } + return 0; +} + +void GetAveTime(const std::map<double, double> &costTime_map, int *inferCount, double *average) { + for (auto iter = costTime_map.begin(); iter != costTime_map.end(); iter++) { + double diff = 0.0; + diff = iter->second - iter->first; + (*average) += diff; + (*inferCount)++; + } + (*average) /= (*inferCount); + return; +} + +void InitInputs(size_t input_index, const std::vector<MSTensor> &model0_inputs, std::vector<MSTensor> *inputs) { + std::string news_dataset_path = FLAGS_base_path + "/news_test_data"; + auto file0_name = news_dataset_path + "/00_category_data/naml_news_" + std::to_string(input_index) + ".bin"; + auto file1_name = news_dataset_path + "/01_subcategory_data/naml_news_" + std::to_string(input_index) + ".bin"; + auto file2_name = news_dataset_path + "/02_title_data/naml_news_" + std::to_string(input_index) + ".bin"; + auto file3_name = news_dataset_path + "/03_abstract_data/naml_news_" + std::to_string(input_index) + ".bin"; + + auto news_input0 = ReadFileToTensor(file0_name); + auto news_input1 = ReadFileToTensor(file1_name); + auto news_input2 = ReadFileToTensor(file2_name); + auto news_input3 = ReadFileToTensor(file3_name); + + inputs->emplace_back(model0_inputs[0].Name(), model0_inputs[0].DataType(), model0_inputs[0].Shape(), + news_input0.Data().get(), news_input0.DataSize()); + inputs->emplace_back(model0_inputs[1].Name(), model0_inputs[1].DataType(), model0_inputs[1].Shape(), + news_input1.Data().get(), news_input1.DataSize()); + inputs->emplace_back(model0_inputs[2].Name(), model0_inputs[2].DataType(), model0_inputs[2].Shape(), + news_input2.Data().get(), news_input2.DataSize()); + inputs->emplace_back(model0_inputs[3].Name(), model0_inputs[3].DataType(), model0_inputs[3].Shape(), + news_input3.Data().get(), news_input3.DataSize()); + return; +} + +void InitNewsDict(const std::vector<std::string> &news_input0_0_files, const std::vector<MSTensor> &model0_inputs, + std::map<uint32_t, MSTensor> *news_dict, Model *model0) { + int count = 0; + for (size_t i = 0; i < news_input0_0_files.size() - 1; ++i) { + struct timeval start; + struct timeval end; + double startTime_ms; + double endTime_ms; + std::vector <MSTensor> inputs0; + std::vector <MSTensor> outputs0; + + // init inputs by model0 input for each iter + InitInputs(i, model0_inputs, &inputs0); + + // get model0 outputs + gettimeofday(&total_start, nullptr); + gettimeofday(&start, nullptr); + Status ret0 = model0->Predict(inputs0, &outputs0); + gettimeofday(&end, nullptr); + if (ret0 != kSuccess) { + std::cout << "ERROR: Predict model0 failed." << std::endl; + return; + } + // init news_dict + auto file_name = FLAGS_base_path + "/news_id_data/naml_news_" + std::to_string(count++) + ".bin"; + auto nid = ReadFileToTensor(file_name); + auto nid_addr = reinterpret_cast<uint32_t *>(nid.MutableData()); + // output0 size is 1, shape: batch_size * 400 + auto outputs0_addr = reinterpret_cast<float *>(outputs0[0].MutableData()); + + for (int k = 0; k < FLAGS_batch_size; ++k) { + MSTensor ret("", mindspore::DataType::kNumberTypeFloat32, {400}, nullptr, sizeof(float)* 400); + uint32_t *addr = reinterpret_cast<uint32_t *>(ret.MutableData()); + memcpy(addr, outputs0_addr, 400 * sizeof(float)); + (*news_dict)[nid_addr[k]] = ret; + outputs0_addr += 400; + } + startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000; + endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000; + model0_cost_time.insert(std::pair<double, double>(startTime_ms, endTime_ms)); + } + std::cout << "=========InitNewsDict end" << std::endl; + return; +} + +void InitUserDict(const std::vector<std::string> &history_input_files, const std::map<uint32_t, MSTensor> &news_dict, + std::map<uint32_t, MSTensor> *user_dict, Model *model1) { + int count = 0; + int uid_count = 0; + for (size_t i = 0; i < history_input_files.size() - 1; ++i) { + // model1, get model1 outputs + struct timeval start; + struct timeval end; + double startTime_ms; + double endTime_ms; + std::vector<MSTensor> outputs1; + int64_t size = FLAGS_batch_size * 50 * 400 * sizeof(float); + MSTensor buffer("", mindspore::DataType::kNumberTypeFloat32, {FLAGS_batch_size, 50, 400}, nullptr, size); + uint8_t *addr = reinterpret_cast<uint8_t *>(buffer.MutableData()); + auto file_name = FLAGS_base_path + "/users_test_data/01_history_data/naml_users_" + + std::to_string(count++) + ".bin"; + auto nid = ReadFileToTensor(file_name); + auto nid_addr = reinterpret_cast<uint32_t *>(nid.MutableData()); + + for (int j = 0; j < FLAGS_batch_size; ++j) { + for (int k = 0; k < 50; ++k) { + if (news_dict.find(nid_addr[k]) == news_dict.end()) { + addr += 400 * sizeof(float); + continue; + } + auto ms_tensor = news_dict.at(nid_addr[k]); + uint32_t *new_dict_data = reinterpret_cast<uint32_t *>(ms_tensor.MutableData()); + if (addr == nullptr || new_dict_data == nullptr) { + std::cout << "addr is nullptr or new_dict_data is nullptr" + << "src is: " << &new_dict_data << " dst is: " << &addr << std::endl; + return; + } + memcpy(addr, new_dict_data, 400 * sizeof(float)); + addr += 400 * sizeof(float); + } + nid_addr += 50; + } + gettimeofday(&start, nullptr); + Status ret1 = model1->Predict({buffer}, &outputs1); + gettimeofday(&end, nullptr); + if (ret1 != kSuccess) { + std::cout << "ERROR: Predict model1 failed." << std::endl; + return; + } + // init user_dict + auto file_name1 = FLAGS_base_path + "/users_test_data/00_user_id_data/naml_users_" + + std::to_string(uid_count++) + ".bin"; + auto nid1 = ReadFileToTensor(file_name1); + auto nid_addr1 = reinterpret_cast<uint32_t *>(nid1.MutableData()); + auto outputs1_addr = reinterpret_cast<float *>(outputs1[0].MutableData()); + for (int k = 0; k < FLAGS_batch_size; ++k) { + MSTensor ret("", mindspore::DataType::kNumberTypeFloat32, {400}, nullptr, sizeof(float) * 400); + uint32_t *addr1 = reinterpret_cast<uint32_t *>(ret.MutableData()); + memcpy(addr1, outputs1_addr, 400 * sizeof(float)); + addr1 += 400; + (*user_dict)[nid_addr1[k]] = ret; + outputs1_addr += 400; + } + startTime_ms = (1.0 * start.tv_sec * 1000000 + start.tv_usec) / 1000; + endTime_ms = (1.0 * end.tv_sec * 1000000 + end.tv_usec) / 1000; + model1_cost_time.insert(std::pair<double, double>(startTime_ms, endTime_ms)); + } + std::cout << "=========InitUserDict end" << std::endl; + return; +} + +void InitPred(const std::map<uint32_t, MSTensor> &news_dict, const std::map<uint32_t, MSTensor> &user_dict) { + std::string browsed_news_path = FLAGS_base_path + "/browsed_news_test_data"; + std::string file1_path = browsed_news_path + "/01_candidate_nid_data"; + auto eval_candidate_news = GetAllFiles(file1_path); + for (size_t i = 0; i < eval_candidate_news.size() - 1; ++i) { + std::vector<MSTensor> pred; + std::string file2_path = browsed_news_path + "/00_user_id_data"; + auto uid_file = file2_path + "/naml_browsed_news_" + std::to_string(i) + ".bin"; + auto uid_nid = ReadFileToTensor(uid_file); + auto uid_nid_addr = reinterpret_cast<uint32_t *>(uid_nid.MutableData()); + if (user_dict.find(uid_nid_addr[0]) == user_dict.end()) { + int rst = WriteResult(uid_file, pred); + if (rst != 0) { + std::cout << "write result failed." << std::endl; + return; + } + continue; + } + + MSTensor dot2 = user_dict.at(uid_nid_addr[0]); + auto candidate_nid_file = file1_path + "/naml_browsed_news_" + std::to_string(i) + ".bin"; + auto candidate_nid = ReadFileToTensor(candidate_nid_file); + size_t bin_size = candidate_nid.DataSize(); + size_t browsed_news_count = bin_size / sizeof(float); + + auto candidate_nid_addr = reinterpret_cast<uint32_t *>(candidate_nid.MutableData()); + MSTensor ret("", mindspore::DataType::kNumberTypeFloat32, {static_cast<int>(browsed_news_count)}, + nullptr, bin_size); + uint8_t *addr = reinterpret_cast<uint8_t *>(ret.MutableData()); + for (size_t j = 0; j < browsed_news_count; ++j) { + float sum = 0; + if (news_dict.find(candidate_nid_addr[j]) == news_dict.end()) { + addr += sizeof(float); + continue; + } + + MSTensor dot1 = news_dict.at(candidate_nid_addr[j]); + auto dot1_addr = reinterpret_cast<float *>(dot1.MutableData()); + auto dot2_addr = reinterpret_cast<float *>(dot2.MutableData()); + for (int k = 0; k < 400; ++k) { + sum = sum + dot1_addr[k] * dot2_addr[k]; + } + memcpy(addr, &sum, sizeof(float)); + addr += sizeof(float); + } + pred.emplace_back(ret); + int rst = WriteResult(uid_file, pred); + if (rst != 0) { + std::cout << "write result failed." << std::endl; + return; + } + } + std::cout << "=========InitPred end" << std::endl; + return; +} + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + if (RealPath(FLAGS_news_mindir).empty()) { + std::cout << "Invalid mindir" << std::endl; + return 1; + } + auto ascend310 = std::make_shared<mindspore::Ascend310DeviceInfo>(); + ascend310->SetDeviceID(FLAGS_device_id); + context->MutableDeviceInfo().push_back(ascend310); + + double startTimeMs; + double endTimeMs; + std::map<double, double> total_cost_time; + // om -> model + Model model0; + Model model1; + if (InitModel(FLAGS_news_mindir, &model0) != 0 || InitModel(FLAGS_user_mindir, &model1) != 0) { + std::cout << "ERROR: Init model failed." << std::endl; + return 1; + } + + // get model inputs + std::vector<MSTensor> model0_inputs = model0.GetInputs(); + if (model0_inputs.empty()) { + std::cout << "Invalid model, inputs is empty." << std::endl; + return 1; + } + + // get input files by bin files + std::string news_dataset_path = FLAGS_base_path + "/news_test_data"; + std::string history_data_path = FLAGS_base_path + "/users_test_data/01_history_data"; + news_input0_0_files = GetAllFiles(news_dataset_path + "/00_category_data"); + auto history_input_files = GetAllFiles(history_data_path); + if (news_input0_0_files.empty() || history_input_files.empty()) { + std::cout << "ERROR: input data empty." << std::endl; + return 1; + } + + std::map<uint32_t, MSTensor> news_dict; + std::map<uint32_t, MSTensor> user_dict; + + InitNewsDict(news_input0_0_files, model0_inputs, &news_dict, &model0); + InitUserDict(history_input_files, news_dict, &user_dict, &model1); + InitPred(news_dict, user_dict); + gettimeofday(&total_end, nullptr); + + startTimeMs = (1.0 * total_start.tv_sec * 1000000 + total_start.tv_usec) / 1000; + endTimeMs = (1.0 * total_end.tv_sec * 1000000 + total_end.tv_usec) / 1000; + total_cost_time.insert(std::pair<double, double>(startTimeMs, endTimeMs)); + + double average0 = 0.0; + int inferCount0 = 0; + double average1 = 0.0; + int infer_cnt = 0; + GetAveTime(model0_cost_time, &inferCount0, &average0); + GetAveTime(model1_cost_time, &infer_cnt, &average1); + double total_time = total_cost_time.begin()->second - total_cost_time.begin()->first; + + std::stringstream timeCost0, timeCost1, totalTimeCost; + timeCost0 << "first model cost average time: "<< average0 << " ms of infer_count " << inferCount0 << std::endl; + timeCost1 << "second model cost average time: "<< average1 << " ms of infer_count " << infer_cnt << std::endl; + totalTimeCost << "total cost time: "<< total_time << " ms of infer_count " << infer_cnt << std::endl; + + std::string fileName = "./time_Result" + std::string("/test_perform_static.txt"); + std::ofstream fileStream(fileName.c_str(), std::ios::trunc); + fileStream << timeCost0.str() << std::endl; + fileStream << timeCost1.str() << std::endl; + fileStream << totalTimeCost.str() << std::endl; + std::cout << timeCost0.str() << std::endl; + std::cout << timeCost1.str() << std::endl; + std::cout << totalTimeCost.str() << std::endl; + fileStream.close(); + model0_cost_time.clear(); + model1_cost_time.clear(); + total_cost_time.clear(); + std::cout << "Execute success." << std::endl; + return 0; +} diff --git a/official/recommend/naml/ascend310_infer/src/main.cpp b/official/recommend/naml/ascend310_infer/src/main.cpp deleted file mode 100644 index ab259b32a99d099575035fe92e8bda22c32cf3f0..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/src/main.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/** - * 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; -} diff --git a/official/recommend/naml/ascend310_infer/src/model_process.cpp b/official/recommend/naml/ascend310_infer/src/model_process.cpp deleted file mode 100644 index 1b0db70dc3741798b0d528bf0421c285d9fa48b0..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/src/model_process.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/** - * 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(); - 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::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); - (void)aclrtFreeHost(outHostData); - 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) { - 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; - } - 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 = nullptr; - 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); - (*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; - - 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); - 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); - 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; - - 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; - - std::stringstream timeCost; - timeCost << "first model latency "<< average << " ms; count " << infer_cnt << std::endl; - - return timeCost.str(); -} diff --git a/official/recommend/naml/ascend310_infer/src/sample_process.cpp b/official/recommend/naml/ascend310_infer/src/sample_process.cpp deleted file mode 100644 index 9a1d02c8042ec093018380ac927f925b18e9e03b..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/src/sample_process.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/** - * 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 <sstream> - -#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(const std::vector<std::string> &omPaths, - const std::vector<std::string> &inputDataPaths, - const std::vector<std::string> &inputIdPaths, - uint32_t batchSize, - std::map<int, std::shared_ptr<ModelProcess>> *modelProcessContainer) { - 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) { - INFO_LOG("Start do sample process"); - struct timeval totalStart; - struct timeval totalEnd; - std::map<int, std::shared_ptr<ModelProcess>> modelProcessContainer; - - CreateModelProcessInstance(omPaths, inputDataPaths, inputIdPaths, batchSize, &modelProcessContainer); - - 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(&modelProcessContainer, 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)); - time_cost_.clear(); - time_cost_.emplace_back(modelProcessContainer[0]->GetCostTimeInfo()); - 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(std::map<int, std::shared_ptr<ModelProcess>> *modelProcessContainer, - 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; - return FAILED; - } - } - 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 = aclFinalize(); - if (ret != ACL_ERROR_NONE) { - ERROR_LOG("finalize acl failed"); - } - INFO_LOG("end to finalize acl"); - - ret = aclrtResetDevice(deviceId_); - if (ret != ACL_ERROR_NONE) { - ERROR_LOG("reset device failed"); - } - INFO_LOG("end to reset device is %d", deviceId_); -} - -std::vector<std::string> SampleProcess::GetModelExecCostTimeInfo() { - double secondModelAverage = 0.0; - int infer_cnt = 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; - std::stringstream timeCost; - timeCost << "second model inference cost average time: "<< secondModelAverage << - " ms of infer_count " << infer_cnt << std::endl; - time_cost_.emplace_back(timeCost.str()); - - double totalCostTime = totalCostTime_map_.begin()->second - totalCostTime_map_.begin()->first; - std::stringstream totalTimeCost; - totalTimeCost << "total inference cost time: "<< totalCostTime << " ms; count " << infer_cnt << std::endl; - time_cost_.emplace_back(totalTimeCost.str()); - - return time_cost_; -} diff --git a/official/recommend/naml/ascend310_infer/src/utils.cc b/official/recommend/naml/ascend310_infer/src/utils.cc new file mode 100644 index 0000000000000000000000000000000000000000..65f68ca9a55903a462514d9e1db4383cee1b613e --- /dev/null +++ b/official/recommend/naml/ascend310_infer/src/utils.cc @@ -0,0 +1,142 @@ +/** + * 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 <fstream> +#include <algorithm> +#include <iostream> +#include "inc/utils.h" + +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"; + const int INVALID_POINTER = -1; + const int ERROR = -2; + 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"); + if (outputFile == nullptr) { + std::cout << "open result file " << outFileName << " failed" << std::endl; + return INVALID_POINTER; + } + size_t size = fwrite(netOutput.get(), sizeof(char), outputSize, outputFile); + if (size != outputSize) { + fclose(outputFile); + outputFile = nullptr; + std::cout << "write result file " << outFileName << " failed, write size[" << size << + "] is smaller than output size[" << outputSize << "], maybe the disk is full." << std::endl; + return ERROR; + } + 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; +} + diff --git a/official/recommend/naml/ascend310_infer/src/utils.cpp b/official/recommend/naml/ascend310_infer/src/utils.cpp deleted file mode 100644 index 6898dc6770a8b4eeada839dd0d2f7680b37804bb..0000000000000000000000000000000000000000 --- a/official/recommend/naml/ascend310_infer/src/utils.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/** - * 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 = 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; -} diff --git a/official/recommend/naml/postprocess.py b/official/recommend/naml/postprocess.py index 196613d49d00e04743181894240d045eb255884b..9da38f64c073c7c6d9945112694742b63b2204b7 100644 --- a/official/recommend/naml/postprocess.py +++ b/official/recommend/naml/postprocess.py @@ -15,16 +15,11 @@ """Evaluation for NAML""" import os -import argparse +from model_utils.config import config 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) @@ -79,15 +74,23 @@ class NAMLMetric: 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) + label_list = os.listdir(label_path) + for file in label_list: + f = file.split(".bin")[0] + "_0.bin" + result_file = os.path.join(result_path, f) + if not os.path.exists(result_file): + print("exclude file:", file) + continue pred = np.fromfile(result_file, dtype=np.float32) + if pred.size == 0: + print("exclude file:", file) + continue label_file = os.path.join(label_path, file) label = np.fromfile(label_file, dtype=np.int32) if np.nan in pred: + print("exclude file:", file) continue metric.update(pred, label) @@ -96,4 +99,4 @@ def get_metric(result_path, label_path, metric): if __name__ == "__main__": naml_metric = NAMLMetric() - get_metric(args.result_path, args.label_path, naml_metric) + get_metric(config.result_path, config.label_path, naml_metric) diff --git a/official/recommend/naml/preprocess.py b/official/recommend/naml/preprocess.py new file mode 100644 index 0000000000000000000000000000000000000000..8a3571b8f97c76daee3702c033f4ee26ec43486b --- /dev/null +++ b/official/recommend/naml/preprocess.py @@ -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. +# ============================================================================ +"""Preprocess NAML.""" +import os + +from model_utils.config import config +from src.dataset import MINDPreprocess +from src.dataset import create_eval_dataset, EvalNews, EvalUsers, EvalCandidateNews + +def export_bin(): + '''pre process function.''' + config.phase = "eval" + config.neg_sample = config.eval_neg_sample + config.embedding_file = os.path.join(config.dataset_path, config.embedding_file) + config.word_dict_path = os.path.join(config.dataset_path, config.word_dict_path) + config.category_dict_path = os.path.join(config.dataset_path, config.category_dict_path) + config.subcategory_dict_path = os.path.join(config.dataset_path, config.subcategory_dict_path) + config.uid2index_path = os.path.join(config.dataset_path, config.uid2index_path) + config.train_dataset_path = os.path.join(config.dataset_path, config.train_dataset_path) + config.eval_dataset_path = os.path.join(config.dataset_path, config.eval_dataset_path) + args = config + mindpreprocess = MINDPreprocess(vars(args), dataset_path=args.eval_dataset_path) + base_path = args.preprocess_path + + data_dir = base_path + '/news_test_data/' + news_id_folder = base_path + "/news_id_data/" + if not os.path.exists(news_id_folder): + os.makedirs(news_id_folder) + print("======== news_id_folder is ", news_id_folder, flush=True) + + category_folder = os.path.join(data_dir, "00_category_data") + if not os.path.exists(category_folder): + os.makedirs(category_folder) + print("======== category_folder is ", category_folder, flush=True) + + subcategory_folder = os.path.join(data_dir, "01_subcategory_data") + if not os.path.exists(subcategory_folder): + os.makedirs(subcategory_folder) + + title_folder = os.path.join(data_dir, "02_title_data") + if not os.path.exists(title_folder): + os.makedirs(title_folder) + + abstract_folder = os.path.join(data_dir, "03_abstract_data") + if not os.path.exists(abstract_folder): + os.makedirs(abstract_folder) + dataset = create_eval_dataset(mindpreprocess, EvalNews, batch_size=args.batch_size) + iterator = dataset.create_dict_iterator(output_numpy=True) + idx = 0 + for idx, data in enumerate(iterator): + news_id = data["news_id"] + category = data["category"] + subcategory = data["subcategory"] + title = data["title"] + abstract = data["abstract"] + file_name = "naml_news_" + str(idx) + ".bin" + news_id_file_path = os.path.join(news_id_folder, file_name) + news_id.tofile(news_id_file_path) + category_file_path = os.path.join(category_folder, file_name) + category.tofile(category_file_path) + subcategory_file_path = os.path.join(subcategory_folder, file_name) + subcategory.tofile(subcategory_file_path) + title_file_path = os.path.join(title_folder, file_name) + title.tofile(title_file_path) + abstract_file_path = os.path.join(abstract_folder, file_name) + abstract.tofile(abstract_file_path) + + data_dir = base_path + '/users_test_data/' + user_id_folder = os.path.join(data_dir, "00_user_id_data") + print("======== user_id_folder is ", user_id_folder) + if not os.path.exists(user_id_folder): + os.makedirs(user_id_folder) + + history_folder = os.path.join(data_dir, "01_history_data") + if not os.path.exists(history_folder): + os.makedirs(history_folder) + + dataset = create_eval_dataset(mindpreprocess, EvalUsers, batch_size=args.batch_size) + iterator = dataset.create_dict_iterator(output_numpy=True) + + for idx, data in enumerate(iterator): + user_id = data["uid"] + history = data["history"] + file_name = "naml_users_" + str(idx) + ".bin" + user_id_file_path = os.path.join(user_id_folder, file_name) + user_id.tofile(user_id_file_path) + history_file_path = os.path.join(history_folder, file_name) + history.tofile(history_file_path) + data_dir = base_path + '/browsed_news_test_data/' + user_id_folder = os.path.join(data_dir, "00_user_id_data") + if not os.path.exists(user_id_folder): + os.makedirs(user_id_folder) + + candidate_nid_folder = os.path.join(data_dir, "01_candidate_nid_data") + if not os.path.exists(candidate_nid_folder): + os.makedirs(candidate_nid_folder) + + labels_folder = os.path.join(data_dir, "02_labels_data") + print("======== labels_folder is ", labels_folder) + if not os.path.exists(labels_folder): + os.makedirs(labels_folder) + dataset = create_eval_dataset(mindpreprocess, EvalCandidateNews, batch_size=args.batch_size) + iterator = dataset.create_dict_iterator(output_numpy=True) + for idx, data in enumerate(iterator): + # 'uid', 'candidate_nid', 'labels' + uid = data["uid"] + candidate_nid = data["candidate_nid"] + labels = data["labels"] + file_name = "naml_browsed_news_" + str(idx) + ".bin" + user_id_file_path = os.path.join(user_id_folder, file_name) + uid.tofile(user_id_file_path) + candidate_nid_file_path = os.path.join(candidate_nid_folder, file_name) + candidate_nid.tofile(candidate_nid_file_path) + labels_file_path = os.path.join(labels_folder, file_name) + labels.tofile(labels_file_path) + +if __name__ == "__main__": + export_bin() diff --git a/official/recommend/naml/script/run_infer_310.sh b/official/recommend/naml/script/run_infer_310.sh index a4df3a012fa2b16f548aa4c19452e67941b0366c..275225f79338c15527f58e79988258220b7cbbf3 100644 --- a/official/recommend/naml/script/run_infer_310.sh +++ b/official/recommend/naml/script/run_infer_310.sh @@ -14,8 +14,8 @@ # 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] +if [[ $# -lt 2 || $# -gt 3 ]]; then + echo "Usage: bash run_infer_310.sh [NEWS_MODEL] [USER_MODEL] [DEVICE_ID] DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero" exit 1 fi @@ -30,16 +30,10 @@ get_real_path(){ 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 [ $# == 3 ]; then + device_id=$3 +elif [ $# == 2 ]; then if [ -z $device_id ]; then device_id=0 else @@ -49,11 +43,6 @@ 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/ @@ -70,10 +59,17 @@ else export ASCEND_OPP_PATH=$ASCEND_HOME/opp fi -function air_to_om() +function preprocess_data() { - 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 + if [ -d preprocess_Result ]; then + rm -rf ./preprocess_Result + fi + mkdir preprocess_Result + python3.7 ../preprocess.py --preprocess_path=./preprocess_Result &> preprocess.log + if [ $? -ne 0 ]; then + echo "preprocess data failed" + exit 1 + fi } function compile_app() @@ -101,7 +97,7 @@ function infer() 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 + ../ascend310_infer/out/main --news_mindir=$news_model --user_mindir=$user_model --device_id=$device_id --base_path=./preprocess_Result &> infer.log if [ $? -ne 0 ]; then echo "execute inference failed" exit 1 @@ -110,14 +106,14 @@ function infer() function cal_acc() { - python ../postprocess.py --result_path=./result_Files --label_path=$browsed_news_path/02_labels_data &> acc.log + python ../postprocess.py --result_path=./result_Files --label_path=./preprocess_Result/browsed_news_test_data/02_labels_data &> acc.log if [ $? -ne 0 ]; then echo "calculate accuracy failed" exit 1 fi } -air_to_om +preprocess_data compile_app infer cal_acc