From 5b360b2ee554c07b236e060b796b37f450b495bd Mon Sep 17 00:00:00 2001 From: bachelor-dou <15529241576@163.com> Date: Thu, 12 Mar 2026 08:08:40 +0000 Subject: [PATCH] update onnxruntime docs, sync CANN quick start from upstream at build time --- .gitignore | 1 + Makefile | 26 ++- _static/custom.css | 39 +++++ _static/onnxruntime_quickstart.js | 14 ++ conf.py | 1 + index.rst | 2 +- sources/onnxruntime/index.rst | 2 +- sources/onnxruntime/quick_start.rst | 244 ---------------------------- 8 files changed, 81 insertions(+), 248 deletions(-) create mode 100644 _static/onnxruntime_quickstart.js delete mode 100644 sources/onnxruntime/quick_start.rst diff --git a/.gitignore b/.gitignore index c2e1aefd..c4f7724b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ sources/_generated/ .tasks/ venv/ _repos/ +_static/ascend_config.json diff --git a/Makefile b/Makefile index b15972f2..3495e930 100644 --- a/Makefile +++ b/Makefile @@ -24,11 +24,15 @@ ASCEND_CONFIG := _static/ascend_config.json # Fetch script FETCH_SCRIPT := scripts/fetch_ascend_data.py +# Official ONNX Runtime CANN EP quick start source +ONNXRUNTIME_CANN_MD_URL := https://raw.githubusercontent.com/microsoft/onnxruntime/gh-pages/docs/execution-providers/community-maintained/CANN-ExecutionProvider.md +ONNXRUNTIME_CANN_MD_LOCAL := sources/_generated/sources/onnxruntime/quick_start.md + # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -.PHONY: help Makefile copy-docs clean-submodules fetch-config +.PHONY: help Makefile copy-docs clean-submodules fetch-config sync-onnxruntime-doc # Fetch ascend config (always run to ensure freshness) .PHONY: $(ASCEND_CONFIG) @@ -36,6 +40,24 @@ fetch-config: @echo "Fetching ascend configuration data..." @python3 $(FETCH_SCRIPT) +# Sync latest ONNX Runtime CANN EP doc from official gh-pages branch +sync-onnxruntime-doc: + @echo "Syncing ONNX Runtime CANN quick start from upstream..." + @mkdir -p $(dir $(ONNXRUNTIME_CANN_MD_LOCAL)) + @curl -fsSL "$(ONNXRUNTIME_CANN_MD_URL)" -o "$(ONNXRUNTIME_CANN_MD_LOCAL).tmp" + @awk 'BEGIN{in_fm=0} \ + {sub(/\r$$/, "", $$0)} \ + NR==1 && $$0=="---" {in_fm=1; next} \ + in_fm && $$0=="---" {in_fm=0; next} \ + in_fm {next} \ + $$0 ~ /^##[[:space:]]+Contents[[:space:]]*$$/ {next} \ + $$0 ~ /^\{:[[:space:]]*\.no_toc[[:space:]]*\}$$/ {next} \ + $$0 ~ /^\{:[[:space:]]*toc[[:space:]]*\}$$/ {next} \ + $$0 ~ /^\*[[:space:]]*TOC[[:space:]]+placeholder[[:space:]]*$$/ {next} \ + {print}' "$(ONNXRUNTIME_CANN_MD_LOCAL).tmp" > "$(ONNXRUNTIME_CANN_MD_LOCAL)" + @rm -f "$(ONNXRUNTIME_CANN_MD_LOCAL).tmp" + @echo "Synced to $(ONNXRUNTIME_CANN_MD_LOCAL)" + # Initialize submodules if not exists (use pinned commits for reproducibility) _repos/verl _repos/VeOmni _repos/LLaMA-Factory _repos/ms-swift: @echo "Initializing submodules..." @@ -65,7 +87,7 @@ clean-submodules: @git submodule deinit -f _repos/* # Explicit build targets with prerequisites -html dirhtml singlehtml latex pdf: fetch-config copy-docs +html dirhtml singlehtml latex pdf: fetch-config copy-docs sync-onnxruntime-doc @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) # Catch-all target for other Sphinx targets (clean, help, etc.) diff --git a/_static/custom.css b/_static/custom.css index 7dda4af4..b3b2e0c9 100644 --- a/_static/custom.css +++ b/_static/custom.css @@ -318,6 +318,45 @@ margin-bottom: 5%; } +body.onnxruntime-quickstart-page .rst-content { + color: #27384a; + font-size: 16px; + line-height: 1.75; +} + +body.onnxruntime-quickstart-page .rst-content h1, +body.onnxruntime-quickstart-page .rst-content h2, +body.onnxruntime-quickstart-page .rst-content h3 { + color: #1f4b8f; +} + +body.onnxruntime-quickstart-page .rst-content h1 { + border-bottom: 1px solid #d8e3f2; + padding-bottom: 8px; +} + +body.onnxruntime-quickstart-page .rst-content a { + color: #1f63d8; +} + +body.onnxruntime-quickstart-page .rst-content table.docutils { + border: 1px solid #d8e3f2; +} + +body.onnxruntime-quickstart-page .rst-content table.docutils th { + background: #f2f7ff; +} + +body.onnxruntime-quickstart-page .rst-content table.docutils tr:nth-child(even) td { + background: #f9fbff; +} + +body.onnxruntime-quickstart-page .rst-content .highlight { + background: #f7faff; + border: 1px solid #d8e3f2; + border-radius: 6px; +} + .box .flex-grow { flex-grow: 1; /* 让文本内容占据剩余空间 */ } diff --git a/_static/onnxruntime_quickstart.js b/_static/onnxruntime_quickstart.js new file mode 100644 index 00000000..239e5892 --- /dev/null +++ b/_static/onnxruntime_quickstart.js @@ -0,0 +1,14 @@ +(function () { + function isQuickstartPage() { + var pathname = window.location.pathname.toLowerCase(); + return pathname.indexOf('onnxruntime') !== -1 && pathname.indexOf('quick_start') !== -1; + } + + document.addEventListener('DOMContentLoaded', function () { + if (!isQuickstartPage()) { + return; + } + + document.body.classList.add('onnxruntime-quickstart-page'); + }); +})(); diff --git a/conf.py b/conf.py index aedc8f87..3b0a4410 100644 --- a/conf.py +++ b/conf.py @@ -73,6 +73,7 @@ def setup(app): app.add_css_file('custom.css') app.add_js_file('package_info.js') app.add_js_file('statistics.js') + app.add_js_file('onnxruntime_quickstart.js') # Generate ascend_config.json if it doesn't exist (for RTD/CI builds) import os.path diff --git a/index.rst b/index.rst index 48247751..35887271 100644 --- a/index.rst +++ b/index.rst @@ -233,7 +233,7 @@

