昇腾社区首页
中文
注册
开发者
下载

单进程单卡异步Graph运行

本章节给出使用异步运行接口,并使用Device内存运行Graph的示例。

功能介绍

Atlas 200I/500 A2 推理产品 不支持该特性

构建完Graph之后,如果您希望编译并异步运行Graph获得Graph的运行结果,请参考本节内容。涉及的主要接口为:

  1. 调用GEInitializeV2进行系统初始化(也可在Graph构建前调用),申请系统资源。
  2. 调用aclInit接口,初始化acl
  3. 调用Session构造函数创建Session类对象,申请Session资源。
  4. 调用aclrtSetDevice指定运行的Device,调用aclrtCreateStream创建Stream,然后调用aclrtMallocHostaclrtMalloc分别申请Host和Device内存。
  5. 调用AddGraph在Session类对象中添加定义好的图。
  6. (可选)调用CompileGraph完成图编译。
  7. (可选)调用LoadGraph(异步执行Graph场景),加载图模型到4创建的Stream上。
  8. 调用RunGraphWithStreamAsync异步运行接口,运行Graph:

    若在调用本接口前未执行LoadGraph完成图加载,则本接口将自动调用LoadGraph以完成加载;若在调用LoadGraph接口前未执行CompileGraph完成图编译,则LoadGraph将自动调用CompileGraph以完成编译。

  9. 调用aclrtSynchronizeStream阻塞程序运行,直到指定Stream中的所有任务都完成。
  10. 调用aclrtFreeaclrtFreeHost释放内存;调用GEFinalizeV2,释放系统资源;调用aclFinalize释放acl相关资源。

开发示例

  1. 包含的头文件,包括acl、C或C++标准库的头文件。
    1
    2
    3
    #include "ge_api.h"
    #include "acl.h"
    #include "acl_rt.h"
    
  2. 申请系统资源。

    Graph定义完成后,调用GEInitialize进行系统初始化(也可在Graph定义前调用),申请系统资源。示例代码如下:

    1
    2
    3
    std::map<AscendString, AscendString>config = {{"ge.exec.deviceId", "0"},
                                                  {"ge.graphRunMode", "1"}};
    Status ret = ge::GEInitializeV2(config);
    

    可以通过config配置传入GE运行的初始化信息,配置参数ge.exec.deviceId和ge.graphRunMode,分别用于指定GE实例运行设备,图执行模式(在线推理请配置为0,训练请配置为1)。更多配置请参考options参数说明

    GE options中的dump信息,与后续调用acl初始化接口时配置的dump信息,建议两者不要同时配置,否则可能导致异常。其他相同功能的参数类似。

  3. acl资源初始化。
    1
    2
    3
    4
    5
    6
    7
        std::string aclConfigPath = "xx/xx/xx";
        aclError retInit = aclInit(aclConfigPath);
        if (retInit != ACL_ERROR_NONE) {
            // ...
            // ...
            return FAILED;
        }
    
  4. 创建Session。
    若想使定义好的Graph运行起来,首先,要创建一个Session对象。Session中的options可以加载配置参数,支持的配置参数请参见options参数说明
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    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;
    }
    
  5. 指定运行的Device,创建Stream,申请内存。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 指定用于运算的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);
    
  6. 添加Graph对象。
    调用AddGraph接口添加Graph。示例代码如下:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    // 准备将要添加到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中。

  7. (可选)编译Graph。
    如果不调用CompileGraph接口,LoadGraph接口将自动调用CompileGraph以完成编译。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    uint32_t graph_id = 0;
    ret = session-> CompileGraph(graph_id);
    if(ret != SUCCESS) {
      // ...
      // ...
      // 释放资源
      ge::GEFinalizeV2();
      delete session;
      return FAILED;
    }
    
  8. (可选)加载Graph到创建的Stream上。
    如果不调用LoadGraph接口,RunGraphWithStreamAsync接口将自动调用LoadGraph以完成加载。LoadGraph中的options可以加载配置参数,比如可以加载“ge.exec.frozenInputIndexes(设置地址不刷新的输入Tensor索引)”参数,该配置参数可以提升图执行性能;options中支持的更多配置参数请参见options参数说明
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    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;
    }
    
  9. 数据传输。
    1
    2
    3
    // 内存复制,将Host上数据传输到Device
    // hostPtrA表示Host上源内存地址指针,devPtrB表示Device上目的内存地址指针,size表示内存大小
        aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE);
    
  10. 异步执行Graph,输出执行结果。
    1
    2
    3
    4
    5
    6
    7
    8
        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);
    
  11. 释放资源。
    1
    2
    3
    4
    5
    6
    7
    // 释放内存
        ret = aclrtFree(devPtrB);
        ret = aclrtFreeHost(hostPtrA);
    // 释放Graph资源
        ret = ge::GEFinalizeV2();
    // acl去初始化
        ret = aclFinalize();