
异步运行Graph【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge单进程单卡异步运行本章节给出使用异步运行接口并使用Device内存运行Graph的示例。功能介绍构建完Graph之后如果您希望编译并异步运行Graph获得Graph的运行结果请参考本节内容。涉及的主要接口为调用GEInitializeV2进行系统初始化也可在Graph构建前调用申请系统资源。调用《Runtime运行时 API》中的“初始化和去初始化 aclInit”接口初始化acl。调用Session构造函数创建Session类对象申请Session资源。调用《Runtime运行时 API》中的“Device管理 aclrtSetDevice”指定运行的Device调用“aclrtCreateStream”创建Stream然后调用《Runtime运行时 API》中的“内存管理 aclrtMallocHost/aclrtMalloc”分别申请Host和Device内存。调用AddGraph在Session类对象中添加定义好的图。可选调用CompileGraph完成图编译。可选调用LoadGraph异步执行Graph场景加载图模型到上面步骤创建的Stream上。调用RunGraphWithStreamAsync异步运行接口运行Graph若在调用本接口前未执行LoadGraph完成图加载则本接口将自动调用LoadGraph以完成加载若在调用LoadGraph接口前未执行CompileGraph完成图编译则LoadGraph将自动调用CompileGraph以完成编译。调用“aclrtSynchronizeStream”阻塞程序运行直到指定Stream中的所有任务都完成。调用《Runtime运行时 API》中的“内存管理 aclrtFree/aclrtFreeHost”释放内存调用GEFinalizeV2释放系统资源调用《Runtime运行时 API》中的“初始化和去初始化 aclFinalize”释放相关资源。开发示例包含的头文件包括acl、C或C标准库的头文件。#include ge_api_v2.h #include acl.h #include acl_rt.h申请系统资源。Graph定义完成后调用GEInitializeV2进行系统初始化也可在Graph定义前调用申请系统资源。示例代码如下std::mapAscendString, AscendStringconfig {{ge.exec.deviceId, 0}, {ge.graphRunMode, 1}}; Status ret ge::GEInitializeV2(config);可以通过config配置传入GE运行的初始化信息配置参数ge.exec.deviceId和ge.graphRunMode分别用于指定GE实例运行设备图执行模式在线推理请配置为0训练请配置为1。更多配置请参考options参数说明。[!NOTE]说明GE options中的dump信息与后续调用acl初始化接口时配置的dump信息建议两者不要同时配置否则可能导致异常。其他相同功能的参数类似。acl资源初始化。std::string aclConfigPath xx/xx/xx; aclError retInit aclInit(aclConfigPath); if (retInit ! ACL_ERROR_NONE) { // ... // ... return FAILED; }创建Session。若想使定义好的Graph运行起来首先要创建一个Session对象。Session中的options可以加载配置参数支持的配置参数请参见options参数说明。std::map AscendString, AscendString options; // 创建Session对象 ge::GeSession* session new GeSession(options); // 判断Session是否创建成功 if(session nullptr) { std::cout Create session failed. std::endl; // ... // ... // 释放资源 ge::GEFinalizeV2(); return FAILED; }指定运行的Device创建Stream申请内存。// 指定用于运算的Device int32_t deviceId 0; retInit aclrtSetDevice(deviceId); // 创建一个Stream aclrtStream stream nullptr; aclError aclRet aclrtCreateStream(stream); // 申请Host上的内存 void* hostPtrA NULL; size_t size 1024; aclRet aclrtMallocHost(hostPtrA, size); // 申请Device上的内存 void* devPtrB NULL; aclRet aclrtMalloc(devPtrB, size, ACL_MEM_MALLOC_HUGE_FIRST); // 内存复制将Host上数据传输到Device // hostPtrA表示Host上源内存地址指针devPtrB表示Device上目的内存地址指针size表示内存大小 aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE);添加Graph对象。调用AddGraph接口添加Graph。示例代码如下// 准备将要添加到Session的Graph ID并创建空的Graph对象 uint32_t conv_graph_id 0; ge::Graph conv_graph; // 将Graph添加到Session Status ret session-AddGraph(conv_graph_id, conv_graph); if(ret ! SUCCESS) { // ... // ... // 释放资源并销毁Session ge::GEFinalizeV2(); delete session; return FAILED; }用户可以通过传入options配置图运行相关配置信息相关配置请参考Session构造函数。其中图运行完之后的数据保存在Tensor output_cov中。可选编译Graph。如果不调用CompileGraph接口LoadGraph接口将自动调用CompileGraph以完成编译。uint32_t graph_id 0; ret session-CompileGraph(graph_id); if(ret ! SUCCESS) { // ... // ... // 释放资源 ge::GEFinalizeV2(); delete session; return FAILED; }可选加载Graph到创建的Stream上。如果不调用LoadGraph接口RunGraphWithStreamAsync接口将自动调用LoadGraph以完成加载。LoadGraph中的options可以加载配置参数比如可以加载**“ge.exec.frozenInputIndexes设置地址不刷新的输入Tensor索引”**参数该配置参数可以提升图执行性能参数说明请参见options参数说明。std::map AscendString, AscendString options; uint32_t graph_id 0; ret session-LoadGraph(graph_id, options, stream); if(ret ! SUCCESS) { // ... // ... // 释放资源 ge::GEFinalizeV2(); delete session; return FAILED; }数据传输。// 内存复制将Host上数据传输到Device // hostPtrA表示Host上源内存地址指针devPtrB表示Device上目的内存地址指针size表示内存大小 aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE);异步执行Graph输出执行结果。ret session-RunGraphWithStreamAsync(graph_id, stream, input, output); // 调用aclrtSynchronizeStream接口阻塞应用程序运行直到指定Stream中的所有任务都完成 aclRet aclrtSynchronizeStream(stream); // 内存复制将Device数据传回Host // devPtrA表示Device上的源内存地址指针hostPtrB表示Host上的目的内存地址指针size表示内存大小 aclrtMemcpy(hostPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_HOST);释放资源。// 释放内存 ret aclrtFree(devPtrB); ret aclrtFreeHost(hostPtrA); // 释放Graph资源 ret ge::GEFinalizeV2(); // acl去初始化 ret aclFinalize();单进程多卡异步运行本章节介绍如何使用单进程管理多卡即一个进程可以并发执行在不同的Device上。功能介绍涉及的主要接口为调用GEInitializeV2进行系统初始化也可在Graph构建前调用申请系统资源。调用《Runtime运行时 API》中的“初始化和去初始化 aclInit”接口初始化acl。调用Session构造函数创建多个Session类对象申请Session资源每个Session传入不同的ge.session_device_id将模型运行在不同的Device。创建多个线程每个线程传入不同的Session下面以一个线程为例描述简单的流程调用《Runtime运行时 API》中的“Device管理 aclrtSetDevice”指定运行的Device调用“aclrtCreateStream”创建Stream然后调用《Runtime运行时 API》中的“内存管理 aclrtMalloc”申请Device内存。调用AddGraph在Session类对象中添加定义好的图。调用CompileGraph完成图编译。调用LoadGraph异步执行Graph场景将图模型加载到前面创建的Stream上。调用《Runtime运行时 API》中的“内存管理 aclrtMemcpy”将数据从Host传输到Device。调用RunGraphWithStreamAsync异步执行接口运行Graph。调用“aclrtSynchronizeStream”阻塞程序运行直到指定Stream中的所有任务都完成。调用《Runtime运行时 API》中的“内存管理 aclrtMemcpy”将数据从Device回传到Host。调用《Runtime运行时 API》中的“内存管理 aclrtFree”释放内存。调用GEFinalizeV2释放系统资源调用《Runtime运行时 API》中的“初始化和去初始化 aclFinalize”释放相关资源。开发示例包含的头文件包括acl、C或C标准库的头文件。#include ge_api_v2.h #include acl.h #include acl_rt.h #include graph/ascend_string.h #include thread申请系统资源。Graph定义完成后调用GEInitializeV2进行系统初始化也可在Graph定义前调用申请系统资源。示例代码如下std::mapAscendString, AscendStringconfig {{ge.exec.deviceId, 0}, {ge.graphRunMode, 1}}; Status ret ge::GEInitializeV2(config);可以通过config配置传入GE运行的初始化信息配置参数ge.exec.deviceId和ge.graphRunMode分别用于指定GE实例运行设备图执行模式在线推理请配置为0训练请配置为1。更多配置请参考options参数说明。[!NOTE]说明GE options中的dump信息与后续调用acl初始化接口时配置的dump信息建议两者不要同时配置否则可能导致异常。其他相同功能的参数类似。acl资源初始化。std::string aclConfigPath xx/xx/xx; aclError retInit aclInit(aclConfigPath); if (retInit ! ACL_ERROR_NONE) { // ... // ... return FAILED; }创建多个Session。若想使定义好的Graph运行起来首先要创建一个Session对象。Session中的options可以加载配置参数支持的配置参数请参见options参数说明。int thread_num 8; // 以8个device为例 for (int i 0; i thread_num; i) { // 创建多个Session每个Session的options中传入不同的ge.session_device_id std::mapge::AscendString, ge::AscendString options { // 构造Session的配置 {ge.session_device_id,std::to_string(i).c_str()}, }; ge::GeSession *session new ge::GeSession(options); // 创建Session传入配置map if (session nullptr) { // 检查Session是否创建成功 std::cout create session failed! std::endl; ge::GEFinalizeV2(); return FAILED; } sessions.push_back(session); }创建多个线程每个线程传入不同的Session和ge.session_device_id进行异步运行Graph。// 用来保存所有线程对象的容器 std::vectorstd::thread threads; // 创建多条线程并存入容器 for (int i 0; i thread_num; i) { std::thread worker_thread(exec_func, i); // 创建一个线程执行exec_funcexec_func线程函数如5.a~5.g步骤所示 threads.emplace_back(std::move(worker_thread)); //通过std::move将worker_thread移动到threads容器中 } // 等待所有线程完成 for (int i 0; i thread_num; i) { threads.at(i).join(); }单个线程exec_func异步运行步骤如下指定运行的Device创建Stream申请内存。// 指定用于运算的Device int32_t deviceId 0; retInit aclrtSetDevice(deviceId); // 创建一个Stream aclrtStream stream nullptr; aclError aclRet aclrtCreateStreamWithConfig(stream, 0, ACL_STREAM_FAST_LAUNCH); // 申请Device上的内存 void* devPtrB NULL; aclRet aclrtMalloc(devPtrB, data_size, ACL_MEM_MALLOC_HUGE_FIRST);添加Graph对象。uint32_t graph_id 0; ge::Graph graph; sess_ sessionList[index]; ge::Status ret sess_ - AddGraph(graph_id, graph, graph_options); if(ret ! SUCCESS) { // ... // ... // 释放资源 ge::GEFinalizeV2(); delete session; return FAILED; }用户可以通过传入options配置图运行相关配置信息其中图运行完之后的数据保存在Tensor output_cov中。可选编译Graph。如果不调用CompileGraph接口LoadGraph接口将自动调用CompileGraph以完成编译。uint32_t graph_id 0; ret sess_ - CompileGraph(graph_id); if(ret ! SUCCESS) { // ... // ... // 释放资源并销毁Session ge::GEFinalizeV2(); delete session; return FAILED; }可选加载Graph到创建的Stream上。如果不调用LoadGraph接口RunGraphWithStreamAsync接口将自动调用LoadGraph以完成加载。LoadGraph中的options可以加载配置参数支持的配置参数请参见options参数说明。std::map AscendString, AscendString options; uint32_t graph_id 0; ret sess_ - LoadGraph(graph_id, options, stream); if(ret ! SUCCESS) { // ... // ... // 释放资源并销毁Session ge::GEFinalizeV2(); delete session; return FAILED; }数据传输。// 内存复制将Host上数据传输到Device // hostPtrA表示Host上源内存地址指针devPtrB表示Device上目的内存地址指针size表示内存大小 aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE);异步运行Graph输出执行结果。std::vectorgert::Tensor input; std::vectorgert::Tensor output; ret sess_-RunGraphWithStreamAsync(graph_id, stream, input, output); // 调用aclrtSynchronizeStream接口阻塞应用程序运行直到指定Stream中的所有任务都完成 aclRet aclrtSynchronizeStream(stream); // 内存复制将Device数据传回Host // devPtrA表示Device上源内存地址指针hostPtrB表示Host上目的内存地址指针size表示内存大小 aclrtMemcpy(hostPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_HOST);释放内存。// 释放内存 ret aclrtFree(devPtrB);释放资源。// 释放各个Session资源 for (auto session : sessions) { delete session; } // 释放Graph资源 ret ge::GEFinalizeV2(); // acl去初始化 ret aclFinalize();【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考