onnxruntime

跨平台高性能推理加速器,v1.13.1 起支持昇腾。

- +
diff --git a/sources/onnxruntime/index.rst b/sources/onnxruntime/index.rst index b0164d9e..78e0dfed 100644 --- a/sources/onnxruntime/index.rst +++ b/sources/onnxruntime/index.rst @@ -5,4 +5,4 @@ onnxruntime :maxdepth: 2 install.rst - quick_start.rst + ../_generated/sources/onnxruntime/quick_start diff --git a/sources/onnxruntime/quick_start.rst b/sources/onnxruntime/quick_start.rst deleted file mode 100644 index 39a83caa..00000000 --- a/sources/onnxruntime/quick_start.rst +++ /dev/null @@ -1,244 +0,0 @@ -快速开始 -=========== - -.. note:: - 阅读本篇前,请确保已按照 :doc:`安装指南 <./install>` 准备好昇腾环境及 ONNX Runtime! - -本教程以一个简单的 resnet50 模型为例,讲述如何在 Ascend NPU上使用 ONNX Runtime 进行模型推理。 - -环境准备 ------------ - -安装本教程所依赖的额外必要库。 - -.. code-block:: shell - :linenos: - - pip install numpy Pillow onnx - -模型准备 ------------ - -ONNX Runtime 推理需要 ONNX 格式模型作为输入,目前有以下几种主流途径获得 ONNX 模型。 - -1. 从 `ONNX Model Zoo `_ 中下载模型。 -2. 从 torch、TensorFlow 等框架导出 ONNX 模型。 -3. 使用转换工具,完成其他类型到 ONNX 模型的转换。 - -本教程使用的 resnet50 模型是从 ONNX Model Zoo 中直接下载的,具体的 `下载链接 `_ - -类别标签 ------------ - -类别标签用于将输出权重转换成人类可读的类别信息,具体的 `下载链接 `_ - -模型推理 ------------ - -python推理示例 -~~~~~~~~~~~~~~~~~~~~ -.. code-block:: python - :linenos: - - import onnxruntime as ort - import numpy as np - import onnx - from PIL import Image - - def preprocess(image_path): - img = Image.open(image_path) - img = img.resize((224, 224)) - img = np.array(img).astype(np.float32) - - img = np.transpose(img, (2, 0, 1)) - img = img / 255.0 - mean = np.array([0.485, 0.456, 0.406]).reshape(3, 1, 1) - std = np.array([0.229, 0.224, 0.225]).reshape(3, 1, 1) - img = (img - mean) / std - img = np.expand_dims(img, axis=0) - return img - - def inference(model_path, img): - options = ort.SessionOptions() - providers = [ - ( - "CANNExecutionProvider", - { - "device_id": 0, - "arena_extend_strategy": "kNextPowerOfTwo", - "npu_mem_limit": 2 * 1024 * 1024 * 1024, - "op_select_impl_mode": "high_performance", - "optypelist_for_implmode": "Gelu", - "enable_cann_graph": True - }, - ), - "CPUExecutionProvider", - ] - - session = ort.InferenceSession(model_path, sess_options=options, providers=providers) - input_name = session.get_inputs()[0].name - output_name = session.get_outputs()[0].name - - result = session.run([output_name], {input_name: img}) - return result - - def display(classes_path, result): - with open(classes_path) as f: - labels = [line.strip() for line in f.readlines()] - - pred_idx = np.argmax(result) - print(f'Predicted class: {labels[pred_idx]} ({result[0][0][pred_idx]:.4f})') - - if __name__ == '__main__': - model_path = '~/model/resnet/resnet50.onnx' - image_path = '~/model/resnet/cat.jpg' - classes_path = '~/model/resnet/imagenet_classes.txt' - - img = preprocess(image_path) - result = inference(model_path, img) - display(classes_path, result) - -C++推理示例 -~~~~~~~~~~~~~~~~~ -.. code-block:: c++ - :linenos: - - #include - #include - - #include "onnxruntime_cxx_api.h" - - // path of model, Change to user's own model path - const char* model_path = "./onnx/resnet50_Opset16.onnx"; - - /** - * @brief Input data preparation provided by user. - * - * @param num_input_nodes The number of model input nodes. - * @return A collection of input data. - */ - std::vector> input_prepare(size_t num_input_nodes) { - std::vector> input_datas; - input_datas.reserve(num_input_nodes); - - constexpr size_t input_data_size = 3 * 224 * 224; - std::vector input_data(input_data_size); - // initialize input data with values in [0.0, 1.0] - for (unsigned int i = 0; i < input_data_size; i++) - input_data[i] = (float)i / (input_data_size + 1); - input_datas.push_back(input_data); - - return input_datas; - } - - /** - * @brief Model output data processing logic(For User updates). - * - * @param output_tensors The results of the model output. - */ - void output_postprocess(std::vector& output_tensors) { - auto floatarr = output_tensors.front().GetTensorMutableData(); - - for (int i = 0; i < 5; i++) { - std::cout << "Score for class [" << i << "] = " << floatarr[i] << '\n'; - } - - std::cout << "Done!" << std::endl; - } - - /** - * @brief The main functions for model inference. - * - * The complete model inference process, which generally does not need to be - * changed here - */ - void inference() { - const auto& api = Ort::GetApi(); - Ort::Env env(ORT_LOGGING_LEVEL_WARNING); - - // Enable cann graph in cann provider option. - OrtCANNProviderOptions* cann_options = nullptr; - api.CreateCANNProviderOptions(&cann_options); - - // Configurations of EP - std::vector keys{ - "device_id", - "npu_mem_limit", - "arena_extend_strategy", - "enable_cann_graph"}; - std::vector values{"0", "4294967296", "kNextPowerOfTwo", "1"}; - api.UpdateCANNProviderOptions( - cann_options, keys.data(), values.data(), keys.size()); - - // Convert to general session options - Ort::SessionOptions session_options; - api.SessionOptionsAppendExecutionProvider_CANN( - static_cast(session_options), cann_options); - - Ort::Session session(env, model_path, session_options); - - Ort::AllocatorWithDefaultOptions allocator; - - // Input Process - const size_t num_input_nodes = session.GetInputCount(); - std::vector input_node_names; - std::vector input_names_ptr; - input_node_names.reserve(num_input_nodes); - input_names_ptr.reserve(num_input_nodes); - std::vector> input_node_shapes; - std::cout << num_input_nodes << std::endl; - for (size_t i = 0; i < num_input_nodes; i++) { - auto input_name = session.GetInputNameAllocated(i, allocator); - input_node_names.push_back(input_name.get()); - input_names_ptr.push_back(std::move(input_name)); - auto type_info = session.GetInputTypeInfo(i); - auto tensor_info = type_info.GetTensorTypeAndShapeInfo(); - input_node_shapes.push_back(tensor_info.GetShape()); - } - - // Output Process - const size_t num_output_nodes = session.GetOutputCount(); - std::vector output_node_names; - std::vector output_names_ptr; - output_names_ptr.reserve(num_input_nodes); - output_node_names.reserve(num_output_nodes); - for (size_t i = 0; i < num_output_nodes; i++) { - auto output_name = session.GetOutputNameAllocated(i, allocator); - output_node_names.push_back(output_name.get()); - output_names_ptr.push_back(std::move(output_name)); - } - - // User need to generate input date according to real situation. - std::vector> input_datas = input_prepare(num_input_nodes); - - auto memory_info = Ort::MemoryInfo::CreateCpu( - OrtAllocatorType::OrtArenaAllocator, OrtMemTypeDefault); - - std::vector input_tensors; - input_tensors.reserve(num_input_nodes); - for (size_t i = 0; i < input_node_shapes.size(); i++) { - auto input_tensor = Ort::Value::CreateTensor( - memory_info, - input_datas[i].data(), - input_datas[i].size(), - input_node_shapes[i].data(), - input_node_shapes[i].size()); - input_tensors.push_back(std::move(input_tensor)); - } - - auto output_tensors = session.Run( - Ort::RunOptions{nullptr}, - input_node_names.data(), - input_tensors.data(), - num_input_nodes, - output_node_names.data(), - output_node_names.size()); - - // Processing of out_tensor - output_postprocess(output_tensors); - } - - int main(int argc, char* argv[]) { - inference(); - return 0; - } \ No newline at end of file