【昇腾】【玩转​Atlas200DK系列】应用开发之HelloWorld

举报
山人_mhc 发表于 2019/12/22 11:54:30 2019/12/22
【摘要】 从hello world用例开始!在本例中,我们不新增引擎,只是利用默认的引擎打印一句“Hello World”,并在结束时打印“App run finished”,来了解和学习Matrix框架和引擎的概念以及数据的流动。

【昇腾】【玩转Atlas200DK系列】应用开发之HelloWorld

【昇腾】万事皆有开头,从本篇起,开始学习如何开发运行在Atlas200DK上的应用!

不免俗,咱也从hello world用例开始!在本例中,我们不新增引擎,只是利用默认的引擎打印一句“Hello World”,并在结束时打印“App run finished”,来了解和学习Matrix框架和引擎的概念以及数据的流动。

通过Mind Studio工具提供的UI界面进行应用开发前,需要完成Mind Studio的安装(包括DDK安装)和编译环境的配置(包括Lib包安装),如果还没有准备好环境,请参见请参见Mind Studio安装以及配置编译环境

 

创建工程

创建工程时注意选择Ascend App,并选择Custom工程,便可以创建一个最基本的拥有Matrix编程框架的自定义工程,你可以在该基本框架下添枝加叶,开发出你自己的应用。

image.png image.png

点击Finish之后,创建的工程目录结构如下:

 

image.png

其中,工程结构及Matrix/Engine等的概念请参考官方指导中快速入门中体验首个AI应用进行了解,官方指导中的例子会详细告诉你这些概念,在此不再赘述。在本例中,我们开始最简单的实战编程。

编译并运行

我们先编译运行一下看看,发现该工程已经能够运行,只是运行后没有任何输出(在开发板侧直接运行也是),没有任何感觉。

HelloWorld实现

接下来我们实现我们预定的目标:

在本例中,我们不新增引擎,只是利用默认的引擎打印一句Hello World”,并在结束时打印“App run finished”,来了解和学习Matrix框架和引擎的概念以及数据的流动。

第一步:

main.cpp中将原来发送的空串赋值为Hello World

image.png 

第二步:

Custom.cpp中,接收传入的字符串并打印到屏幕上,然后发送字符串,该字符串会在引擎的回调函数中接收并输出到屏幕;

image.png 

第三步:

main.cpp中定义的回调函数中将接收到的内容输出到屏幕

image.png 

第四步:

编译运行;

然后ssh登陆到开发板上直接运行可执行程序:

image.png 

发现预定目标已经实现。

是不是非常简单,那当然了,要不然干嘛叫HelloWorld呢。

 

知其所以然

(注:如果有任何不明白的可以查看应用开发教程:https://ascend.huawei.com/doc/Atlas%20200%20DK/1.31.0.0(beta)/zh/zh-cn_topic_0197853888.html

接下来解析工程,尝试理解下这个这个工程框架;

1. 查看graph.config, 发现只有一个引擎(Custom),该引擎ID611,引擎名称为“Custom”,该引擎后面编译后会生成libHost.so,该so会在运行时被同步到Atlas200DK

image.png 

2. 解析main.cpp,只干了两件事情;

2.1 创建图并注册回调函数,创建图好理解,在Matrix流程编排中,依据graph.config创建图,图中定义了各个引擎以及各个引擎之间的链接关系;注册回调函数,则一般是为最后一个引擎注册一个回调函数,当最后一个引擎发送数据时,该回调函数会被调用,具体实现方法请参考(https://ascend.huawei.com/doc/Atlas%20200%20DK/1.31.0.0(beta)/zh/zh-cn_topic_0188098559.html

2.2 发送一个数据至引擎,这时候调的是Graph::SendData, 是从外部向Matrix发送一个数据启动引擎,该数据可以是一个空串,也可以是任意一个数据类型,强转为void类型,该数据会被发送至Graph.confg中定义的一个引擎,这时数据就流动起来了。

ret = graph->SendData(engineId, "string", std::static_pointer_cast<void>(data));

在本案例中,我们就是用的这个string向引擎Custom发送一个字符串:HelloWorld 

3. 解析Custom.cpp, 也是干了两件事:

首先接收传进来的数据arg0,后面我们会了解到如果有多个数据,则为arg1arg2....

然后在发出一个数据,该数据被从0端口发出,框架保证了发送的数据会被main.cpp中定义的注册函数接收到,所以我们在这里发了一个字符串: "App run finished!"

HIAI_IMPL_ENGINE_PROCESS("Custom", Custom, INPUT_SIZE)

{

    //TODO:

//user code here 

auto a  = std::static_pointer_cast<string>(arg0); 

    printf("%s\n", (*a).c_str());

//send data

std::shared_ptr<std::string> resultData(new std::string);

*resultData = "App run finished!"; 

    HIAI_StatusT ret = SendData(0, "string", std::static_pointer_cast<void>(resultData));

    return ret;

}

4. 接下来再来看main.cpp, 看注册的回到函数做了是啥?

首先是咱加的一句打屏;

然后可以看到就是将flag--, 那么该flag--什么用呢?

 

HIAI_StatusT CustomDataRecvInterface::RecvData(const std::shared_ptr<void>& message) {

    std::shared_ptr<std::string> data =  std::static_pointer_cast<std::string>(message); 

    std::cout <<  *data << std::endl; 

    mt.lock();

    flag--;

    mt.unlock();

    return HIAI_OK;

}

继续查看flag发现,flag在程序启动时初始化为1,在主函数中,每隔100毫秒便会查看一次flag,如果flag小于等于0则停止运行。

那么可以理解了,在回调函数中做的事情就是为了告诉主函数该结束了。(如果你想玩一下,可以试一下将flag初始化为2(而不是1),那么一旦你开始运行,你发现你的程序结束不了了。) 

for (;;) {

        if(flag <= 0) {

            break;

        } else {

            usleep(100000);

        }

}

 

总结

通过该案例并结合应用开发教程,你应该已经大致了解了Matrix开发的基本流程,回调函数在Matrix开发中的应用,Graph::SendData以及Engine::SendDataarg0的解析,graph.config的结构和使用等等知识点。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。