• [经验分享] ResNet18 :使用MindStudio进行MindX SDK应用开发
    目录写在最前面ResNet18简介工具简介MindX SDK简介MindStudio环境搭建与配置MindStudio安装(Windows版本)SSH连接MindX SDK安装推理开发运行流程业务开发Python版本开发新建一个目录代码目录结构模型转换pipeline文件编排main.py文件编写代码运行C++版本开发新建一个项目代码目录结构模型转换(或者不转换)业务代码书写(修改)项目编译代码运行可参考的代码FAQ模型运行报错?如果想换个数据集怎么办?Python找不到模型路径?C++找不到模型路径?No Python interpreter configured for the module?SDK版本获取失败?结语1. 写在最前面这是一篇基于昇腾众智“ResNet18 for pytorch”代码的MindX SDK应用开发经验帖。原始项目代码可以从Ascend/ModelZoo-PyTorch - Gitee.com仓库中找到,根据原始项目代码,我们可以在MindStudio上快速实现一个ImageNet2012数据集1000分类应用的开发。整个过程中,MindStudio昇腾论坛上的教程基于MindStudio的MindX SDK应用开发全流程MindStudio昇腾_华为云论坛 (huaweicloud.com)也提供了很大的帮助。2. ResNet18简介ResNet是ImageNet竞赛中分类问题效果较好的网络,它引入了残差学习的概念,通过增加直连通道来保护信息的完整性,解决信息丢失、梯度消失、梯度爆炸等问题,让很深的网络也得以训练。ResNet有不同的网络层数,常用的有18-layer、34-layer、50-layer、101-layer、152-layer。ResNet18的含义是指网络中有18-layer。参考论文:He K, Zhang X, Ren S, et al. Deep residual learning for image recognition[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2016: 770-778.3. 工具简介3.1. MindX SDK介绍MindX SDK是华为昇腾AI处理器加速的AI软件开发套件(SDK), 提供了大量丰富的API,可以快速完成AI应用的开发3.2. MindStudioMindStudio提供了一个AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助开发者在一个工具上就能高效便捷地完成AI应用开发MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能官网地址:MindStudio-昇腾社区 (hiascend.com)4. 环境搭建与配置因为我使用的Windows系统环境,所以这里提供Windows环境下MindStdio环境搭建和配置的全流程,其它系统可以查看安装方案-安装指南-MindStudio-文档首页-昇腾社区 (hiascend.com)4.1. MindStudio 安装(Windows版本)安装前的说明MindStudio可以单独安装在Windows上。在安装MindStudio前需要在Linux服务器上安装部署好Ascend-cann-toolkit开发套件包,之后在Windows上安装MindStudio,安装完成后通过配置远程连接的方式建立MindStudio所在的Windows服务器与Ascend-cann-toolkit开发套件包所在的Linux服务器的连接,实现全流程开发功能。我所采用的是windows共部署的方法​​2. 下载安装MindStudio前往MindStudio下载-昇腾社区 (hiascend.com)页面进行MindStudio软件包的下载,并且参照安装MindStudio-安装操作(Windows)完成MindStudio的安装。4.2. SSH连接在进行共部署之前,先确认SSH服务器连接成功按照上面图中所示,依次配置之后,点击Test Connection,显示下图就表示连接成功。4.3. MindX SDK安装远端环境MindX SDK安装Windows 场景下基于 MindStuido 的 SDK 应用开发,请先确保远端环境上 MindX SDK 软件包已安装完成,安装方式请参见《mxManufacture 用户指南》和 《mxVision 用户指南》的“使用命令行方式开发”>“安装 MindX SDK 开发套件” 章节。本地 CANN 安装①:在 Windows 本地打开 MindStudio,点击 Customize > Allsettings…,如下图所示:②:进入设置页面,点击 Appearance & Behavior > System Settings > CANN 进入 CANN 管理界面。完成后的状态如下图所示:3. 本地 MindX SDK安装与步骤 2 开始一致,进入设置页面,点击 Appearance & Behavior > System Settings > MindX SDK 进入 MindX SDK 管理界面。界面中 MindX SDK Location 为软件包的默认安装路径,默认安装路径为“C:\Users\用户名\Ascend\mindx_sdk”。 单击 Install SDK 进入 Installation settings 界面。参数说明Remote Connection远程连接的用户及 IPRemote CANN Location远端环境上 CANN 开发套件包的路 径,请配置到版本号一级Remote SDK Location远端环境上 SDK 的路径,请配置到 版本号一级。IDE 将同步该层级下的 include、opensource、python、 samples 文件夹到本地 Windows 环境Local SDK Location同步远端环境上 SDK 文件夹到本地 的路径。默认安装路径为“C:\Users\ 用户名\Ascend\mindx_sdk”5. 推理开发运行流程使用 MindStudio 开发和运行推理业务步骤如下:(1) 确定业务流程:根据业务功能如目标检测、图像分类、属性识别等,将 业务流程进行模块化。(2) 寻找合适插件:根据已有 SDK 插件的功能描述和规格限制来匹配业务功 能,当 SDK 提供的插件无法满足功能需求时,用户可以开发自定义插件。(3) 准备推理模型文件与数据:准备输入图片和下载模型,使用 Model Convertor 模型转换工具将模型转换为 om 格式。(4) 流程编排:以可视化的方式,开发数据流图,生成 pipeline 文件供应用框 架使用,配置文件以 json 格式编写,必须指定业务流名称、元件名称和 插件名称,并根据需要,补充元件属性和下游元件名称信息。(5) 业务集成:编写 C++程序或 Python 程序,调用业务流管理的 API ( MxStreamManager ), 先 进 行 初 始 化 , 再 加 载 业 务 流 配 置 文 件 (*.pipeline),然后根据 stream 配置文件中的 StreamName 往指定 Stream 获取输出数据,最后销毁 Stream。(6) 编译与运行应用:若新建的工程为 Python 版本的应用工程,不需要执行 编译应用工程,配置 Python 环境后,即可在远端服务器运行;若新建工 程为 C++版本的应用工程,则需要进行远端编译,远端编译时,会对工 程文件夹进行目录拷贝到远端连接的环境,编译成功后即可运行。6. 业务开发业务开发将按照python版和C++版分别进行介绍6.1.Python版本开发6.1.1 新建一个项目首先创建一个项目,选择一个自己喜欢的位置,比如图中所示,将在D:\Codes\python\Ascend\MyApp位置下创建自己的项目。选择好了后,点击下一步选择MindX SDK Project(Python)如图所示,被圈出来的4个项目,上面两个是空模板,在这里面创建我们自己的工程项目,因为我们要创建Python版的应用,所以选箭头指的这个;下面两个是官方给出的样例项目,如果对目录结构和应该写哪些代码不太熟悉的话,也可以创建一个样例项目先学习一下。选择完成后,点击Finish完成项目的创建6.1.2 代码目录结构Python版本的SDK项目大概有哪些文件呢?我们其实可以先打开一个官方样例项目先看看左边是我们自己创建的项目,右边是官方样例项目,对比之下我们可以发现,右边的样例项目主要有models(用于存储模型文件)、pipeline(流程编排文件)、python(项目python代码)和streamserver(实际开发中没用上)。PS: 其实也不一定要按照这个目录结构存放代码,只是这样结构更加清晰一些。我的工程目录文件是这样其中data用来存放数据图片6.1.3 模型转换下载模型首先我们先在ModelZoo-昇腾社区 (hiascend.com)中下载ResNet18模型和代码选Pytorch版分别下载模型脚本和模型其中模型脚本在“pipeline文件编排”和“main.py文件编写”章节得到应用解压后,我们只要这个onnx模型,同时,我们将names标签数据也一起放进models文件夹模型转换点击这个工具,进入模型转换界面选择待转换的模型路径选好后点一下任意一个位置,MindStudio会进入模型解析状态等待模型解析完成后,可以修改输出的模型名字,或者点击下一步点击Finish,开始转换转换完成稍等片刻,出现这个就表明转换完成如上图所示,在显示的路径中可以找到转化好的文件我们将om文件移动到models文件夹中,就可以进行接下去的步骤了6.1.4 pipeline文件编排pipeline文件编排是python版SDK最主要的推理开发步骤作为一个图片分类任务,主要包括以下几个步骤:初始化 → 图片数据传送 → 图片预处理 → 图片分类 → 序列化 → 结果传回由于ResNet18模型采用的是PIL库进行图片预处理,而非opencv,因此我们不在pipeline中进行图片预处理步骤(包括图片解码、缩放、裁剪),而是通过在main.py文件中进行图片预处理,再将结果传给推理业务因此pipeline流程编排为以下几个步骤初始化 → 获取图片数据 → 图片分类 → 序列化 → 结果传回可视化结果如下图所示:实际上,我们可以通过对之前下载好的代码文件中已有的pipeline进行简单修改,就可以完成我们自己的pipeline文件编排在下载好的ResNet18_for_PyTorch_{$version}__code中,路径./infer/sdk/data/config下可以找到resnet18.cfg和resnet8.pipeline两个文件,将这两个文件分别移动到models目录和pipeline目录下,如下图所示:对resnet18.pipeline进行参数修改我个人比较喜欢文本编辑的方式修改,如下图所示修改完成后,就可以进行main.py文件的编写了,离成功运行越来越近了!6.1.5 main.py文件编写根据pipeline文件编排中的说明,我们在main.py中需要完成3件事——对图片进行预处理+将预处理好的结果传给推理业务+获取推理结果实际上,我们依旧可以参考下载的代码文件中./infer/sdk/main.py文件中的做法,稍作修改就可以(1) 图片预处理主要用到resize、center_crop、preprocess和gen_protobuf(图片编码为推理业务需要的字节流)四个函数参照下载代码中的main.py文件,很容易就能得到这四个函数# resize and cropdef resize(img, size, interpolation=Image.BILINEAR): return img.resize(size[::-1], interpolation)def center_crop(img, out_height, out_width): height, width, _ = img.shape left = int((width - out_width) / 2) right = int((width + out_width) / 2) top = int((height - out_height) / 2) bottom = int((height + out_height) / 2) img = img[top:bottom, left:right] return img# preprocessor调用上面的两个函数进行图片缩放裁剪处理def preprocess(in_file): mean = [0.485, 0.456, 0.406] std = [0.229, 0.224, 0.225] img = Image.open(in_file).convert('RGB') w = img.size[0] h = img.size[1] if w > h: input_size = np.array([256, 256 * w / h]) else: input_size = np.array([256 * h / w, 256]) input_size = input_size.astype(int) print(input_size) img = resize(img, input_size) # transforms.Resize(256) img = np.array(img, dtype=np.float32) img = center_crop(img, 224, 224) # transforms.CenterCrop(224) img = img / 255. # transforms.ToTensor() img[..., 0] = (img[..., 0] - mean[0]) / std[0] img[..., 1] = (img[..., 1] - mean[1]) / std[1] img[..., 2] = (img[..., 2] - mean[2]) / std[2] img = img.transpose(2, 0, 1) # HWC -> CHW return img#generate protobuf调用preprocess生成传给推理业务的流数据def gen_protobuf(in_file): img_np = preprocess(in_file) vision_list = MxpiDataType.MxpiVisionList() vision_vec = vision_list.visionVec.add() vision_vec.visionInfo.format = 0 vision_vec.visionInfo.width = 224 vision_vec.visionInfo.height = 224 vision_vec.visionInfo.widthAligned = 224 vision_vec.visionInfo.heightAligned = 224 vision_vec.visionData.memType = 0 vision_vec.visionData.dataStr = img_np.tobytes() vision_vec.visionData.dataSize = len(img_np) protobuf = MxProtobufIn() protobuf.key = b"appsrc0" protobuf.type = b'MxTools.MxpiVisionList' protobuf.protobuf = vision_list.SerializeToString() protobuf_vec = InProtobufVector() protobuf_vec.push_back(protobuf) return protobuf_vec(2) main方法编写main方法的编写,可以基于官方样例代码中的main方法,在那个基础上,调用我们自己的预处理函数再传值给推理业务即可streamName: 业务流的名字,需要和pipeline文件中写的保持一致6.1.6 代码运行前面的步骤完成之后,我们就可以进行代码的运行了。(1) 选择一张测试用图片我们在data目录中放入自己想要的测试图片,比如我放的这张然后在main.py中设置好图片位置全部完成后应该为这样(2) 设置运行脚本接着,我们点击上图中箭头指的地方,设置运行脚本为main.py(3) 获取运行结果点击运行获得推理结果我们可以看到,推理结果为golden retriver 金毛寻回犬上网搜搜看,发现和我们测试的狗狗图片是一样的品种6.2 C++版本开发6.2.1 新建一个项目可以参见“Python版本开发-新建一个项目”章节,这次我们选择的是C++开发空项目应该为这样6.2.2 代码目录结构根据上图的说明,我们还需要建立一个models文件用于存放模型文件,完整的目录结构应该长这样值得注意的是,这里多了一个preprocess.py文件,是用于预处理图片的,在下面“代码运行”章节会详细说明6.2.3 模型转换(或者不转换)和Python版本开发一样,可以对下载到的onnx模型进行转换,也因为转换好的模型其实就是下载的模型中的om模型,所以也可以直接拿来用。6.2.4 业务代码书写(修改)(1) 将下载到的代码中,./infer/mxbase中的src代码和CMakeLists.txt文件全部移动到src目录下(2) 修改src代码①修改路径首先修改main.cpp中的文件路径再修改编译文件中的代码路径②修改业务代码因为我们下载到的代码中,推理结果只保留了推理的类别编号,并且需要传入测试图片所在的父目录。而我们想要让它测试一张图片,并且将推理结果输出类别名称,所以需要对main.cpp和Resnet18Classify.cpp中部分代码进行修改main.cpp主要修改传入图片的方法,像上图中一样,改为传单张图片Resnet18Classify.cpp主要修改一处,将结果储存到文本文件中的方法,修改为打印输出ShowResult函数(记得在.h头文件中也添上这个方法)APP_ERROR Resnet18Classify::ShowResult(const std::string &imgPath, std::vector> \ &BatchClsInfos) { uint32_t batchIndex = 0; std::string fileName = imgPath.substr(imgPath.find_last_of("/") + 1); for (const auto &clsInfos : BatchClsInfos) { std::string resultStr; for (const auto &clsInfo : clsInfos) { resultStr += std::to_string(clsInfo.classId) + "," + clsInfo.className + "," + "confidence: " + std::to_string(clsInfo.confidence) + ";"; } LogInfo << fileName << "->Result: " << resultStr; batchIndex++; } return APP_ERR_OK;}同时,在Process函数中,将SaveResult替换成ShowResult方法调用Process函数APP_ERROR Resnet18Classify::Process(const std::string &imgPath) { std::vector inputs = {}; std::string inputIdsFile = imgPath; APP_ERROR ret = ReadInputTensor(inputIdsFile, &inputs); if (ret != APP_ERR_OK) { LogError << "Read input ids failed, ret=" << ret << "."; return ret; } std::vector outputs = {}; ret = Inference(inputs, outputs); if (ret != APP_ERR_OK) { LogError << "Inference failed, ret=" << ret << "."; return ret; } std::vector> BatchClsInfos = {}; ret = PostProcess(outputs, BatchClsInfos); if (ret != APP_ERR_OK) { LogError << "PostProcess failed, ret=" << ret << "."; return ret; } ret = ShowResult(imgPath, BatchClsInfos); if (ret != APP_ERR_OK) { LogError << "Show result failed, ret=" << ret << "."; return ret; } return APP_ERR_OK;}Init函数中,注释掉生成txt文本的代码全部完成后,就可以进行下一步了!6.2.5 项目编译业务代码写好之后,我们需要编译整个文件点击编译后,等待下方提示编译成功后,就可以运行代码了!编译好的文件在out目录下6.2.6 代码运行由于Resnet18用的预处理方法是PIL,C++中没有相应的图片处理方法,为了精度更高一些,我们需要稍微麻烦一下,使用python编写一个预处理方法prepreocess.py,将处理后的图片再传给C++代码运行preprocess.py文件可以在下载好的代码中 ./infer/util中找到,根据实际需求稍作修改就可以使用。因此我们先准备一张测试图片,比如下面这张,命名为test.jpg①:先通过preprocess.py预处理生成test.bin②:运行项目先配置运行命令点击运行7 可参考的代码我已经将自己写好的项目上传到了GitHub上,有需要可以参考Python版SDK应用开发:cid:link_12C++版SDK应用开发:cid:link_118 FAQ模型运行报错?在模型转换的时候,是否注意了选择FP32? 默认状态下是FP16的方式进行转换。或者也可以直接将下载到的模型中的om模型文件直接拿来用如果想换个数据集怎么办?可以参考modelzoo中,下载ResNet18模型的地方的说明。可以通过ModelArts训练快速进行迁移学习。Python找不到模型路径?注意在pipeline流程编排中,模型路径若使用的是相对路径,则是相对main.py文件的位置的相对路径,而不是相对于pipeline文件的相对路径。因此注意根据自己的main.py文件位置修改模型的路径C++找不到模型路径?检查自己此时代码中的模型路径是否和已经编译好的代码路径一致,C++已经编译完成后再修改代码,则需要重新编译才能运行修改后结果。No Python interpreter configured for the module?SDK版本获取失败?注意这两个地方要选子路径,选择父路径会找不到版本号9 结语MindStudio官方文档非常详细,不一而足。所以在一开始查看的时候难免会有种觉得东西太多,不知道从哪里下手的感觉。但随着开发过程的推进,逐渐发现官方文档才是开发者最应该参考的内容。此外,遇到问题时,也可以在MindStudio 昇腾社区论坛中得到许多启发,相信大家在自己动手的过程中也能体会到这一点。Now, it's time to get your hands dirty!
  • [使用说明] CodeArts IDE下载激活
    1.注册成为华为云账户(如果您已经是华为云用户可跳过此步骤)2.登陆华为云并下载CodeArts3.安装CodeArts开始安装CodeArts可能会被操作系统拦截,遇到如下提示:点击更多信息,然后点击'运行'按钮即可继续安装。4. 登录激活首次打开CodeArts会提示登陆激活,使用华为云账号即可登陆激活。注1:CodeArts暂不支持开放下载试用,我们会根据已试用用户的反馈情况来择机给申请的候选用户提供试用机会。注2:如果不登录激活CodeArts客户端,相关源代码管理、华为云API功能将不能使用。前往>>>开始使用Codearts
  • [生态对接] spark提交yarn idea执行正常,提交yarn报错找不到主类
    【功能模块】spark 代码,rdd提交时报错【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [其他] 使用MindStudio开发Ascend算子
    背景介绍MindStudio是一套基于IntelliJ框架的开发工具链平台,提供了应用开发、调试、模型转换功能,同时还提供了网络移植、优化和分析功能,为用户开发应用程序带来了极大的便利。MindStudio提供了基于TBE和AI CPU的算子编程开发的集成开发环境,让不同平台下的算子移植更加便捷,适配昇腾AI处理器的速度更快。ModelArts集成了基于MindStudio镜像的Notebook实例,方便用户通过ModelArts平台使用MindStudio镜像进行算子开发。想了解更多关于MindStudio相关内容,请参见MindStudio资料。前提条件已经创建基于MindStudio引擎的Notebook实例,并设置允许远程访问的白名单IP地址。且该Notebook实例状态必须为“运行中”。具体操作参考创建Notebook实例。图1 创建基于MindStudio引擎的Notebook实例在Notebook实例详情页面获取开发环境IP地址(例如:dev-modelarts-cnnorth4.huaweicloud.com)和端口号。图2 Notebook实例详情页面准备好密钥对。密钥对在用户第一次创建时,自动下载,之后使用相同的密钥时不会再有下载界面(用户一定要保存好),或者每次都使用新的密钥对。创建新的密钥对操作入口在创建Notebook实例页面中可以找到。在本地使用MobaXterm连接并打开MindStudio环境在本地使用MobaXterm远程连接MindStudio开发环境。下载并安装MobaXterm软件,下载地址MobaXterm。对MobaXterm软件版本不做要求。打开MobaXterm,单击“Sessions ”,在Session settings窗口设置SSH连接,单击“OK”,连接到Notebook实例环境中。图3 在MobaXterm中设置SSH连接Remote host:云上Notebook实例的IP地址,即在Notebook实例详情页获取的地址。例如:dev-modelarts-cnnorth4.huaweicloud.comPort:云上Notebook实例的端口,即在Notebook实例详情页获取的端口号。Specify username:固定为ma-userUse private key:在创建Notebook实例时创建并保存的密钥对文件。说明:如果使用MobaXterm远程连接Notebook失败,有可能是Notebook状态不是在“运行中”,或者允许远程访问的IP地址配置问题。在MobaXterm中连接到Notebook实例后,执行如下命令打开MindStudio,弹出UI界面即为打开MindStudio开发环境镜像成功。sh MindStudio/bin/MindStudio.sh图4 连接到Notebook实例图5 MindStudio UI界面在图5的窗口中保持默认配置,单击“OK”,进入下一步。单击“CANN-Toolkit Path”右侧的,选择最新版本的“ascend-toolkit”,本示例中为“/home/ma-user/Ascend/ascend-toolkit/5.0.2.1”。“ascend-toolkit”持续在升级更新,版本号以实际界面为准。图6 选择Ascend Toolkit Path单击“Finish”。进入MindStudio工程创建页面,单击新建工程,创建一个新工程。图7 选择Ascend Toolkit Path在创建Ascend Operator工程页面,选择工程存放路径为“/home/ma-user/work”目录。图8 创建Ascend Operator工程注意:创建工程时,建议选择“/home/ma-user/work”目录存放工程文件。“/home/ma-user/work”目录为持久化目录,Notebook实例停止后该目录下的内容不会丢失。单击Next,进入算子模板配置界面,参考创建算子工程,完成算子信息配置。选择保存目录为“/home/ma-user/work”目,单击“Save”。图9 保存文件单击“Finish”,完成算子工程创建。图10 创建完成算子工程算子开发之前,开发者需要参考设置Python库章节设置算子工程依赖Python库。创建MindStudio算子更多操作介绍,请参见MindStudio官方资料。停止Notebook实例前备份文件Notebook实例停止时,后端对应的容器环境会被删除,只有“/home/ma-user/work”目录下的内容会持久化保存,其他目录下的修改都会丢失。备份方法可以在停止Notebook实例前手工拷贝文件到/home/ma-user/work目录下。需要拷贝的目录内容包括:/home/ma-user/ AscendProjects目录下的自建工程/home/ma-user/modelzoo/目录下的模型转换后的om文件、配置文件、评估报告/home/ma-user/.mindstudio目录下的ssh配置其他用户自己修改的内容当Notebook实例再次启动时,用户将手工备份的目录内容拷贝回原始目录后即可正常继续使用。
  • [技术干货] 第二讲:鲲鹏代码迁移工具基础知识读书笔记
    新增功能&功能变化介绍交付特性   (特性&价值描述)T10语言迁移优化:支持go语言源码分析. Fortran语言迁移增强.C/C++语言源码迁移增强·支持Python/Java/Scala解释型语言的扫描分析内存一致性:扩展语言支持场景,对关键算法进行改进 ·增加自动修复功能 ·支持下载静态检查工具产生的BC文件 ·支持自动生成目标工程的中间文件软件迁移评估:Jar、War包扫描提示优化,识别鲲鹏平台已经支持的依赖,在报告中给出提示;专项软件迁移:·扩充“一键式软件迁移”支持的软件范围:增加HPC场景5款软件的过移文持;支持Top16款操作系统: 新增支持openEuler 20.03(LTS-SP1) 、openEuler 20.03 (LTS-uoS Server 20 Euler (1000).BC- Linux 7.6、BC- Linux 7.7和普华(iSoft)5.1六款操作系统运行环境和目标操作系统;源码迁移识别C/C+/Fortran/汇编源代码,提供修改建议;Make、CMake、Automake编译选项、编译宏的解析及迁移建议支持100%Intrinsic函数转换(6000+个),包括MMX 、SSE及AVX Intrinsic等支持更多的Fortran内联函数和诰法特性以及编译选项的识别支持Go语言迁移,对go程序使用cgo编译部分中的编译选项、宏定义提供兼容性检查,给出修改建议支持python、Java、Scala语言,对程序中的动态链接库提供兼容性检查,给出修改建议新增支持openEuler、BC_Linux等六款主流操作系统C/C++x86Intrinsic函数实现了一键式自动迁移;平台相关宏扫描准确率和覆盖率提升;构建文件编译选项、宏定义识别率提升。FortranFortran内联函数识别(增加xx条),增加Fortran语法特性解析,整体准确率提升70%;构建文件中针对Fortran语言中所使用编译选项的识别率和准确率达到100%。Go对编译选项、宏定义、依赖库提供兼容性检查,一键下载替换。Python/Java/Scala识别源码中的加载动态库的函数;识别依赖库文件,进行兼容性检查,一键下载替换。
  • [技术干货] 第二讲:鲲鹏代码迁移工具基础知识
    一.代码迁移工具是什么       处理器所支持的指令集不同,意味着开发者可能需要对代码进行跨!平台的迁移。通常,代码迁移是件复杂又繁琐的工作,需要花费开发者大量精力对软件包、源代码、依赖库文件进行人工分析、检查和识别,手动修正不同指令集之间的相关差异,这些差异主要涉及语法、指令、函数和库文件支持情况。为了解决用户代码可迁移性人工排查困难、移植经验欠缺、反复依赖编译调错定位等,投入工作量大,整体效率低的问题,我们推出Kunpeng PortingAdvisor鲲鹏代码迁移工具。        鲲鹏代码迁移工具是一款可以简化应用迁移到鲲鹏架构服务器过程的工具。主要面向鲲鹏平台的开发者、用户和第三方待迁移软件提供方开发工程师,对海量代码进行快速地自动化扫描和分析,提供专业的迁移指导报告。同时能够自动分析出需修改的代码内容,并指导如何修改,帮助开发者实现高效的代码迁移。同时支持原生开发代码亲和检查等能力。二.代码迁移工具功能三.功能特性代码迁移工具可以作为独立软件提供给鲲鹏生态用户安装使用,支持的功能特性如下:•当前工具支持五组功能,支持的功能特性分别如下:      •软件迁移评估            •检查用户提供的软件安装包,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。            •检查用户在x86服务器上已安装的软件,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。      •源码迁移            •检查用户C/C++/汇编/Fortran代码软件构建工程文件,并指导用户如何迁移该文件。            •检查用户C/C++/汇编/Fortran/python/Java/Scala/Go软件构建工程文件使用的链接库,并提供可迁移性信息。            •检查用户C/C++/汇编/Fortran软件源码,并指导用户如何迁移源文件。      •软件包重构,分析用户x86软件包构成,重构为适用于鲲鹏平台的软件包。      •专项软件迁移,基于我们丰富的软件迁移经验,帮助用户快速迁移Web、数据库、大数据、高性能计算四大解决方案类软件。      •鲲鹏亲和分析,目前含64位运行模式检查、结构体字节对齐检查、缓存行字节对齐检查、内存一致性检查、构建亲和检查。•用户通过安全传输协议上传软件源码、软件包、二进制文件等资源到工作空间,也可以从Web页面上直接对工作目录下的文件进行删除清理或者覆盖重命名。•支持命令行方式、Web、IDE插件三种工作模式,后两种方式下支持多用户并发扫描。•特别说明:工具不支持迁移windows环境下的软件或者IOS/Mac OS平台应用至Kunpeng平台Linux环境下。四.应用场景对最常用的x86汇编指令进行识别并转换•最常用的1000+条汇编指令自动翻译。•针对受支持的嵌入式汇编指令,提供修改指导;针对完全由受支持的完整汇编指令构成的文件,支持自动转换为结果汇编文件; 支持对尚无法指导修改和转换的汇编指令的识别、提醒。五.源码迁移•识别C/C++/Fortran/汇编源代码,提供修改建议;Make、CMake、Automake编译选项、编译宏的解析及迁移建议•支持100%Intrinsic函数转换(6000+个),包括MMX、SSE及AVX Intrinsic等•支持Fortran内联函数和语法特性以及编译选项的识别•支持Go语言迁移,对go程序使用cgo编译部分中的编译选项、宏定义提供兼容性检查,给出修改建议支持python、Java、Scala语言,对程序中的动态链接库提供兼容性检查,给出修改建议软件迁移评估•识别检查x86平台软件安装包或已安装软件中使用的动态链接库、静态链接库和可执行文件,并将检查出的文件与工具内置的依赖文件列表进行比较匹配,从而为用户提供迁移建议•Jar、war包扫描增强,识别鲲鹏平台已经支持的依赖,提供更精准的依赖兼容替换建议
  • [技术干货] 第二讲:鲲鹏代码迁移工具基础知识
    一.代码迁移工具是什么       处理器所支持的指令集不同,意味着开发者可能需要对代码进行跨!平台的迁移。通常,代码迁移是件复杂又繁琐的工作,需要花费开发者大量精力对软件包、源代码、依赖库文件进行人工分析、检查和识别,手动修正不同指令集之间的相关差异,这些差异主要涉及语法、指令、函数和库文件支持情况。为了解决用户代码可迁移性人工排查困难、移植经验欠缺、反复依赖编译调错定位等,投入工作量大,整体效率低的问题,我们推出Kunpeng Porting Advisor鲲鹏代码迁移工具。        鲲鹏代码迁移工具是一款可以简化应用迁移到鲲鹏架构服务器过程的工具。主要面向鲲鹏平台的开发者、用户和第三方待迁移软件提供方开发工程师,对海量代码进行快速地自动化扫描和分析,提供专业的迁移指导报告。同时能够自动分析出需修改的代码内容,并指导如何修改,帮助开发者实现高效的代码迁移。同时支持原生开发代码亲和检查等能力。二.代码迁移工具功能三.功能特性代码迁移工具可以作为独立软件提供给鲲鹏生态用户安装使用,支持的功能特性如下:•当前工具支持五组功能,支持的功能特性分别如下:      •软件迁移评估            •检查用户提供的软件安装包,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。            •检查用户在x86服务器上已安装的软件,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。      •源码迁移            •检查用户C/C++/汇编/Fortran代码软件构建工程文件,并指导用户如何迁移该文件。            •检查用户C/C++/汇编/Fortran/python/Java/Scala/Go软件构建工程文件使用的链接库,并提供可迁移性信息。            •检查用户C/C++/汇编/Fortran软件源码,并指导用户如何迁移源文件。      •软件包重构,分析用户x86软件包构成,重构为适用于鲲鹏平台的软件包。      •专项软件迁移,基于我们丰富的软件迁移经验,帮助用户快速迁移Web、数据库、大数据、高性能计算四大解决方案类软件。      •鲲鹏亲和分析,目前含64位运行模式检查、结构体字节对齐检查、缓存行字节对齐检查、内存一致性检查、构建亲和检查。•用户通过安全传输协议上传软件源码、软件包、二进制文件等资源到工作空间,也可以从Web页面上直接对工作目录下的文件进行删除清理或者覆盖重命名。•支持命令行方式、Web、IDE插件三种工作模式,后两种方式下支持多用户并发扫描。•特别说明:工具不支持迁移windows环境下的软件或者IOS/Mac OS平台应用至Kunpeng平台Linux环境下。四.应用场景对最常用的x86汇编指令进行识别并转换•最常用的1000+条汇编指令自动翻译。•针对受支持的嵌入式汇编指令,提供修改指导;针对完全由受支持的完整汇编指令构成的文件,支持自动转换为结果汇编文件; 支持对尚无法指导修改和转换的汇编指令的识别、提醒。五.源码迁移•识别C/C++/Fortran/汇编源代码,提供修改建议;Make、CMake、Automake编译选项、编译宏的解析及迁移建议•支持100%Intrinsic函数转换(6000+个),包括MMX、SSE及AVX Intrinsic等•支持Fortran内联函数和语法特性以及编译选项的识别•支持Go语言迁移,对go程序使用cgo编译部分中的编译选项、宏定义提供兼容性检查,给出修改建议支持python、Java、Scala语言,对程序中的动态链接库提供兼容性检查,给出修改建议软件迁移评估•识别检查x86平台软件安装包或已安装软件中使用的动态链接库、静态链接库和可执行文件,并将检查出的文件与工具内置的依赖文件列表进行比较匹配,从而为用户提供迁移建议•Jar、war包扫描增强,识别鲲鹏平台已经支持的依赖,提供更精准的依赖兼容替换建议
  • [技术干货] 第二讲:鲲鹏代码迁移工具基础知识
    一.代码迁移工具是什么       处理器所支持的指令集不同,意味着开发者可能需要对代码进行跨!平台的迁移。通常,代码迁移是件复杂又繁琐的工作,需要花费开发者大量精力对软件包、源代码、依赖库文件进行人工分析、检查和识别,手动修正不同指令集之间的相关差异,这些差异主要涉及语法、指令、函数和库文件支持情况。为了解决用户代码可迁移性人工排查困难、移植经验欠缺、反复依赖编译调错定位等,投入工作量大,整体效率低的问题,我们推出Kunpeng Porting Advisor鲲鹏代码迁移工具。        鲲鹏代码迁移工具是一款可以简化应用迁移到鲲鹏架构服务器过程的工具。主要面向鲲鹏平台的开发者、用户和第三方待迁移软件提供方开发工程师,对海量代码进行快速地自动化扫描和分析,提供专业的迁移指导报告。同时能够自动分析出需修改的代码内容,并指导如何修改,帮助开发者实现高效的代码迁移。同时支持原生开发代码亲和检查等能力。二.代码迁移工具功能三.功能特性代码迁移工具可以作为独立软件提供给鲲鹏生态用户安装使用,支持的功能特性如下:•当前工具支持五组功能,支持的功能特性分别如下:      •软件迁移评估            •检查用户提供的软件安装包,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。            •检查用户在x86服务器上已安装的软件,识别依赖关系,并提供鲲鹏兼容版本的so依赖库对应rpm的包OS发行版官方下载链接。      •源码迁移            •检查用户C/C++/汇编/Fortran代码软件构建工程文件,并指导用户如何迁移该文件。            •检查用户C/C++/汇编/Fortran/python/Java/Scala/Go软件构建工程文件使用的链接库,并提供可迁移性信息。            •检查用户C/C++/汇编/Fortran软件源码,并指导用户如何迁移源文件。      •软件包重构,分析用户x86软件包构成,重构为适用于鲲鹏平台的软件包。      •专项软件迁移,基于我们丰富的软件迁移经验,帮助用户快速迁移Web、数据库、大数据、高性能计算四大解决方案类软件。      •鲲鹏亲和分析,目前含64位运行模式检查、结构体字节对齐检查、缓存行字节对齐检查、内存一致性检查、构建亲和检查。•用户通过安全传输协议上传软件源码、软件包、二进制文件等资源到工作空间,也可以从Web页面上直接对工作目录下的文件进行删除清理或者覆盖重命名。•支持命令行方式、Web、IDE插件三种工作模式,后两种方式下支持多用户并发扫描。•特别说明:工具不支持迁移windows环境下的软件或者IOS/Mac OS平台应用至Kunpeng平台Linux环境下。四.应用场景对最常用的x86汇编指令进行识别并转换•最常用的1000+条汇编指令自动翻译。•针对受支持的嵌入式汇编指令,提供修改指导;针对完全由受支持的完整汇编指令构成的文件,支持自动转换为结果汇编文件; 支持对尚无法指导修改和转换的汇编指令的识别、提醒。五.源码迁移•识别C/C++/Fortran/汇编源代码,提供修改建议;Make、CMake、Automake编译选项、编译宏的解析及迁移建议•支持100%Intrinsic函数转换(6000+个),包括MMX、SSE及AVX Intrinsic等•支持Fortran内联函数和语法特性以及编译选项的识别•支持Go语言迁移,对go程序使用cgo编译部分中的编译选项、宏定义提供兼容性检查,给出修改建议支持python、Java、Scala语言,对程序中的动态链接库提供兼容性检查,给出修改建议软件迁移评估•识别检查x86平台软件安装包或已安装软件中使用的动态链接库、静态链接库和可执行文件,并将检查出的文件与工具内置的依赖文件列表进行比较匹配,从而为用户提供迁移建议•Jar、war包扫描增强,识别鲲鹏平台已经支持的依赖,提供更精准的依赖兼容替换建议
  • [优秀实践] 鲲鹏众智性能分析工具IntelliJ插件实现
    很荣幸参加《鲲鹏性能分析工具IntelliJ插件实现》项目,我们的项目主要是做Inellij插件开发实现性能分析工具功能。性能分析插件安装卸载等功能可以通过密码认证或密钥认证,下面记录一下通过密钥认证连接的方式①首先打开本地cmd②执行ssh-keygen -m PEM -t rsa -b 2048命令生成公私钥对,生成的公私钥默认保存在C:\Users\username/.ssh目录,id_rsa为私钥,id_rsa.pub为公钥③登录服务器并上传本地生成的公钥文件;普通用户上传至/home/用户名/.ssh目录下;root上传至/root/.ssh目录下上传后将公钥文件id_rsa.pub名字改为authorized_keys④使用chmod 600 authorized_keys命令修改authorized_keys文件权限⑤使用cat /etc/ssh/sshd_config命令查看服务器ssh配置文件。检查如下开关为yes,如果不是,改为yes后保存配置文件,并重启sshd服务:PubkeyAuthentication yesRSAAuthentication yes以上步骤成功后,进入登录页面选择密钥认证,导入本地私钥,其它输入框内容填写正确,点击检测连接,检测成功后就可以开始安装部署了。
  • [技术干货] 使用PyCharm ToolKit工具快速实现模型训练和部署
    这里提供了使用MXNet实现手写数字图像识别应用的示例,帮助您使用ModelArts提供的PyCharm ToolKit工具,在本地快速完成模型的训练和部署。更多关于PyCharm ToolKit工具的描述,请参见《工具指南》。MNIST是一个手写体数字识别数据集,常被用作深度学习的入门样例。本示例将针对MNIST数据集,使用MXNet原生接口编写的模型训练脚本(ModelArts默认提供),在ModelArts PyCharm ToolKit中完成模型训练,并将此模型部署为在线服务。部署完成后,用户可通过在线服务识别输入图片中的数字。开始使用样例前,请仔细阅读准备工作罗列的要求,提前完成准备工作。本示例模型构建的步骤如下所示:准备工作本地已安装PyCharm 2019.2或以上版本,推荐Windows版本,Community或Professional均可,请单击PyCharm工具下载地址获取工具并在本地完成安装。使用PyCharm ToolKit远程连接Notebook开发环境,仅限PyCharm专业版。使用PyCharm ToolKit提交训练作业,社区版和专业版都支持,但仅限于提交旧版训练作业,暂不支持新版训练作业。已注册华为云帐号,且在使用ModelArts前检查帐号状态,帐号不能处于欠费或冻结状态。在ModelArts管理控制台中,当前帐号已完成访问授权的配置。如果已完成,此操作可跳过。如未完成,请参考使用委托授权。针对之前使用访问密钥授权的用户,建议清空授权,然后使用委托进行授权。已在OBS服务中创建桶和文件夹,用于存放样例数据集以及模型。如下示例中,请创建命名为“test-modelarts”的桶,并创建如表1所示的文件夹。创建OBS桶和文件夹的操作指导请参见创建桶和新建文件夹。确保您使用的OBS目录与ModelArts在同一区域。表1 文件夹列表文件夹名称用途“dataset-mnist”用于存储数据集。“mnist-output”用于存储训练输出的模型和日志文件。步骤1:安装PyCharm ToolKit,并添加访问密钥获取PyCharm ToolKit工具安装包,单击ToolKit工具的下载地址,获得工具包。打开本地PyCharm工具。在PyCharm工具中,选择菜单栏的“File > Settings”,弹出“Settings”对话框。在“Settings”对话框中,首先单击左侧导航栏中的“Plugins”,然后单击右侧的设置图标,选择“Install Plugin from Disk”,弹出文件选择对话框。图1 选择从本地安装插件在弹出的对话框中,从本地目录选择ToolKit的工具zip包,然后单击“OK”。图2 选择插件文件单击“Restart IDE”重启PyCharm。在弹出的确认对话框中,单击“Restart”开始重启。图3 重启PyCharm重启成功后,打开一个Project,当PyCharm工具栏出现“ModelArts”页签,表示ToolKit工具已安装完成。图4 安装成功单击工具栏上的“ModelArts > Edit Credential”,在PyCharm中添加访问密钥。获取此帐号的访问密钥(“AK/SK”),详细操作请参见获取访问密钥。PyCharm ToolKit安装后,在ToolKit工具中添加访问密钥,详细操作请参见使用访问秘钥登录。图5 填写区域和访问密钥查看认证结果。在右下角Event Log区域中,当提示如下类似信息时,表示访问密钥添加成功。16:01 Validate Credential Success: The HUAWEI CLOUD credential is valid.步骤2:准备数据ModelArts在公共OBS桶中提供了MNIST数据集,命名为“Mnist-Data-Set”,因此,本文的操作示例使用此数据集进行模型构建。您需要执行如下操作,将数据集上传至您的OBS目录下,即准备工作中您创建的OBS目录“test-modelarts/dataset-mnist”。单击数据集下载链接,将“Mnist-Data-Set”数据集下载至本地。在本地,将“Mnist-Data-Set.zip”压缩包解压。例如,解压至本地“Mnist-Data-Set”文件夹下。参考上传文件,使用批量上传方式将“Mnist-Data-Set”文件夹下的所有文件上传至“test-modelarts/dataset-mnist”OBS路径下。“Mnist-Data-Set”数据集包含的内容如下所示,其中“.gz”为对应的压缩包。“t10k-images-idx3-ubyte”:验证集,共包含10000个样本。“t10k-images-idx3-ubyte.gz”:验证集的压缩包文件。“t10k-labels-idx1-ubyte”:验证集标签,共包含10000个样本的类别标签。“t10k-labels-idx1-ubyte.gz”:验证集标签的压缩包文件。“train-images-idx3-ubyte”:训练集,共包含60000个样本。“train-images-idx3-ubyte.gz”:训练集的压缩包文件。“train-labels-idx1-ubyte”:训练集标签,共包含60000个样本的类别标签。“train-labels-idx1-ubyte.gz”:训练集标签的压缩包文件。步骤3:编写训练代码ModelArts提供了本示例需要使用的训练代码,请获取并在PyCharm工程中打开。在gitee的ModelArts-Lab工程中,单击“克隆/下载”,然后单击“下载ZIP”,下载工程。下载完成后,解压缩“ModelArts-Lab-master.zip”文件,然后在“\ModelArts-Lab-master\official_examples\Using_MXNet_to_Create_a_MNIST_Dataset_Recognition_Application\codes”目录中获取到训练代码文件“train_mnist.py”。打开PyCharm工具,单击“File > New Project”创建新工程, 在工程目录下创建“src”文件夹,并将训练代码文件“train_mnist.py”拷贝到“src”文件夹下。图6 将训练代码拷贝至src目录步骤4:训练模型数据和代码准备完成后,您可以创建一个训练作业,选用MXNet引擎,基于本地的train_mnist.py训练脚本,并最终生成一个可用的模型。本示例已提供编码完成的脚本(基于MXNet引擎的原生接口),如果使用自行编写的代码,请使用ModelArts支持的引擎类型及其对应版本的接口,并满足其要求。在PyCharm工具栏中,选择“ModelArts > Edit Training Job Configuration”。在弹出的对话框中,按照如下示例配置训练参数。“Job Name”:自动生成,首次提交训练作业时,该名称也可以自己指定。“AI Engine”:选择“MXNet”,版本为“MXNet-1.2.1-python3.6”。“Algorithm Source”:此处选择“Frequently-used”,代表常用框架。Custom表示自定义镜像,基于自定义镜像的训练作业案例请参见使用自定义镜像创建训练作业。“Specifications”:选择GPU规格。“OBS Path”:填写准备工作中创建的输出路径,用于存储训练输出模型和日志文件。“Data Path in OBS”:填写步骤2:准备数据中数据上传的OBS目录。此处需完整OBS路径,需包含OBS桶名称。此示例填写的值如图所示,请务必修改为您自己的OBS桶及路径。“Boot File Path”:选择本地的训练脚本“train_mnist.py”。“Code Directory”:选择启动脚本所在“src”目录。“Running Parameters”:是训练脚本所需要的输入参数,本样例中没有参数,无需填写。填写完成后,单击“Apply and Run”提交训练作业到云上ModelArts。说明:由于MNIST数据集数据较多,为提升训练效率,操作示例选择GPU训练。但是,GPU的费用高于CPU,请根据实际情况选择可用的资源池。图7 配置训练作业训练作业提交后,可在下方查看训练日志。当训练日志中出现“Current training job status: Successful”类似信息时,表示训练作业运行成功。图8 查看训练日志其中, “ModelArts Event Log”栏为工具打印的日志,“ModelArts Training Log”为训练脚本代码打印的日志。从日志可以看到,工具会先将本地工程的代码自动上传至云上OBS,然后自动提交一个训练作业。作业提交成功后,工具会实时从云上的训练环境获取日志并展示在“ModelArts Training Log”窗口,直至作业运行结束。在PyCharm的左边菜单栏,单击“ModelArts Explorer”,选择刚才提交的作业,双击版本号“V0001”,可以查看作业详情。图9 选择对应的训练作业及版本图10 训练作业详情步骤5:编写推理代码和配置文件,并上传至模型所在路径ModelArts提供了本示例需要使用的推理代码“customize_service.py”和配置文件“config.json”,文件路径和下载的git工程中的训练代码在同一目录。此推理代码和配置文件是ModelArts提供的示例。在步骤4:训练模型中,训练作业生成的模型存储在“test-modelarts/mnist-output/MA-mnist-11-30-16/output/V0001”路径下(其中MA-mnist-11-30-16是Job Name,如果配置时填写了自定义Job Name,则路径中就是自定义的Job Name),且系统将自动生成“model”文件夹,模型相关的文件存储在此目录下。将获取的“customize_service.py”和“config.json”文件,上传至OBS的“model”文件夹下。说明:如果训练作业运行多次,将在“训练输出位置”生成不同的版本,即“mnist-output”目录下将生成多种版本的目录,如“V0001”、“V0002”,请基于训练作业的版本,将文件上传至对应版本下的“model”文件夹内。前往OBS管理控制台,找到“test-modelarts”桶,然后进入“test-modelarts/mnist-output/MA-mnist-11-30-16/output/V001/model”路径,执行“上传对象”的操作。OBS的上传操作指导,请参见上传文件。步骤6:部署在线服务训练完成的模型还是存储在OBS路径中,您可以将此模型导入到ModelArts中并部署为在线服务。在训练作业版本号上单击鼠标右键,选择“Deploy to Service”。图11 部署为在线服务在弹出的对话框中,按照如下说明填写部署为在线服务的参数。“Service Name”:自动生成,也可以自定义。“Auto Stop”:勾选Auto Stop,表示启动自动停止功能,服务会在指定时间后自动停止。“Model Path”:自动填写,无需自己配置。与您选择的训练作业及其版本一致。“Environment Variables”:填写运行参数,设置为“input_data_name=images;input_data_shape=0,1,28,28;output_data_shape=0,10”。“input_data_name”:参数值必须是images。针对自己开发训练脚本的场景,此参数是必须设置的。您可以在导入模型时设置参数,也可以写到推理代码中。“input_data_shape”:代表NCHW。本示例的数值为“0,1,28,28”,表示设置了输入图片的规则,其中,输入预测图片大小必须是“28px*28px”。“output_data_shape”:置信度。本示例指定范围为“0~10”。表示输出结果会显示“0~9”中10个类别,属于每一个类别的概率。信息填写完成后,单击“OK”,开始服务部署。图12 部署为在线服务可以在最下方的日志栏查看服务部署进度。图13 查看部署进度模型部署上线需要花费一些时间,请耐心等待几分钟。当出现类似“Service status is running”信息时,表示服务部署成功。服务部署成功后,将展示在线服务的链接,单击链接可以进入ModelArts控制台部署上线 >在线服务的界面。说明:首次进入需要输入华为云帐号密码登录。图14 完成部署步骤7:测试服务在线服务部署成功后,您可以进入在线服务,发起预测请求进行测试。部署成功后,单击提供的链接进入ModelArts控制台的“部署上线 >在线服务”界面。找到刚部署的在线服务,单击服务名称,进入在线服务详情页面中,单击“预测”页签,进入预测页面。在“选择预测图片文件”右侧,单击“上传”按钮,上传一张黑底白字的图片,然后单击“预测”。预测完成后,预测结果显示区域将展示预测结果,根据预测结果内容,可识别出此图片的数字是“2”的概率为“1”。说明:由于推理代码和配置文件中已指定图片要求,用于预测的图片,大小必须为“28px*28px”,且图片必须是黑底白字。建议不要使用数据中自带的图片,可以使用Windows自带的画图工具绘制一张。图15 预测结果步骤8:清除相应资源,避免产生费用为避免产生不必要的费用,在完成试用后,建议您删除相关资源,如在线服务、训练作业及其OBS目录。进入ModelArts管理控制台,删除在线服务:在“在线服务”页面,单击操作列的“更多>删除”。在PyCharm菜单栏中,选择“ModelArts > Stop Training Job”停止此训练作业。或者进入ModelArts管理控制台,在“训练作业旧版”页面,单击操作列的“删除”,删除此训练作业。进入OBS管理控制台,删除数据准备阶段创建的OBS桶。先逐个删除桶内文件夹和文件,再执行删除桶的操作。
  • [经验分享] 使用MindStudio进行Pytorch模型迁移以及推理
    1. MindStudio环境搭建    MindStudio是一套基于IntelliJ框架的开发工具链平台,提供了应用开发,调试,Profiling工具,模型转换,模型可视化等功能,以及对开发者来说至关重要的精度对比,自定义算子等重要功能,同时还提供了网络移植,优化和分析功能,方便用户开发应用程序。    按照平台安装教程安装MindStudio即可完成本部分的环境搭建。2.模型简介    本次实验我们的目标是在MindStudio上使用ResNet进行图像分类任务。ResNet曾在ILSVRC2015比赛中获得冠军,在图像分类上具有很大的潜力。ResNet的主要思想是在网络中增加了直连通道,使得原始输入信息能够直接传入到后面的层中,ResNet的结构如下图所示。ResNet会将残差块串联,形成多层网络。一般常见的ResNet根据层数的大小有ResNet-18, ResNet-34, ResNet-50, ResNet-101等。3. 创建推理工程    打开MindStudio,点击New Project,进入新建工程界面。选择Ascend App。填入项目名resNext101_32x8d。首次新建训练工程时,需要配置CANN的版本。点击Change。点击 + 配置远程连接,然后根据选项填入自己服务器的IP地址、端口号、用户名和密码等。配置Remote CANN location。该参数需要填入ascend-toolkit在服务器上的路径地址。在这里,我们的toolkit路径如下/usr/local/Ascend/ascend-toolkit/5.1.RC1。点击finishing进行配置。点击Next,选择Pytorch Project。点击Finish,完成工程创建,进入工程主界面。4. 将环境部署到远端Mind Studio可以支持实时的将本地文件夹内容同步到服务器,可以达到像自己电脑上执行模型推理一样的效果,此过程需要两个步骤。点击File->Settings->Tools,即可看到两个设置的入口。配置ssh                首先点击SSH Configuration,再点击 + 配置远程连接,然后根据选项填入自己的服务器ip地址,端口号,用户名和密码。部署本地文件夹        相当于将远端服务器的路径与本地文件夹形成一个对应关系。Deployment配置能够更精准地连接远程服务,他需要选择一个SSH连接来定位远程主机,然后设置本地与远程项目目录的对应关系。首先选择连接哪SSH服务,然后测试连接是否可用。下一步,设置项目目录映射关系,点击Mappings,然后选择本地的项目目录和远程的项目目录(最好提前创建文件夹),接下来跑代码的时候MindStudio会保证这两个目录文件的同步。配置好Mappings之后,建议配置Excluded Paths, 因为MindStudio默认行为会把Mappings目录的文件保持完全相同,这意味着只存在于远端服务器的数据集文件会被删除(如果本地没有数据集)。再次,我配置了几个需要排除的文件夹目录。5. 配置Python环境    点击File -> Project Structures -> SDKs可以看到如图所示的界面。点击+号,可以新增python SDK和JDK。    点击Add Python SDK后,将弹出下图所示界面,点击左侧的SSH Interpreter,如下图所示,首先选择使用哪一个Deployment,这是刚刚我们配置过的。然后选择python解释器的路径。图中的路径是MindStudio自动检测出来的,但一般需要我们找自己的Python环境安装目录。然后点击Project,选择刚才添加到MindStudio中的Python解释器,将其作为本项目所使用的解释器。6. 数据预处理   首先执行数据预处理脚本image_torch_preprocess.py, 将原生的图片数据转换为bin格式的输入文件。第一个参数为原始数据集(.jpeg)所在路径,第二个参数为输出的二进制文件(.bin)所在的路径。每个图片对应生成一个二进制文件。在预处理获得bin文件之后,再执行get_info.py提取输入信息。7. 模型转换    模型转换主要分为两步,第一步是将原有的pth模型转换为通用的onnx模型,第二步是将onnx模型转换为npu适用的om模型。    首先调用python脚本将pth模型转换为onnx模型。再使用ATC工具将onnx模型导出为om模型。MindStudio提供了atc工具的窗口化应用,他会根据用户选择自动生成atc指令。Model Converter的入口如图所示。选择onnx路径,模型输出名称,目标设备,输入格式和batchsize等信息。本实验需要跑到不同的batchsize,这里只需要修改shape参数即可对应生成不同batch size的om模型。MindStudio自动生成如下atc指令,用户可以在此做最后的校验,点击Finish即可开始进行模型转换。转换成功得到结果如下:8. 离线推理    使用benchmark工具进行离线推理,可以创建如图所示的应用:点击 + 号,再点击Ascend App,按照自己的模型相关信息进行填写即可。在不同机器上执行效率对比如下表格ModelBatch Size310p310 (FPS/Card)T4 (FPS/Card)310p/310310p/T4ResNeXt1011594.884594.696254.2521.0002.340ResNeXt1014566.742674.64486.6560.8401.160ResNeXt1018937.698669.232531.9961.4011.763ResNeXt101161086.34670.3570.8671.6211.903ResNeXt101321191.32429.944543.2932.7712.193ResNeXt10164781.172427.304539.9241.8281.447最优batch32/8/161191.32669.232570.8671.7662.0879. 精度对比    推理结束之后,可以调用imagenet_acc_eval.py脚本和原有标签数据进行对比,得到top5的结果。最后的精度表现如下:top1准确率为79.3%,top5准确率为94.52%。
  • [最佳实践] 使用IntelliJ IDEA Java创建和使用DLI表
    操作场景DLI支持用户编写代码创建Spark作业来创建数据库、创建DLI表或OBS表和插入表数据等操作。本示例完整的演示通过编写java代码、使用Spark作业创建数据库、创建表和插入表数据的详细操作,帮助您在DLI上进行作业开发。约束限制不支持的场景:在SQL作业中创建了数据库(database),编写程序代码指定在该数据库下创建表。例如在DLI的SQL编辑器中的某SQL队列下,创建了数据库testdb。后续通过编写程序代码在testdb下创建表testTable,编译打包后提交的Spark Jar作业则会运行失败。不支持创建加密的DLI表,即不支持创建DLI表时设置encryption=true。例如,如下建表语句不支持:CREATE TABLE tb1(id int) using parquet options(encryption=true)支持的场景在SQL作业中创建数据库(database),表(table) , 通过SQL或Spark程序作业读取插入数据。在Spark程序作业中创建数据库(database),表(table), 通过SQL或Spark程序作业读取插入数据。环境准备在进行Spark 作业访问DLI元数据开发前,请准备以下开发环境。表1 Spark Jar作业开发环境准备项说明操作系统Windows系统,支持Windows7以上版本。安装JDKJDK使用1.8版本。安装和配置IntelliJ IDEAIntelliJ IDEA为进行应用开发的工具,版本要求使用2019.1或其他兼容版本。安装Maven开发环境的基本配置。用于项目管理,贯穿软件开发生命周期。开发流程DLI进行Spark作业访问DLI元数据开发流程参考如下:图1 Spark作业访问DLI元数据开发流程表2 开发流程说明序号阶段操作界面说明1创建DLI通用队列DLI控制台创建作业运行的DLI队列。2OBS桶文件配置OBS控制台如果是创建OBS表,则需要上传文件数据到OBS桶下。配置Spark创建表的元数据信息“spark.sql.warehouse.dir”的存储路径。3新建Maven工程,配置pom文件IntelliJ IDEA参考样例代码说明,编写程序代码创建DLI表或OBS表。4编写程序代码5调试,编译代码并导出Jar包6上传Jar包到OBS和DLIOBS控制台将生成的Spark Jar包文件上传到OBS目录下和DLI程序包中。7创建Spark Jar作业DLI控制台在DLI控制台创建Spark Jar作业并提交运行作业。8查看作业运行结果DLI控制台查看作业运行状态和作业运行日志。步骤1:创建DLI通用队列第一次提交Spark作业,需要先创建队列,例如创建名为“sparktest”的队列,队列类型选择为“通用队列”。在DLI管理控制台的左侧导航栏中,选择“队列管理”。单击“队列管理”页面右上角“购买队列”进行创建队列。创建名为“sparktest”的队列,队列类型选择为“通用队列”。创建队列详细介绍请参考创建队列。单击“立即购买”,确认配置。配置确认无误,单击“提交”完成队列创建。步骤2:OBS桶文件配置如果需要创建OBS表,则需要先上传数据到OBS桶目录下。本次演示的样例代码创建了OBS表,测试数据内容参考如下示例,创建名为的testdata.csv文件。12,Michael 27,Andy 30,Justin进入OBS管理控制台,在“桶列表”下,单击已创建的OBS桶名称,本示例桶名为“dli-test-obs01”,进入“概览”页面。单击左侧列表中的“对象”,选择“上传对象”,将testdata.csv文件上传到OBS桶根目录下。在OBS桶根目录下,单击“新建文件夹”,创建名为“warehousepath”的文件夹。该文件夹路径用来存储Spark创建表的元数据信息“spark.sql.warehouse.dir”。步骤3:新建Maven工程,配置pom依赖以下通过IntelliJ IDEA 2020.2工具操作演示。打开IntelliJ IDEA,选择“File > New > Project”。图2 新建Project选择Maven,Project SDK选择1.8,单击“Next”。定义样例工程名和配置样例工程存储路径,单击“Finish”完成工程创建。如上图所示,本示例创建Maven工程名为:SparkJarMetadata,Maven工程路径为:“D:\DLITest\SparkJarMetadata”。在pom.xml文件中添加如下配置。<dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.3.2</version> </dependency> </dependencies>图3 修改pom.xml文件在工程路径的“src > main > java”文件夹上鼠标右键,选择“New > Package”,新建Package和类文件。Package根据需要定义,本示例定义为:“com.huawei.dli.demo”,完成后回车。在包路径下新建Java Class文件,本示例定义为:DliCatalogTest。步骤4:编写代码编写DliCatalogTest程序创建数据库、DLI表和OBS表。完整的样例请参考Java样例代码,样例代码分段说明如下:导入依赖的包。import org.apache.spark.sql.SparkSession;创建SparkSession会话。创建SparkSession会话时需要指定Spark参数:"spark.sql.session.state.builder"、"spark.sql.catalog.class"和"spark.sql.extensions",按照样例配置即可。SparkSession spark = SparkSession .builder() .config("spark.sql.session.state.builder", "org.apache.spark.sql.hive.UQueryHiveACLSessionStateBuilder") .config("spark.sql.catalog.class", "org.apache.spark.sql.hive.UQueryHiveACLExternalCatalog") .config("spark.sql.extensions","org.apache.spark.sql.CarbonInternalExtensions"+","+"org.apache.spark.sql.DliSparkExtension") .appName("java_spark_demo") .getOrCreate();创建数据库。如下样例代码演示,创建名为test_sparkapp的数据库。spark.sql("create database if not exists test_sparkapp").collect();创建DLI表并插入测试数据。spark.sql("drop table if exists test_sparkapp.dli_testtable").collect(); spark.sql("create table test_sparkapp.dli_testtable(id INT, name STRING)").collect(); spark.sql("insert into test_sparkapp.dli_testtable VALUES (123,'jason')").collect(); spark.sql("insert into test_sparkapp.dli_testtable VALUES (456,'merry')").collect();创建OBS表。如下示例中的OBS路径需要根据步骤2:OBS桶文件配置中的实际数据路径修改。spark.sql("drop table if exists test_sparkapp.dli_testobstable").collect(); spark.sql("create table test_sparkapp.dli_testobstable(age INT, name STRING) using csv options (path 'obs://dli-test-obs01/testdata.csv')").collect();关闭SparkSession会话spark。spark.stop();步骤5:调试、编译代码并导出Jar包单击IntelliJ IDEA工具右侧的“Maven”,参考下图分别单击“clean”、“compile”对代码进行编译。编译成功后,单击“package”对代码进行打包。打包成功后,生成的Jar包会放到target目录下,以备后用。本示例将会生成到:“D:\DLITest\SparkJarMetadata\target”下名为“SparkJarMetadata-1.0-SNAPSHOT.jar”。步骤6:上传Jar包到OBS和DLI下登录OBS控制台,将生成的“SparkJarMetadata-1.0-SNAPSHOT.jar”Jar包文件上传到OBS路径下。将Jar包文件上传到DLI的程序包管理中,方便后续统一管理。登录DLI管理控制台,单击“数据管理 > 程序包管理”。在“程序包管理”页面,单击右上角的“创建”创建程序包。在“创建程序包”对话框,配置以下参数。包类型:选择“JAR”。OBS路径:程序包所在的OBS路径。分组设置和组名称根据情况选择设置,方便后续识别和管理程序包。图4 创建程序包单击“确定”,完成创建程序包。步骤7:创建Spark Jar作业登录DLI控制台,单击“作业管理 > Spark作业”。在“Spark作业”管理界面,单击“创建作业”。在作业创建界面,配置对应作业运行参数。具体说明如下:表3 Spark Jar作业参数填写参数名参数值所属队列选择已创建的DLI通用队列。例如当前选择步骤1:创建DLI通用队列创建的通用队列“sparktest”。作业名称(--name)自定义Spark Jar作业运行的名称。当前定义为:SparkTestMeta。应用程序选择步骤6:上传Jar包到OBS和DLI下中上传到DLI程序包。例如当前选择为:“SparkJarObs-1.0-SNAPSHOT.jar”。主类格式为:程序包名+类名。例如当前为:com.huawei.dli.demo.DliCatalogTest。Spark参数(--conf)spark.dli.metaAccess.enable=truespark.sql.warehouse.dir=obs://dli-test-obs01/warehousepath说明:spark.sql.warehouse.dir参数的OBS路径为步骤2:OBS桶文件配置中配置创建。访问元数据选择:是其他参数保持默认值即可。图5 创建Spark Jar作业单击“执行”,提交该Spark Jar作业。在Spark作业管理界面显示已提交的作业运行状态。查看作业运行结果在Spark作业管理界面显示已提交的作业运行状态。初始状态显示为“启动中”。如果作业运行成功则作业状态显示为“已成功”,通过以下操作查看创建的数据库和表。可以在DLI控制台,左侧导航栏,单击“SQL编辑器”。在“数据库”中已显示创建的数据库“test_sparkapp”。图6 查看创建的数据库双击数据库名,可以在数据库下查看已创建成功的DLI和OBS表。图7 查看表双击DLI表名dli_testtable,单击“执行”查询DLI表数据。图8 查询DLI表数据注释掉DLI表查询语句,双击OBS表名dli_testobstable,单击“执行”查询OBS表数据。图9 查询OBS表数据如果作业运行失败则作业状态显示为“已失败”,单击“操作”列“更多”下的“Driver日志”,显示当前作业运行的日志,分析报错原因。图10 查看Driver日志原因定位解决后,可以在作业“操作”列,单击“编辑”,修改作业相关参数后,单击“执行”重新运行该作业即可。后续指引如果您想通过Spark Jar作业访问其他数据源,请参考《使用Spark作业跨源访问数据源》。创建DLI表的语法请参考创建DLI表,创建OBS表的语法请参考创建OBS表。如果是通过API接口调用提交该作业请参考以下操作说明:调用创建批处理作业接口,参考以下请求参数说明。详细的API参数说明请参考《数据湖探索API参考》>《创建批处理作业》。将请求参数中的“catalog_name”参数设置为“dli”。conf 中需要增加"spark.dli.metaAccess.enable":"true"。如果需要执行DDL,则还要在conf中配置"spark.sql.warehouse.dir": "obs://bucket/warehousepath"。完整的API请求参数可以参考如下示例说明。{ "queue":"citest", "file":"SparkJarMetadata-1.0-SNAPSHOT.jar", "className":"DliCatalogTest", "conf":{"spark.sql.warehouse.dir": "obs://bucket/warehousepath", "spark.dli.metaAccess.enable":"true"}, "sc_type":"A", "executorCores":1, "numExecutors":6, "executorMemory":"4G", "driverCores":2, "driverMemory":"7G", "catalog_name": "dli" }Java样例代码本示例操作步骤采用Java进行编码,具体完整的样例代码参考如下:package com.huawei.dli.demo; import org.apache.spark.sql.SparkSession; public class DliCatalogTest { public static void main(String[] args) { SparkSession spark = SparkSession .builder() .config("spark.sql.session.state.builder", "org.apache.spark.sql.hive.UQueryHiveACLSessionStateBuilder") .config("spark.sql.catalog.class", "org.apache.spark.sql.hive.UQueryHiveACLExternalCatalog") .config("spark.sql.extensions","org.apache.spark.sql.CarbonInternalExtensions"+","+"org.apache.spark.sql.DliSparkExtension") .appName("java_spark_demo") .getOrCreate(); spark.sql("create database if not exists test_sparkapp").collect(); spark.sql("drop table if exists test_sparkapp.dli_testtable").collect(); spark.sql("create table test_sparkapp.dli_testtable(id INT, name STRING)").collect(); spark.sql("insert into test_sparkapp.dli_testtable VALUES (123,'jason')").collect(); spark.sql("insert into test_sparkapp.dli_testtable VALUES (456,'merry')").collect(); spark.sql("drop table if exists test_sparkapp.dli_testobstable").collect(); spark.sql("create table test_sparkapp.dli_testobstable(age INT, name STRING) using csv options (path 'obs://dli-test-obs01/testdata.csv')").collect(); spark.stop(); } }scala样例代码scala样例代码object DliCatalogTest { def main(args:Array[String]): Unit = { val sql = args(0) val runDdl = Try(args(1).toBoolean).getOrElse(true) System.out.println(s"sql is $sql runDdl is $runDdl") val sparkConf = new SparkConf(true) sparkConf .set("spark.sql.session.state.builder", "org.apache.spark.sql.hive.UQueryHiveACLSessionStateBuilder") .set("spark.sql.catalog.class", "org.apache.spark.sql.hive.UQueryHiveACLExternalCatalog") sparkConf.setAppName("dlicatalogtester") val spark = SparkSession.builder .config(sparkConf) .enableHiveSupport() .config("spark.sql.extensions", Seq("org.apache.spark.sql.CarbonInternalExtensions", "org.apache.spark.sql.DliSparkExtension").mkString(",")) .appName("SparkTest") .getOrCreate() System.out.println("catalog is " + spark.sessionState.catalog.toString) if (runDdl) { val df = spark.sql(sql).collect() } else { spark.sql(sql).show() } spark.close() } }Python样例代码Python样例代码#!/usr/bin/python # -*- coding: UTF-8 -*- from __future__ import print_function import sys from pyspark.sql import SparkSession if __name__ == "__main__": url = sys.argv[1] creatTbl = "CREATE TABLE test_sparkapp.dli_rds USING JDBC OPTIONS ('url'='jdbc:mysql://%s'," \ "'driver'='com.mysql.jdbc.Driver','dbtable'='test.test'," \ " 'passwdauth' = 'DatasourceRDSTest_pwd','encryption' = 'true')" % url spark = SparkSession \ .builder \ .enableHiveSupport() \ .config("spark.sql.session.state.builder","org.apache.spark.sql.hive.UQueryHiveACLSessionStateBuilder") \ .config("spark.sql.catalog.class", "org.apache.spark.sql.hive.UQueryHiveACLExternalCatalog") \ .config("spark.sql.extensions",','.join(["org.apache.spark.sql.CarbonInternalExtensions","org.apache.spark.sql.DliSparkExtension"])) \ .appName("python Spark test catalog") \ .getOrCreate() spark.sql("CREATE database if not exists test_sparkapp").collect() spark.sql("drop table if exists test_sparkapp.dli_rds").collect() spark.sql(creatTbl).collect() spark.sql("select * from test_sparkapp.dli_rds").show() spark.sql("insert into table test_sparkapp.dli_rds select 12,'aaa'").collect() spark.sql("select * from test_sparkapp.dli_rds").show() spark.sql("insert overwrite table test_sparkapp.dli_rds select 1111,'asasasa'").collect() spark.sql("select * from test_sparkapp.dli_rds").show() spark.sql("drop table test_sparkapp.dli_rds").collect() spark.stop()
  • [最佳实践] 使用IntelliJ IDEA Java创建和使用Spark UDTF
    操作场景DLI支持用户使用Hive UDTF(User-Defined Table-Generating Functions)自定义表值函数,UDTF用于解决一进多出业务场景,即其输入与输出是一对多的关系,读入一行数据,输出多个值。约束限制在DLI Console上执行UDTF相关操作时,需要使用自建的SQL队列。跨账号使用UDTF时,除了创建UDTF函数的用户,其他用户如果需要使用时,需要先进行授权才可使用对应的UDTF函数。授权操作参考如下:登录DLI管理控制台,选择“ 数据管理 > 程序包管理”页面,选择对应的UDTF Jar包,单击“操作”列中的“权限管理”,进入权限管理页面,单击右上角“授权”,勾选对应权限。自定义函数中引用static类或接口时,必须要加上“try catch”异常捕获,否则可能会造成包冲突,导致函数功能异常。环境准备在进行UDTF开发前,请准备以下开发环境。表1 UDTF开发环境准备项说明操作系统Windows系统,支持Windows7以上版本。安装JDKJDK使用1.8版本。安装和配置IntelliJ IDEAIntelliJ IDEA为进行应用开发的工具,版本要求使用2019.1或其他兼容版本。安装Maven开发环境的基本配置。用于项目管理,贯穿软件开发生命周期。开发流程DLI下UDTF函数开发流程参考如下:图1 UDTF开发流程表2 开发流程说明序号阶段操作界面说明1新建Maven工程,配置pom文件IntelliJ IDEA参考操作步骤说明,编写UDTF函数代码。2编写UDTF函数代码3调试,编译代码并导出Jar包4上传Jar包到OBSOBS控制台将生成的UDTF函数Jar包文件上传到OBS目录下。5创建DLI的UDTF函数DLI控制台在DLI控制台的SQL作业管理界面创建使用的UDTF函数。6验证和使用DLI的UDTF函数DLI控制台在DLI作业中使用创建的UDTF函数。操作步骤新建Maven工程,配置pom文件。以下通过IntelliJ IDEA 2020.2工具操作演示。打开IntelliJ IDEA,选择“File > New > Project”。图2 新建Project选择Maven,Project SDK选择1.8,单击“Next”。定义样例工程名和配置样例工程存储路径,单击“Finish”完成工程创建。在pom.xml文件中添加如下配置。<dependencies> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-exec</artifactId> <version>1.2.1</version> </dependency> </dependencies>图3 pom文件中添加配置在工程路径的“src > main > java”文件夹上鼠标右键,选择“New > Package”,新建Package和类文件。Package根据需要定义,本示例定义为:“com.huawei.demo”,完成后回车。在包路径下新建Java Class文件,本示例定义为:UDTFSplit。编写UDTF函数代码。完整样例代码请参考样例代码。UDTF的类需要继承“org.apache.hadoop.hive.ql.udf.generic.GenericUDTF”,实现initialize,process,close三个方法。UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息,如,返回个数,类型等。初始化完成后,会调用process方法,真正处理在process函数中,在process中,每一次forward()调用产生一行。如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward()函数。public void process(Object[] args) throws HiveException { // TODO Auto-generated method stub if(args.length == 0){ return; } String input = args[0].toString(); if(StringUtils.isEmpty(input)){ return; } String[] test = input.split(";"); for (int i = 0; i < test.length; i++) { try { String[] result = test[i].split(":"); forward(result); } catch (Exception e) { continue; } } }最后调用close方法,对需要清理的方法进行清理。编写调试完成代码后,通过IntelliJ IDEA工具编译代码并导出Jar包。单击工具右侧的“Maven”,参考下图分别单击“clean”、“compile”对代码进行编译。编译成功后,单击“package”对代码进行打包。图4 编译打包打包成功后,生成的Jar包会放到target目录下,以备后用。本示例将会生成到:“D:\MyUDTF\target”下名为“MyUDTF-1.0-SNAPSHOT.jar”。登录OBS控制台,将生成的Jar包文件上传到OBS路径下。说明:Jar包文件上传的OBS桶所在的区域需与DLI的队列区域相同,不可跨区域执行操作。(可选)可以将Jar包文件上传到DLI的程序包管理中,方便后续统一管理。登录DLI管理控制台,单击“数据管理 > 程序包管理”。在“程序包管理”页面,单击右上角的“创建”创建程序包。在“创建程序包”对话框,配置以下参数。包类型:选择“JAR”。OBS路径:程序包所在的OBS路径。分组设置和组名称根据情况选择设置,方便后续识别和管理程序包。单击“确定”,完成创建程序包。创建DLI的UDTF函数。登录DLI管理控制台,单击“SQL编辑器”,执行引擎选择“spark”,选择已创建的SQL队列和数据库。图5 选择队列和数据库在SQL编辑区域输入下列命令创建UDTF函数,单击“执行”提交创建。CREATE FUNCTION mytestsplit AS 'com.huawei.demo.UDTFSplit' using jar 'obs://dli-test-obs01/MyUDTF-1.0-SNAPSHOT.jar';重启原有SQL队列,使得创建的UDTF函数生效。登录数据湖探索管理控制台,选择“队列管理”,在对应“SQL队列”类型作业的“操作”列,单击“重启”。在“重启队列”界面,选择“确定”完成队列重启。验证和使用创建的UDTF函数。在查询语句中使用6中创建的UDTF函数,如:select mytestsplit('abc:123\;efd:567\;utf:890');图6 执行结果(可选)删除UDTF函数。如果不再使用该Function,可执行以下语句删除UDTF函数:Drop FUNCTION mytestsplit;样例代码UDTFSplit.java完整的样例代码参考如下所示:package com.huawei.demo; import java.util.ArrayList; import org.apache.commons.lang.StringUtils; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; public class UDTFSplit extends GenericUDTF { @Override public void close() throws HiveException { // TODO Auto-generated method stub } @Override public void process(Object[] args) throws HiveException { // TODO Auto-generated method stub if(args.length == 0){ return; } String input = args[0].toString(); if(StringUtils.isEmpty(input)){ return; } String[] test = input.split(";"); for (int i = 0; i < test.length; i++) { try { String[] result = test[i].split(":"); forward(result); } catch (Exception e) { continue; } } } @Override public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException { if (args.length != 1) { throw new UDFArgumentLengthException("ExplodeMap takes only one argument"); } if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) { throw new UDFArgumentException("ExplodeMap takes string as a parameter"); } ArrayList<String> fieldNames = new ArrayList<String>(); ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(); fieldNames.add("col1"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); fieldNames.add("col2"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs); } }
  • [最佳实践] 使用IntelliJ IDEA Java创建和使用Spark UDF
    操作场景DLI支持用户使用Hive UDF(User Defined Function,用户定义函数)进行数据查询等操作,UDF只对单行数据产生作用,适用于一进一出的场景。约束限制在DLI Console上执行UDF相关操作时,需要使用自建的SQL队列。跨账号使用UDF时,除了创建UDF函数的用户,其他用户如果需要使用时,需要先进行授权才可使用对应的UDF函数。授权操作参考如下:登录DLI管理控制台,选择“ 数据管理 > 程序包管理”页面,选择对应的UDF Jar包,单击“操作”列中的“权限管理”,进入权限管理页面,单击右上角“授权”,勾选对应权限。自定义函数中引用static类或接口时,必须要加上“try catch”异常捕获,否则可能会造成包冲突,导致函数功能异常。环境准备在进行UDF开发前,请准备以下开发环境。表1 UDF开发环境准备项说明操作系统Windows系统,支持Windows7以上版本。安装JDKJDK使用1.8版本。安装和配置IntelliJ IDEAIntelliJ IDEA为进行应用开发的工具,版本要求使用2019.1或其他兼容版本。安装Maven开发环境的基本配置。用于项目管理,贯穿软件开发生命周期。开发流程DLI下UDF函数开发流程参考如下:图1 开发流程表2 开发流程说明序号阶段操作界面说明1新建Maven工程,配置pom文件IntelliJ IDEA参考操作步骤说明,编写UDF函数代码。2编写UDF函数代码3调试,编译代码并导出Jar包4上传Jar包到OBSOBS控制台将生成的UDF函数Jar包文件上传到OBS目录下。5创建DLI的UDF函数DLI控制台在DLI控制台的SQL作业管理界面创建使用的UDF函数。6验证和使用DLI的UDF函数DLI控制台在DLI作业中使用创建的UDF函数。操作步骤新建Maven工程,配置pom文件。以下通过IntelliJ IDEA 2020.2工具操作演示。打开IntelliJ IDEA,选择“File > New > Project”。图2 新建Project选择Maven,Project SDK选择1.8,单击“Next”。定义样例工程名和配置样例工程存储路径,单击“Finish”完成工程创建。在pom.xml文件中添加如下配置。<dependencies> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-exec</artifactId> <version>1.2.1</version> </dependency> </dependencies>图3 pom文件中添加配置在工程路径的“src > main > java”文件夹上鼠标右键,选择“New > Package”,新建Package和类文件。Package根据需要定义,本示例定义为:“com.huawei.demo”,完成后回车。在包路径下新建Java Class文件,本示例定义为:SumUdfDemo。编写UDF函数代码。UDF函数实现,主要注意以下几点:自定义UDF需要继承org.apache.hadoop.hive.ql.UDF。需要实现evaluate函数,evaluate函数支持重载。详细UDF函数实现,可以参考如下样例代码:package com.huawei.demo; import org.apache.hadoop.hive.ql.exec.UDF; public class SumUdfDemo extends UDF { public int evaluate(int a, int b) { return a + b; } }编写调试完成代码后,通过IntelliJ IDEA工具编译代码并导出Jar包。单击工具右侧的“Maven”,参考下图分别单击“clean”、“compile”对代码进行编译。编译成功后,单击“package”对代码进行打包。打包成功后,生成的Jar包会放到target目录下,以备后用。本示例将会生成到:“D:\DLITest\MyUDF\target”下名为“MyUDF-1.0-SNAPSHOT.jar”。登录OBS控制台,将生成的Jar包文件上传到OBS路径下。说明:Jar包文件上传的OBS桶所在的区域需与DLI的队列区域相同,不可跨区域执行操作。(可选)可以将Jar包文件上传到DLI的程序包管理中,方便后续统一管理。登录DLI管理控制台,单击“数据管理 > 程序包管理”。在“程序包管理”页面,单击右上角的“创建”创建程序包。在“创建程序包”对话框,配置以下参数。包类型:选择“JAR”。OBS路径:程序包所在的OBS路径。分组设置和组名称根据情况选择设置,方便后续识别和管理程序包。单击“确定”,完成创建程序包。创建UDF函数。登录DLI管理控制台,单击“SQL编辑器”,执行引擎选择“spark”,选择已创建的SQL队列和数据库。图4 选择队列和数据库在SQL编辑区域输入下列命令创建UDF函数,单击“执行”提交创建。CREATE FUNCTION TestSumUDF AS 'com.huawei.demo.SumUdfDemo' using jar 'obs://dli-test-obs01/MyUDF-1.0-SNAPSHOT.jar';重启原有SQL队列,使得创建的Function生效。登录数据湖探索管理控制台,选择“队列管理”,在对应“SQL队列”类型作业的“操作”列,单击“重启”。在“重启队列”界面,选择“确定”完成队列重启。使用UDF函数。在查询语句中使用6中创建的UDF函数:select TestSumUDF(1,2);图5 执行结果(可选)删除UDF函数。如果不再使用UDF函数,可执行以下语句删除该函数:Drop FUNCTION TestSumUDF;
  • [最佳实践] 使用Spark Jar作业读取和查询OBS数据
    操作场景DLI完全兼容开源的Apache Spark,支持用户开发应用程序代码来进行作业数据的导入、查询以及分析处理。本示例从编写Spark程序代码读取和查询OBS数据、编译打包到提交Spark Jar作业等完整的操作步骤说明来帮助您在DLI上进行作业开发。环境准备在进行Spark Jar作业开发前,请准备以下开发环境。表1 Spark Jar作业开发环境准备项说明操作系统Windows系统,支持Windows7以上版本。安装JDKJDK使用1.8版本。安装和配置IntelliJ IDEAIntelliJ IDEA为进行应用开发的工具,版本要求使用2019.1或其他兼容版本。安装Maven开发环境的基本配置。用于项目管理,贯穿软件开发生命周期。开发流程DLI进行Spark Jar作业开发流程参考如下:图1 Spark Jar作业开发流程表2 开发流程说明序号阶段操作界面说明1创建DLI通用队列DLI控制台创建作业运行的DLI队列。2上传数据到OBS桶OBS控制台将测试数据上传到OBS桶下。3新建Maven工程,配置pom文件IntelliJ IDEA参考样例代码说明,编写程序代码读取OBS数据。4编写程序代码5调试,编译代码并导出Jar包6上传Jar包到OBS和DLIOBS控制台将生成的Spark Jar包文件上传到OBS目录下和DLI程序包中。7创建Spark Jar作业DLI控制台在DLI控制台创建Spark Jar作业并提交运行作业。8查看作业运行结果DLI控制台查看作业运行状态和作业运行日志。步骤1:创建DLI通用队列第一次提交Spark作业,需要先创建队列,例如创建名为“sparktest”的队列,队列类型选择为“通用队列”。在DLI管理控制台的左侧导航栏中,选择“队列管理”。单击“队列管理”页面右上角“购买队列”进行创建队列。创建名为“sparktest”的队列,队列类型选择为“通用队列”。创建队列详细介绍请参考创建队列。单击“立即购买”,确认配置。配置确认无误,单击“提交”完成队列创建。步骤2:上传数据到OBS桶根据如下数据,创建people.json文件。{"name":"Michael"} {"name":"Andy", "age":30} {"name":"Justin", "age":19}进入OBS管理控制台,在“桶列表”下,单击已创建的OBS桶名称,本示例桶名为“dli-test-obs01”,进入“概览”页面。单击左侧列表中的“对象”,选择“上传对象”,将people.json文件上传到OBS桶根目录下。在OBS桶根目录下,单击“新建文件夹”,创建名为“result”的文件夹。单击“result”的文件夹,在“result”下单击“新建文件夹”,创建名为“parquet”的文件夹。步骤3:新建Maven工程,配置pom依赖以下通过IntelliJ IDEA 2020.2工具操作演示。打开IntelliJ IDEA,选择“File > New > Project”。图2 新建Project选择Maven,Project SDK选择1.8,单击“Next”。定义样例工程名和配置样例工程存储路径,单击“Finish”完成工程创建。如上图所示,本示例创建Maven工程名为:SparkJarObs,Maven工程路径为:“D:\DLITest\SparkJarObs”。在pom.xml文件中添加如下配置。<dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.3.2</version> </dependency> </dependencies>图3 修改pom.xml文件在工程路径的“src > main > java”文件夹上鼠标右键,选择“New > Package”,新建Package和类文件。Package根据需要定义,本示例定义为:“com.huawei.dli.demo”,完成后回车。在包路径下新建Java Class文件,本示例定义为:SparkDemoObs。步骤4:编写代码编写SparkDemoObs程序读取OBS桶下的1的“people.json”文件,并创建和查询临时表“people”。完整的样例请参考完整样例代码参考,样例代码分段说明如下:导入依赖的包。import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SaveMode; import org.apache.spark.sql.SparkSession; import static org.apache.spark.sql.functions.col;通过当前帐号的AK和SK创建SparkSession会话spark 。SparkSession spark = SparkSession .builder() .config("spark.hadoop.fs.obs.access.key", "xxx") .config("spark.hadoop.fs.obs.secret.key", "yyy") .appName("java_spark_demo") .getOrCreate();"spark.hadoop.fs.obs.access.key"参数对应的值"xxx"需要替换为帐号的AK值。"spark.hadoop.fs.obs.secret.key"参数对应的值“yyy”需要替换为帐号的SK值。AK和SK值获取请参考:如何获取AK和SK。读取OBS桶中的“people.json”文件数据。其中“dli-test-obs01”为演示的OBS桶名,请根据实际的OBS桶名替换。Dataset<Row> df = spark.read().json("obs://dli-test-obs01/people.json"); df.printSchema();通过创建临时表“people”读取文件数据。df.createOrReplaceTempView("people");查询表“people”数据。Dataset<Row> sqlDF = spark.sql("SELECT * FROM people"); sqlDF.show();将表“people”数据以parquet格式输出到OBS桶的“result/parquet”目录下。sqlDF.write().mode(SaveMode.Overwrite).parquet("obs://dli-test-obs01/result/parquet"); spark.read().parquet("obs://dli-test-obs01/result/parquet").show();关闭SparkSession会话spark。spark.stop();步骤5:调试、编译代码并导出Jar包单击IntelliJ IDEA工具右侧的“Maven”,参考下图分别单击“clean”、“compile”对代码进行编译。编译成功后,单击“package”对代码进行打包。打包成功后,生成的Jar包会放到target目录下,以备后用。本示例将会生成到:“D:\DLITest\SparkJarObs\target”下名为“SparkJarObs-1.0-SNAPSHOT.jar”。步骤6:上传Jar包到OBS和DLI下登录OBS控制台,将生成的“SparkJarObs-1.0-SNAPSHOT.jar”Jar包文件上传到OBS路径下。将Jar包文件上传到DLI的程序包管理中,方便后续统一管理。登录DLI管理控制台,单击“数据管理 > 程序包管理”。在“程序包管理”页面,单击右上角的“创建”创建程序包。在“创建程序包”对话框,配置以下参数。包类型:选择“JAR”。OBS路径:程序包所在的OBS路径。分组设置和组名称根据情况选择设置,方便后续识别和管理程序包。单击“确定”,完成创建程序包。步骤7:创建Spark Jar作业登录DLI控制台,单击“作业管理 > Spark作业”。在“Spark作业”管理界面,单击“创建作业”。在作业创建界面,配置对应作业运行参数。具体说明如下:所属队列:选择已创建的DLI通用队列。例如当前选择步骤1:创建DLI通用队列创建的通用队列“sparktest”。作业名称(--name):自定义Spark Jar作业运行的名称。当前定义为:SparkTestObs。应用程序:选择步骤6:上传Jar包到OBS和DLI下中上传到DLI程序包。例如当前选择为:“SparkJarObs-1.0-SNAPSHOT.jar”。主类:格式为:程序包名+类名。例如当前为:com.huawei.dli.demo.SparkDemoObs。其他参数可暂不选择,想了解更多Spark Jar作业提交说明可以参考创建Spark作业。图4 创建Spark Jar作业单击“执行”,提交该Spark Jar作业。在Spark作业管理界面显示已提交的作业运行状态。步骤8:查看作业运行结果在Spark作业管理界面显示已提交的作业运行状态。初始状态显示为“启动中”。如果作业运行成功则作业状态显示为“已成功”,单击“操作”列“更多”下的“Driver日志”,显示当前作业运行的日志。图5 “Driver日志”中的作业执行日志如果作业运行成功,本示例进入OBS桶下的“result/parquet”目录,查看已生成预期的parquet文件。如果作业运行失败,单击“操作”列“更多”下的“Driver日志”,显示具体的报错日志信息,根据报错信息定位问题原因。例如,如下截图信息因为创建Spark Jar作业时主类名没有包含包路径,报找不到类名“SparkDemoObs”。可以在“操作”列,单击“编辑”,修改“主类”参数为正确的:com.huawei.dli.demo.SparkDemoObs,单击“执行”重新运行该作业即可。后续指引如果您想通过Spark Jar作业访问其他数据源,请参考《使用Spark作业跨源访问数据源》。如果您想通过Spark Jar作业在DLI创建数据库和表,请参考《使用Spark作业访问DLI元数据》。完整样例代码参考package com.huawei.dli.demo; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SaveMode; import org.apache.spark.sql.SparkSession; import static org.apache.spark.sql.functions.col; public class SparkDemoObs { public static void main(String[] args) { SparkSession spark = SparkSession .builder() .config("spark.hadoop.fs.obs.access.key", "xxx") .config("spark.hadoop.fs.obs.secret.key", "yyy") .appName("java_spark_demo") .getOrCreate(); // can also be used --conf to set the ak sk when submit the app // test json data: // {"name":"Michael"} // {"name":"Andy", "age":30} // {"name":"Justin", "age":19} Dataset<Row> df = spark.read().json("obs://dli-test-obs01/people.json"); df.printSchema(); // root // |-- age: long (nullable = true) // |-- name: string (nullable = true) // Displays the content of the DataFrame to stdout df.show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ // Select only the "name" column df.select("name").show(); // +-------+ // | name| // +-------+ // |Michael| // | Andy| // | Justin| // +-------+ // Select people older than 21 df.filter(col("age").gt(21)).show(); // +---+----+ // |age|name| // +---+----+ // | 30|Andy| // +---+----+ // Count people by age df.groupBy("age").count().show(); // +----+-----+ // | age|count| // +----+-----+ // | 19| 1| // |null| 1| // | 30| 1| // +----+-----+ // Register the DataFrame as a SQL temporary view df.createOrReplaceTempView("people"); Dataset<Row> sqlDF = spark.sql("SELECT * FROM people"); sqlDF.show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ sqlDF.write().mode(SaveMode.Overwrite).parquet("obs://dli-test-obs01/result/parquet"); spark.read().parquet("obs://dli-test-obs01/result/parquet").show(); spark.stop(); } }