-
操作场景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;
-
操作场景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(); } }
-
首先:集群规模是健康的。连接的点是集群外。使用hive的beeline和spark的spark-beeline都能正常连接,和操作。但是用IDEA spark开发就出现问题了代码如下:报错如下:2022-05-27 23:29:21,610 [main] ERROR [org.apache.thrift.transport.TSaslTransport] - SASL negotiation failurejavax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)] at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:211) at org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94)。。。Caused by: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt) at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:147)。。。2022-05-27 23:29:21,631 [main] ERROR [org.apache.thrift.transport.TSaslTransport] - SASL negotiation failurejavax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)] at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:211) at org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94)。。。Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient; at org.apache.spark.sql.hive.HiveExternalCatalog.withClient(HiveExternalCatalog.scala:107) at org.apache.spark.sql.hive.HiveExternalCatalog.databaseExists(HiveExternalCatalog.scala:215)。。。Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:522) at org.apache.spark.sql.hive.client.HiveClientImpl.newState(HiveClientImpl.scala:185)。。Caused by: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1523) at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.<init>(RetryingMetaStoreClient.java:86)。。。Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)。。。Caused by: MetaException(message:Could not connect to meta store using any of the URIs provided. Most recent failure: org.apache.thrift.transport.TTransportException: GSS initiate failed at org.apache.thrift.transport.TSaslTransport.sendAndThrowMessage(TSaslTransport.java:232) at org.apache.thrift.transport.TSaslTransport.open(TSaslTransport.java:316) at org.apache.thrift.transport.TSaslClientTransport.open(TSaslClientTransport.java:37)。。。。
-
亮点特性1:远程开发 - 支持本地IDE远程访问Notebook新版Notebook提供了远程开发功能,通过开启SSH连接,用户本地IDE可以远程连接到ModelArts的Notebook开发环境中,调试和运行代码。对于使用本地IDE的开发者,由于本地资源限制,运行和调试环境大多使用团队公共搭建的CPU或GPU服务器,并且是多人共用,这带来一定的环境搭建和维护成本。而ModelArts的Notebook的优势是即开即用,它预先装好了不同的AI引擎,并且提供了非常多的可选规格,用户可以独占一个容器环境,不受其他人的干扰。只需简单配置,用户即可通过本地IDE连接到该环境进行运行和调试。图1 本地IDE远程访问Notebook开发环境ModelArts的Notebook可以视作是本地PC的延伸,均视作本地开发环境,其读取数据、训练、保存文件等操作与常规的本地训练一致。对于习惯使用本地IDE的开发者,使用远程开发方式,不影响用户的编码习惯,并且可以方便快捷的使用云上的Notebook开发环境。本地IDE当前支持VSCode、PyCharm、SSH工具。还有专门的插件PyCharm Toolkit和VSCode Toolkit,方便将云上资源作为本地的一个扩展。亮点特性2:预置镜像 - 即开即用,优化配置,支持主流AI引擎每个镜像预置的AI引擎和版本是固定的,在创建Notebook实例时明确AI引擎和版本,包括适配的芯片。亮点特性3:提供在线的交互式开发调试工具JupyterLabModelArts集成了基于开源的JupyterLab,可为您提供在线的交互式开发调试。您无需关注安装配置,在ModelArts管理控制台直接使用Notebook,编写和调测模型训练代码,然后基于该代码进行模型的训练。JupyterLab是一个交互式的开发环境,是Jupyter Notebook的下一代产品,可以使用它编写Notebook、操作终端、编辑MarkDown文本、打开交互模式、查看csv文件及图片等功能。
-
## TBE DSL开发方式实现Tensorflow BatchNorm算子开发全流程(下) TBE DSL开发方式实现Tensorflow BatchNorm算子开发全流程(上) https://bbs.huaweicloud.com/forumreview/thread-187864-1-1.html TBE DSL开发方式实现Tensorflow BatchNorm算子开发全流程(下) https://bbs.huaweicloud.com/forum/thread-187872-1-1.html bilibili视频链接 https://www.bilibili.com/video/BV17U4y1m7G4 - 编译配置 ```python if is_training: tensor_list = [x_input, scale_input, offset_input] + list(res) else: tensor_list = [x_input, scale_input, offset_input, mean_input, variance_input] + list(res) config = {"name": kernel_name, "tensor_list": tensor_list} tbe.cce_build_code(sch, config) ``` ### 5.5 算子原型文件 算子原型定义规定了在昇腾AI处理器上可运行算子的约束,主要体现算子的数学含义,包含定义算子输入、输出和属性信息,基本参数的校验和shape的推导,原型定义的信息会被注册到GE的算子原型库中。网络模型生成时,GE会调用算子原型库的校验接口进行基本参数的校验,校验通过后,会根据原型库中的推导函数推导每个节点的输出shape与dtype,进行输出tensor的静态内存的分配。 算子的IR用于进行算子的描述,包括算子输入输出信息,属性信息等,用于把算子注册到算子原型库中,需要在算子的工程目录的/op_proto/算子名称\.h 和 /op_proto/算子名称.cc文件中进行实现。 **算子IR头文件.h** ```C /*宏定义*/ #ifndef BATCH_NORM_H #define BATCH_NORM_H /*包含头文件*/ #include "graph/operator_reg.h" /*原型注册*/ /*INPUT与.OUTPUT分别为算子的输入、输出Tensor的名称与数据类型,输入输出的顺序需要与算子代码实现函数形参顺序以及算子信息定义中参数的顺序保持一致。*/ namespace ge { REG_OP(BatchNorm) /*与插件适配文件中的算子类型保存一致,BatchNorm*/ .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(scale, TensorType({DT_FLOAT})) .INPUT(offset, TensorType({DT_FLOAT})) .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(batch_mean, TensorType({DT_FLOAT})) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_3, TensorType({DT_FLOAT})) .ATTR(epsilon, Float, 0.0001) .ATTR(data_format, String, "NHWC") .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(BatchNorm) } // namespace ge /*结束条件编译*/ #endif // BATCH_NORM_H ``` **算子IR定义的.cc文件** IR实现的cc文件中主要实现如下两个功能: - 算子参数的校验,实现程序健壮性并提高定位效率,对应Verify函数。 - 根据算子的输入张量描述、算子逻辑及算子属性,推理出算子的输出张量描述,包括张量的形状、数据类型及数据排布格式等信息。这样算子构图准备阶段就可以为所有的张量静态分配内存,避免动态内存分配带来的开销,对应InferShape函数。 Verify函数主要校验算子内在关联关系,例如对于多输入算子,多个tensor的dtype需要保持一致,此时需要校验多个输入的dtype,其他情况dtype不需要校验。 实现Verify函数 ```c IMPLEMT_VERIFIER(BatchNorm, BatchNormVerify) { if (!CheckTwoInputDtypeSame(op, "scale", "offset")) { return GRAPH_FAILED; } return GRAPH_SUCCESS; } ``` InferShape流程负责推导TensorDesc中的dtype与shape,只要全图所有首节点的TensorDesc确定了,就可以逐个向下传播,再由算子自身实现的Shape推导能力,就可以将全图所有OP的输入输出TensorDesc推导出来,推导结束后,全图的dtype与shape的规格就完全连续了。InferShape函数详细可参见算子原型定义。 实现InferShape函数 ```c IMPLEMT_INFERFUNC(BatchNorm, BatchNormInferShape) { std::string data_format; if (op.GetAttr("data_format", data_format) == GRAPH_SUCCESS) { if (data_format != "NHWC" && data_format != "NCHW") { string expected_format_list = ConcatString("NHWC, NCHW"); std::string err_msg = GetInputFormatNotSupportErrMsg("data_format", expected_format_list, data_format); VECTOR_INFER_SHAPE_INNER_ERR_REPORT(op.GetName(), err_msg); return GRAPH_FAILED; } } if (!OneInOneOutDynamicInfer(op, "x", {"y"})) { return GRAPH_FAILED; } if (!OneInOneOutDynamicInfer(op, "scale", {"batch_mean", "batch_variance", "reserve_space_1", "reserve_space_2"})) { return GRAPH_FAILED; } std::vector<int64_t> oShapeVector; auto op_info = OpDescUtils::GetOpDescFromOperator(op); auto output_desc = op_info->MutableOutputDesc("reserve_space_3"); if (output_desc != nullptr) { output_desc->SetShape(GeShape(oShapeVector)); output_desc->SetDataType(DT_FLOAT); } return GRAPH_SUCCESS; } ``` 注册infershape方法和Verify方法 ```c INFER_FUNC_REG(BatchNorm, BatchNormInferShape); VERIFY_FUNC_REG(BatchNorm, BatchNormVerify); ``` ### 5.6 算子信息库文件 算子信息库作为算子开发的交付件之一,主要体现算子在昇腾AI处理器上的具体实现规格,算子开发者需要通过配置算子信息库文件,将算子在昇腾AI处理器上相关实现信息注册到算子信息库中,包括算子支持输入输出type、format以及输入shape等信息。网络运行时,FE会根据算子信息库中的算子信息做基本校验,选择dtype,format等信息,并根据算子信息库中信息找到对应的算子实现文件进行编译,用于生成算子二进制文件。  图17 算子信息库文件 参数说明请参见文档中的[表1](https://support.huaweicloud.com/usermanual-mindstudio302/atlasms_02_0151.html#ZH-CN_TOPIC_0000001134636812__zh-cn_topic_0238860099_zh-cn_topic_0213377578_table108272271412)。 ## 6. BatchNorm算子编译 ### 6.1 基本概念 算子交付件开发完成后,需要对算子工程进行编译,生成自定义算子安装包*.run,详细的编译操作包括: - 将TBE算子信息库定义文件*.ini编译成aic-{soc version}-ops-info.json。 - 将原型定义文件*.h**与*.cc编译成libcust_op_proto.so。 - 将TensorFlow/Caffe/Onnx算子的适配插件实现文件*.h**与*.cc编译成libcust*{tf|caffe|onnx}*parsers.so。 ### 6.2 编译操作 MindStudio界面顶部,点击Build -> Edit Build Configurations。  图18 打开算子编译配置窗口 进入编译配置窗口,以远程编译为例,若未配置远程连接,则先在Deployment后面点击“+“进行配置,并在Envrionment Variables处进行如下配置,用户需将*/home/xxx/Ascend/ascend-toolkit/latest/*替换为CANN实际安装路径。 ```python ASCEND_TENSOR_COMPILER_INCLUDE=/home/xxx/Ascend/ascend-toolkit/latest/include ```  图19 算子编译配置 表1 算子编译配置参数说明 | 参数 | 说明 | | --------------------- | :----------------------------------------------------------- | | Build Configuration | 编译配置名称,默认为Build-Configuration | | Build Mode | 编译方式。Remote Build:远端编译。Local Build:本地编译。 | | Deployment | Remote Build模式下显示该配置。可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 | | Environment variables | Remote Build模式下显示该配置。配置环境变量。 | | Target OS | Local Build模式下显示该配置。针对Ascend EP:选择昇腾AI处理器所在硬件环境的Host侧的操作系统。针对Ascend RC:选择板端环境的操作系统。 | | Target Architecture | Local Build模式下显示该配置。选择Target OS的操作系统架构。 | 点击Build进行工程编译。编译完成后,显示远程编译完成 Information:build remotely finished。  图20 算子编译完成输出日志 在算子工程的cmake-build目录下生成了编译后的BacthNorm算子安装包,包含了操作系统及对应系统架构信息,如下图所示。  图21 算子编译生成安装包.run文件 ## 7. BatchNorm算子部署 ### 7.1 基本概念 算子部署指将算子编译生成的自定义算子安装包(*.run)部署到OPP算子库中。 - 推理场景下,自定义算子直接部署到开发环境的OPP算子库。 - 训练场景下,自定义算子安装包需要部署到运行环境的OPP算子库中。 ### 7.2 部署操作 在MindStudio工程界面,选中算子工程,点击顶部的Ascend > Operator Deployment,进入算子打包部署界面  图22 打开算子部署配置窗口 如下算子部署界面,Operator Package即前面编译后生成的自定义算子安装包  图23 算子部署配置 在Environment Variables中直接输入ASCEND_OPP_PATH=*/home/xxx/Ascend/ascend-toolkit/latest/opp。* */home/xxx/Ascend/ascend-toolkit/latest*为OPP组件(算子库)的安装路径,请根据实际情况配置。 也可以点击文本框后的图标,在弹出的对话框中填写。 - 在Name中输入环境变量名称:ASCEND_OPP_PATH。 - 在Value中输入环境变量值:*home/xxx/Ascend/ascend-toolkit/latest/opp*。 表2 算子部署配置参数说明 | 参数 | 说明 | | --------------------- | :----------------------------------------------------------- | | Build Configuration | 编译配置名称,默认为Build-Configuration | | Deployment | Remote Build模式下显示该配置。可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 | | Environment variables | Remote Build模式下显示该配置。配置环境变量。 | 点击Operator deploy进行算子部署,部署成功会出现以下输出日志。  图24 算子部署完成输出日志 ## 8. BatchNorm算子UT ### 8.1 基本概念 基于MindStudio进行算子开发的场景下,用户可基于MindStudio进行算子的UT,UT(Unit Test:单元测试)是开发人员进行算子代码验证的手段之一,主要目的是: - 测试算子代码的正确性,验证输入输出结果与设计的一致性。 - UT侧重于保证算子程序能够跑通,选取的场景组合应能覆盖算子代码的所有分支(一般来说覆盖率要达到100%),从而降低不同场景下算子代码的编译失败率。 ### 8.2 UT操作 开发人员可以执行当前工程中所有算子的UT用例,也可以执行单个算子的UT用例: - 右键单击“testcases/ut/ops_test”文件夹,选择Run TBE Operator'All'UT Impl with coverage,执行整个文件夹下算子实现代码的测试用例。 - 右键单击“testcases/ut/ops_test/*算子名称*”文件夹,选择Run TBE Operator'算子名称'UT Impl with coverage,执行单个算子实现代码的测试用例。  图25 第一次打开UT配置窗口 第一次运行时弹出UT配置窗口,进行如下配置后,点击OK执行算子UT。  图26 UT配置 表3 算子UT配置参数说明 | 参数 | 说明 | | ------------- | ------------------------------------------------------------ | | Name | 运行配置名称,用户可以自定义。 | | Compute Unit | 选择计算单元 | | SoC Version | 下拉选择当前版本的昇腾AI处理器类型。 | | Target | 运行环境。Simulator_Function:功能仿真环境。Simulator_TMModel:快速展示算子执行的调度流水线,不进行实际算子计算。 | | Operator Name | 选择运行的测试用例。 | | CANN Machine | CANN工具所在设备的deployment信息。 | | Case Names | 勾选需要运行的测试用例,即算子实现代码的UT Python测试用例。 | 第二次执行UT文件不弹出运行配置,若需改配置,在顶部选择更改的文件,点击Edit Configurations即可修改。  图27 重新打开UT配置窗口 在Target选择Simulator_TMModel时,可以查看执行流水线,如下图所示图。  图28 UT流水线 点击Run,会有一个用例测试结果的url。  图29 UT完成输出日志url 点击该url,查看UT的具体执行结果。  图30 UT测试结果详情 可点击页面中对应算子,进入UT用例覆盖率详情页面,通过绿色和红色标签区分是否覆盖。  图31 UT代码覆盖 ## 9. BatchNorm算子ST ### 9.1 基本概念 自定义算子部署到算子库(OPP)后,可进行ST(System Test),在真实的硬件环境中,验证算 子功能的正确性。 ST的主要功能是: - 基于算子测试用例定义文件*.json生成单算子的om文件; - 使用AscendCL接口加载并执行单算子om文件,验证算子执行结果的正确性。ST会覆盖算子实现文件,算子原型定义与算子信息库,不会对算子适配插件进行测试。 ### 9.2 ST操作 ST用例的创建与UT用例的创建类似: - 右键单击算子工程根目录,选择New Cases > ST Case。 - 右键单击算子信息定义文件:{工程名} /tbe /op_info_cfg/ai_core/SoC version} /xx\.ini,选择New Cases > ST Case。若已经存在了对应算子的ST Case,可以右键单击testcases目录,或者testcases > st目录,选择New Cases > ST Case,追加ST测试用例。 **执行ST** 在工程目录testcases -> st -> batch_norm -> {SoC Version} -> xxx.json,找到保存的ST用例定义文件,右键单击选择Run ST Case ‘xxx.json',首次执行时,会弹出配置窗口中进行ST用例运行配置。  图32 第一次打开ST配置窗口 执行ST用例,其中在Advanced options下勾选Enable Profiling,可获取算子在昇腾AI处理器上的性能数据,该功能需要将运行环境中的msprof工具所在路径配置到PATH环境变量中,可在.bashrc文件中添加如下语句: ``` export PATH="$PATH:/usr/local/Ascend/ascend-toolkit/latest/tools/profiler/bin/" ``` 参考如下配置,其中环境变量配置如表4 表4 ST环境变量配置说明 | Name | Value | | ------------------ | ------------------------------------------------------------ | | ASCEND_DRIVER_PATH | /usr/local/Ascend/driver | | ASCEND_HOME | /usr/local/Ascend//ascend-toolkit/latest | | LD_LIBRARY_PATH | \${ASCEND_DRIVER_PATH}/lib64:\${ASCEND_HOME}/lib64:$LD_LIBRARY_PATH |  图33 ST配置  图34 ST性能数据日志  图35 ST完成输出日志 在’*算子工程根目录*/testcases/st/out/‘目录下生成测试数据和测试代码,并编译出可执行文件,在指定的硬件设备上执行测试用例。在’*算子工程根目录*/testcases/st/out/‘目录下生成的st_report.json文件记录了测试情况,可参考MindStudio文档中的ST测试执行结果表。 ## 10. 关于BatchNorm算子开发的FAQ 1. 创建的BatchNorm算子工程,代码的头文件或者导入的依赖显示为红色。 首先检查是否参考MindStudio的安装指南安装好对应的依赖和环境,其次算子工程是在服务器端的 CANN框架下运行的,但是工程文件保存在Windows端本地,本地没CANN环境会显示为红色,但是不会影响远端工程的运行。 2. 算子流程中的编译、部署和ST测试中如何设置相应的环境变量。 参考MindStudio用户手册中的用户指南,在自定义算子开发章节下的TBE算子开发(TensorFlow/Caffe)小节中,有详细讲解如何设置环境变量。 3. 算子UT测试中无法生成流水线图。 在UT测试的配置框中,Target选择Stimulator_TMModel,UT执行完成后可生成流水线图。 4. ST测试中,勾选了Enable Profiling后的ST日志里,没有出现性能数据,并提示msprof command未找到。 进入Linux服务器,在.bashrc文件最底部中添加export PATH="$PATH:/usr/local/Ascend/ascend-toolkit/latest/tools/profiler/bin/",其中路径需配置到msprof工具实际所在bin目录下。配置完成后,则无该提示并出现性能数据。 5. 如何打开UT测试和ST测试的运行配置窗口。 第一次进行UT测试和ST测试时,运行前会自动打开配置窗口让用户进行配置,第二次开始就会按照第一次的默认配置进行执行,只需在MindStudio界面上方的绿色锤子旁边先选择UT或ST的配置文件,再点击Edit Configurations即可再次打开配置窗口。  图36 再次打开UT、ST配置窗口
-
PyTorch框架使用DSL进行TBE算子开发全流程(上)PyTorch框架使用DSL进行TBE算子开发全流程(上) [https://bbs.huaweicloud.com/forumreview/thread-187817-1-1.html](https://bbs.huaweicloud.com/forumreview/thread-187817-1-1.html) PyTorch框架使用DSL进行TBE算子开发全流程(下) [https://bbs.huaweicloud.com/forum/thread-187818-1-1.html](https://bbs.huaweicloud.com/forum/thread-187818-1-1.html) bilibili视频链接 [https://www.bilibili.com/video/BV1WZ4y1a74i](https://www.bilibili.com/video/BV1WZ4y1a74i) ## 1. DSL算子基本概念介绍 ### 1.1 什么是算子 深度学习算法由一个个计算单元组成,我们称这些计算单元为算子(Operator,简称 OP)。在网络模型中,算子对应层中的计算逻辑,例如:卷积层(Convolution Layer)是一个算子;全连接层(Fully-connected Layer, FC layer)中的权值求和过 程,是一个算子。 对每一个独立的算子,用户需要编写算子描述文件,描述算子的整体逻辑、计算步骤以及相关硬件平台信息等。然后用深度学习编译器对算子描述文件进行编译,生成可在特定硬件平台上运行的二进制文件后,将待处理数据作为输入,运行算子即可得到期望输出。将神经网络所有被拆分后的算子都按照上述过程处理后, 再按照输入输出关系串联起来即可得到整网运行结果。 图1:算子全流程执行### 1.2 什么是TBE算子 TBE(Tensor Boost Engine)提供了基于开源深度学习编译栈TVM框架的自定义算子开发能力,通过TBE提供的API可以完成相应神经网络算子的开发。 一个完整的TBE算子包含四部分:算子原型定义、对应开源框架的算子适配插件、算子信息库定义和算子实现。 图2:TBE算子全流程执行昇腾AI软件栈提供了TBE(Tensor Boost Engine:张量加速引擎)算子开发框架,开发者可以基于此框架使用Python语言开发自定义算子,通过TBE进行算子开发有以下几种方式: * DSL(Domain-Specific Language)开发 * TIK(Tensor Iterator Kernel)开发 ### 1.3 什么是DSL算子 为了方便开发者进行自定义算子开发,TBE(Tensor Boost Engine)提供了一套计算接口供开发者用于组装算子的计算逻辑,使得70%以上的算子可以基于这些接口进行开发,极大的降低自定义算子的开发难度。TBE提供的这套计算接口,称之为DSL(Domain-Specific Language)。基于DSL开发的算子,可以直接使用TBE提供的Auto Schedule机制,自动完成调度过程,省去最复杂的调度编写过程。 图3:DSL算子介绍#### 1.3.1 DSL功能框架 1. 开发者调用TBE提供的DSL接口进行计算逻辑的描述,指明算子的计算方法和步骤。 2. 计算逻辑开发完成后,开发者可调用Auto Schedule接口,启动自动调度,自动调度时TBE会根据计算类型自动选择合适的调度模板,完成数据切块和数据流向的划分,确保在硬件执行上达到最优。 3. Auto Schedule调度完成后,会生成类似于TVM的I R(Intermediate Representation)的中间表示。 4. 编译优化(Pass)会对算子生成的IR进行编译优化,优化的方式有双缓冲(Double Buffer)、流水线(Pipeline)同步、内存分配管理、指令映射、分块适配矩阵计算单元等。 5. 算子经Pass处理后,由CodeGen生成类C代码的临时文件,这个临时代码文件可通过编译器生成算子的实现文件,可被网络模型直接加载调用。 #### 1.3.2 DSL计算接口 TBE DSL提供的计算接口主要涵盖向量运算,包括Math、NN、Reduce、卷积、矩阵计算等接口。 ## 2. 算子开发流程介绍 算子开发通常包括以下步骤: * 环境准备:配置MindStudio算子开发环境 * 算子分析:明确算子的功能及数学表达式,选择算子开发方式 * 工程创建:利用MindStudio创建算子工程 * 算子原型定义:规定在昇腾AI处理器上可运行算子的约束 * 算子代码实现:使用DSL或TIK实现算子 * 算子信息库定义:规定算子在昇腾AI处理器上的具体实现规格 * 算子UT测试:测试算子代码的正确性 * 算子工程编译:编译出可直接安装的自定义算子run包 * 算子工程部署:将自定义算子部署到opp算子库 * 算子ST测试:在真实的硬件环境中,使用离线模型验证算子功能的正确性 图4:算子开发流程介绍## 3.算子分析 进行算子开发前,开发者应首先进行算子分析,算子分析包含:明确算子的功能及数学表达式,选择算子开发方式(DSL方式或者TIK方式),最后细化并明确算子规格,分析流程如下所示: 图5:创建工程1#### 3.1分析算子算法原理,提取算子的数学表达式 当$x=\left[x_{1}, x_{2}, \cdots, x_{n}\right]^{\mathrm{T}}$时那么$x$的$p$范数为 $$ \|x\|_{p}=\left(\left|x_{1}\right|^{p}+\left|x_{2}\right|^{p}+\cdots+\left|x_{n}\right|^{p}\right)^{\frac{1}{p}} $$ 当$p$取0时,表示向量中非零元素的个数(即为其稀疏度) 当$p$取1,2,$\infty$时分别是以下几种最简单的情形 $$ \|x\|_{1}=\left|x_{1}\right|+\left|x_{2}\right|+\ldots+\left|x_{n}\right| $$ $$ \|x\|_{2}=\left(\left|x_{1}\right|^{2}+\left|x_{2}\right|^{2}+\cdots+\left|x_{n}\right|^{2}\right)^{\frac{1}{2}} $$ $$ \|x\|_{\infin}=max(\left|x_{1}\right|,\left|x_{2}\right|,\ldots,\left|x_{n}\right|) $$ #### 3.2明确算子开发方式及使用的计算接口 lp_norm 用到的算子有 + ,幂次方,取最大值,取绝对值 * +:可通过tbe.dsl.vadd接口实现。 * 取最大值:可以通过tbe.dsl.reduce_max接口实现。 * 取绝对值:可以通过tbe.dsl.vabs接口实现 * 幂次方:可以通过tbe.dsl.vmuls, tbe.dsl.exp , tbe.dsl.log 接口实现 通过如上分析,可看出TBE DSL接口满足lp_norm算子的实现要求,所以可优先选择TBE DSL方式进行lp_norm算子的实现。 ## 4.创建Pytorch TBE DSL算子工程 ### 4.1安装和配置环境 按照[MindStudio用户手册](https://www.hiascend.com/document/detail/zh/mindstudio/304/progressiveknowledge/index.html)中的安装指南-->安装操作来安装MindStudio。 除了手册中要求的环境依赖,也需要安装tensorflow,推荐1.15版本 如果采用windows和linux 的公开发环境,需要在本地和远端均配置好所需环境。 ### 4.2创建工程 图6:创建工程1图7:创建工程2图8:创建工程3* 创建工程成功 图9:创建工程成功* 设置python SDK 图10:设置python SDK## 5.算子工程结构和交付件介绍 ``` lp_norm: ├─.idea ├─build //编译生成的中间文件 ├─cmake ├─cmake-build ├─framework ├─log ├─metadef ├─op_proto //算子IR定义文件夹 │ ├─lp_norm.cc //算子IR定义 │ ├─lp_norm.h //算子IR定义 ├─op_tiling ├─out ├─profiling ├─scripts ├─tbe │ ├─impl │ │ ├─dynamic //dynamic operator │ │ ├─util //工具类 │ │ └─lp_norm.py //算子python实现 │ └─op_info_cfg │ └─ai_core │ ├─ascend310 │ ├─ascend710 │ └─ascend910 │ └─lp_norm.ini //ascend910算子信息库文件 ├─testcases //UT、ST测试相关目录 │ ├─st //ST测试相关目录 │ │ ├─lp_norm │ │ │ └─ascend310 │ │ │ └─LpNorm_case_20210527144255.json //ST测试用例 │ └─ut //UT测试相关目录 │ └─ops_test │ └─lp_norm │ └─test_lp_norm_impl.py //UT测试入口及测试用例 ├─third_party //工程第三方依赖 └─CMakeLists.txt //编译规则文件 ``` ### 5.1 lp_norm算子原型 lp_norm算子的原型为pytorch中的torch.norm ```python torch.norm(input, p='fro', dim=None, keepdim=False, out=None, dtype=None) ``` ### 5.2 算子python实现代码 ```python def lp_norm(x, y, p=2, axes=None, keepdim=False, epsilon=1e-12, kernel_name="lp_norm"): # 算子校验 para_check.check_kernel_name(kernel_name) xtype_list = ["float16", "float32"] x_type = x.get("dtype").lower() x_shape = x.get("shape") para_check.check_dtype(x_type, xtype_list) para_check.check_shape(x_shape) p_inf_list = ("inf", "-inf") no_shape = len(x_shape) if isinstance(axes, int): axes = [axes] if axes is None: axes = [i for i in range(no_shape)] if len(axes) == 0: axes = [i for i in range(no_shape)] input_data = tvm.placeholder(x_shape, dtype=x_type, name="input_data") abs_data = tbe.vabs(input_data) #对所有输入取绝对值 # 对p分情况 if (p in p_inf_list) or (p == _CONST_INF) or (p == -_CONST_INF - 1): res = lp_norm_inf_compute(abs_data, x_type, y, p, axes, keepdim, kernel_name) elif p == 0: res = lp_norm0_compute(abs_data, x_type, y, axes, keepdim, kernel_name) elif p == 1: res = lp_norm1_compute(abs_data, x_type, y, axes, keepdim, kernel_name) elif p == 2: res = lp_norm2_compute(abs_data, x_type, y, axes, keepdim, kernel_name) else: res = lp_norm_compute(abs_data, x_type, y, p, axes, keepdim, kernel_name) if x_type == "float16" and float(epsilon) <= _CONST_EPSILON_FP16: std_no = tvm.const(_CONST_EPSILON_FP16, dtype=x_type) else: std_no = tvm.const(float(epsilon), dtype=x_type) res = tbe.vmaxs(res, std_no) # 自动调度 with tvm.target.cce(): schedule = tbe.auto_schedule(res) # 算子编译 config = {"name": kernel_name, "tensor_list": [input_data, res]} tbe.cce_build_code(schedule, config) ``` * 无穷范数的计算 $$ \|x\|_{\infin}=max(\left|x_{1}\right|,\left|x_{2}\right|,\ldots,\left|x_{n}\right|) $$ ```python if (p == "inf") or (p == _CONST_INF): res = tbe.reduce_max(abs_x, axis=axes, keepdims=keepdim, priority_flag=True) #对所有值取最大值 else: # p is "-inf" res = tbe.reduce_min(abs_x, axis=axes, keepdims=keepdim, priority_flag=True) #当p为-inf对所有值取最小值 ``` * 0范数的计算 * 0范数表示向量中非零元素的个数(即为其稀疏度) ```python zero_tensor = tbe.vmuls(abs_x, tvm.const(0, dtype=abs_x.dtype)) one_tensor = tbe.vadds(zero_tensor, tvm.const(1, dtype=abs_x.dtype)) ele_tensor = tbe.vcmpsel(abs_x, zero_tensor, 'ne', one_tensor, zero_tensor) res = tbe.sum(ele_tensor, axis=axes, keepdims=keepdim) ``` * 1范数的计算 $$ \|x\|_{1}=\left|x_{1}\right|+\left|x_{2}\right|+\ldots+\left|x_{n}\right| $$ ```python res = tbe.sum(abs_x, axis=axes, keepdims=keepdim) #对所有值求和 ``` * 2范数的计算 $$ \|x\|_{2}=\left(\left|x_{1}\right|^{2}+\left|x_{2}\right|^{2}+\cdots+\left|x_{n}\right|^{2}\right)^{\frac{1}{2}} $$ ```python pow_x = tbe.vmul(abs_x, abs_x) #求平方 sum_pow = tbe.sum(pow_x, axis=axes, keepdims=keepdim) #求和 res = tbe.vsqrt(sum_pow, priority_flag=1) #求1/2次方 ``` * p范数的计算 $$ \|x\|_{p}=\left(\left|x_{1}\right|^{p}+\left|x_{2}\right|^{p}+\cdots+\left|x_{n}\right|^{p}\right)^{\frac{1}{p}} $$ ```python prod_x = abs_x for p_ix in range(1, p): #求p次方 prod_x = tbe.vmul(prod_x, abs_x) sum_prod_x = tbe.sum(prod_x, axis=axes, keepdims=keepdim) #求和 # 将x的p次方转化 x^p --> exp(log(x)/p) if "910" in _CCE_PLAT: log_sum_x = tbe.vlog(sum_prod_x, priority_flag=1) #取对数 else: log_sum_x = tbe.vlog(sum_prod_x) zero_tensor = tbe.vmuls(log_sum_x, tvm.const(0, dtype=log_sum_x.dtype)) p_tensor = tbe.vadds(zero_tensor, tvm.const(p, dtype=log_sum_x.dtype)) div_log_x = tbe.vdiv(log_sum_x, p_tensor) #除以p exp_div_x = tbe.vexp(div_log_x) #e的幂次方 ``` ## 6.介绍算子原型库、算子信息库代码 算子原型定义规定了在昇腾AI处理器上可运行算子的约束,主要体现算子的数学含义,包含定义算子输入、输出和属性信息,基本参数的校验和shape的推导,原型定义的信息会被注册到GE的算子原型库中。网络模型生成时,GE会调用算子原型库的校验接口进行基本参数的校验,校验通过后,会根据原型库中的推导函数推导每个节点的输出shape与dtype,进行输出tensor的静态内存的分配。 算子的IR用于进行算子的描述,包括算子输入输出信息,属性信息等,用于把算子注册到算子原型库中。 算子的IR需要在算子的工程目录的/op_proto/算子名称.h 和 /op_proto/算子名称.cc文件中进行实现。 ### 6.1算子 IR 头文件.h 注册代码实现 ```c #ifndef GE_OP_LP_NORM_H #define GE_OP_LP_NORM_H //头文件 #include "graph/operator_reg.h" #include "graph/operator.h" namespace ge { // 原型注册 REG_OP(LpNorm) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(p, Int, 2) .ATTR(axes, ListInt, {}) .ATTR(keepdim, Bool, false) .ATTR(epsilon, Float, 1e-12) .OP_END_FACTORY_REG(LpNorm) } // namespace ge #endif // GE_OP_LP_NORM_H ``` ### 6.2 算子IR定义的 .cc 注册代码实现 IR实现的cc文件中主要实现如下两个功能: * 算子参数的校验,实现程序健壮性并提高定位效率。 * 根据算子的输入张量描述、算子逻辑及算子属性,推理出算子的输出张量描述,包括张量的形状、数据类型及数据排布格式等信息。这样算子构图准备阶段就可以为所有的张量静态分配内存,避免动态内存分配带来的开销。 ##### 6.2.1实现InferShape方法 InferShape流程负责推导TensorDesc中的dtype与shape,推导结束后,全图的dtype与shape的规格就完全连续了。 如果生成网络模型时产生的GE Dump图“ge_proto_000000xx_after_infershape.txt”中存在dtype与shape规格不连续的情况,说明InferShape处理有错误。 ```c //实现inferShape方法 IMPLEMT_COMMON_INFERFUNC(LpNormInfer) { auto tensor_input = op.GetInputDesc("x"); Shape x_shape = tensor_input.GetShape(); DataType x_type = tensor_input.GetDataType(); Format x_format = tensor_input.GetFormat(); size_t dim_num = op.GetInputDesc("x").GetShape().GetDimNum(); std::vector<int64_t> x_axes = {}; std::vector<int64_t> new_axes = {}; std::vector<int64_t> y_vec = {}; std::vector<int64_t> x_dim_members = x_shape.GetDims(); bool keep_dim = false; int32_t indice; (void)op.GetAttr("keepdim", keep_dim); if (x_axes.empty()) { for (int32_t i = 0; i < dim_num; i++) { new_axes.push_back(i); } } else { for (int32_t i = 0; i < x_axes.size(); i++) { indice = (x_axes<i> < 0) ? (x_axes<i> + dim_num) : x_axes<i>; new_axes.push_back(indice); } } for (int32_t i = 0; i < x_shape.GetDimNum(); i++) { if (find(new_axes.begin(), new_axes.end(), i) != new_axes.end()) { if (keep_dim == true) { y_vec.push_back(1); } } else { y_vec.push_back(x_dim_members<i>); } } ge::Shape output_shape(y_vec); // update output desc ge::TensorDesc output_desc = op.GetOutputDesc("y"); output_desc.SetShape(output_shape); output_desc.SetDataType(x_type); output_desc.SetFormat(x_format); (void)op.UpdateOutputDesc("y", output_desc); return GRAPH_SUCCESS; } ``` ##### 6.2.2实现verify方法 Verify函数主要校验算子内在关联关系,例如对于多输入算子,多个tensor的dtype需要保持一致,此时需要校验多个输入的dtype,其他情况dtype不需要校验。 ```c // 实现verify方法 IMPLEMT_VERIFIER(LpNorm, LpNormVerify) { return GRAPH_SUCCESS; } 注册InferShape方法与Verify方法 ``` ```c // 注册infershape方法和Verify方法 COMMON_INFER_FUNC_REG(LpNorm, LpNormInfer); VERIFY_FUNC_REG(LpNorm, LpNormVerify); ``` ### 6.3算子信息库 算子信息库作为算子开发的交付件之一,主要体现算子在昇腾AI处理器上的具体实现规格,包括算子支持输入输出dtype、format以及输入shape等信息。网络运行时,FE会根据算子信息库中的算子信息做基本校验,选择dtype,format等信息,并根据算子信息库中信息找到对应的算子实现文件进行编译,用于生成算子二进制文件。 如图为Ascend910的算子信息库文件 图11:Ascend910的算子信息库文件## 7.算子编译 算子交付件开发完成后,需要对算子工程进行编译,生成自定义算子安装包*.run,详细的编译操作包括: * 将TBE算子信息库定义文件*.ini编译成aic-{soc version}-ops-info.json * 将原型定义文件*.h与*.cc编译成libcust_op_proto.so。 * 将TensorFlow/Caffe/Onnx算子的适配插件实现文件*.h与*.cc编译成libcust_{tf|caffe|onnx}_parsers.so。 图12:算子编译* 选择Remote Build 进行远程部署 * 配置环境变量ASCEND_TENSOR_COMPILER_INCLUDE=/usr/local/Ascend/ascend-toolkit/latest/include * 点击执行Build 图13:算子编译设置| 参数 | 说明 | | --------------------- | :----------------------------------------------------------- | | Build Configuration | 编译配置名称,默认为Build-Configuration | | Build Mode | 编译方式。Remote Build:远端编译。Local Build:本地编译。 | | Deployment | Remote Build模式下显示该配置。可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 | | Environment variables | Remote Build模式下显示该配置。配置环境变量。 | | Target OS | Local Build模式下显示该配置。针对Ascend EP:选择昇腾AI处理器所在硬件环境的Host侧的操作系统。针对Ascend RC:选择板端环境的操作系统。 | | Target Architecture | Local Build模式下显示该配置。选择Target OS的操作系统架构。 | 编译成功之后会在在cmake-build目录下生成自定义算子安装包*.run 图14:算子编译成功## 8.算子部署 算子部署指将算子编译生成的自定义算子安装包(*.run)部署到OPP算子库中。在推理场景下,自定义算子直接部署到开发环境的OPP算子库。在训练场景下,自定义算子安装包需要部署到运行环境的OPP算子库中。 * 选择Ascend->Operator Deployment * 选择Operator Deploy Remotely 进行远程部署 * 设置Environment Variables * ASCEND_OPP_PATH=/usr/local/Ascend/ascend-toolkit/latest/opp * 点击Operator deploy进行部署 图15:算子部署参数设置| 参数 | 说明 | | --------------------- | :----------------------------------------------------------- | | Build Configuration | 编译配置名称,默认为Build-Configuration | | Deployment | Remote Build模式下显示该配置。可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 | | Environment variables | Remote Build模式下显示该配置。配置环境变量。 | 图16:算子部署成功
-
PyTorch 框架 AICPU 算子开发全流程(上):https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=187229&page=1&authorid=&replytype=&extra=#pid1461187 PyTorch 框架 AICPU 算子开发全流程(中):https://bbs.huaweicloud.com/forum/thread-187231-1-1.html PyTorch 框架 AICPU 算子开发全流程(下):https://bbs.huaweicloud.com/forumreview/thread-187233-1-1.html 详情指路视频专栏:https://www.bilibili.com/video/BV1nS4y1b7Km ## 八.LogSpace算子UT测试 1. **基本概念** MindStudio提供了基于gtest框架的新的UT测试方案,简化了开发者开发UT测试用例的复杂度。UT(Unit Test:单元测试)是开发人员进行单算子运行验证的手段之一,主要目的是: - 测试算子代码的正确性,验证输入输出结果与设计的一致性。 - UT侧重于保证算子程序能够跑通,选取的场景组合应能覆盖算子代码的所有分支(一般来说覆盖率要达到100%),从而降低不同场景下算子代码的编译失败率。 2. **前提条件** - 需完成自定义算子的开发,包括算子实现代码和算子原型定义。 - 安装CMake,要求版本为3.14及以上,若CMake版本不满足要求,请升级CMake版本。 - MindStudio已连接硬件设备。 3. **操作步骤** - 创建UT测试用例,有以下三种方式。 1. 右键单击算子工程根目录,选择“New Cases > AI CPU UT Case”。 2. 若已经存在了算子的UT测试用例,可以右键单击“testcases”目录。 3. 或者“testcases > ut”目录,选择“New Cases > AI CPU UT Case”,创建UT测试用例。  - 在弹出的算子选择界面,选择需要创建UT测试用例的算子,单击OK。创建完成后,会在算子工程根目录下生成testcases文件夹,并生成ut测试用例。 - 编写算子实现代码的UT C++测试用例。 在“testcases/ut/aicpu_test/reshape_cust/test_log_space_impl.cc”文件中,编写算子实现代码的UT C++测试用例,计算出算子执行结果,并取回结果和预期结果进行比较,来测试算子逻辑的正确性。 ``` TEST_F(LogSpaceTest, log_space_test_case_1) { vector> shapes = {{1}, {1}, {1, 10}, {1}}; vector data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT}; //输入输出数据定义 float input1[1] = {2}; float input2[1] = {10}; float output[10] = {(float)0}; float expect_out[10] = {4.0, 7.4069977, 13.715903, 25.398417, 47.031506, 87.09056, 161.2699, 298.63144, 552.9906, 1024.0}; vector datas = { (void *)input1, (void *)input2, (void *)output }; CREATE_NODEDEF(shapes, data_types, datas); CpuKernelContext ctx(DEVICE); EXPECT_EQ(ctx.Init(node_def.get()), 0); //定义算子 LogSpaceCpuKernel cpuKernel; //计算输入数据 cpuKernel.Compute(ctx); //对比计算输出是否正确 bool compare1 = CompareResult(output, expect_out, 6); EXPECT_EQ(compare1, true); } ``` - 编写算子原型定义的UT C++测试用例。在“testcases/ut/aicpu_test/reshape_cust/test_log_space_proto.cc”文件中,编写算子原型定义的UT C++测试用例,用于定义算子实例、更新算子输入输出并调用InferShapeAndType函数,最后验证InferShapeAndType函数执行过程及结果的正确性。 ``` TEST_F(LogSpaceTest, logspace_test_end_failed) { ge::op::LogSpace LogSpace_op; std::int64_t attr_value = 1; LogSpace_op.SetAttr("dtype", attr_value); std::int64_t num_steps_value = 4; LogSpace_op.SetAttr("steps", num_steps_value); ge::TensorDesc tensorStartDesc; ge::TensorDesc tensorEndDesc; ge::Shape shape0({1}); tensorStartDesc.SetDataType(ge::DT_FLOAT16); tensorStartDesc.SetShape(shape0); tensorStartDesc.SetOriginShape(shape0); LogSpace_op.UpdateInputDesc("start", tensorStartDesc); ge::Shape shape({2,3}); tensorEndDesc.SetDataType(ge::DT_FLOAT16); tensorEndDesc.SetShape(shape); tensorEndDesc.SetOriginShape(shape); LogSpace_op.UpdateInputDesc("end", tensorEndDesc); auto ret = LogSpace_op.VerifyAllAttr(true); EXPECT_EQ(ret, ge::GRAPH_FAILED); } ``` - 运行算子实现文件的UT测试用例。 开发人员可以执行当前工程中所有算子的UT测试用例,也可以执行单个算子的UT测试用例。   - 右键单击“**testcases/ut/aicpu_test**”文件夹,选择Run AI CPU Operator‘All’UT Impl with coverage,运行整个文件夹下算子实现代码的测试用例。 - 右键单击“**testcases/ut/aicpu_test**算子名称”文件夹,选择Run AI CPU Operator ‘算子名称’ UT Impl with coverage,运行单个算子实现代码的测试用例。 第一次运行时会弹出运行配置页面,请参考配置,然后单击Run。后续如需修改运行配置,请参考修改运行配置。 - **查看运行结果**。 运行完成后,通过界面下方的日志打印窗口,查看运行结果。结果中展示此次一共运行几个用例,如下图。 表6 UT测试参数配置信息| **参数** | **说明** | | -------------- | ------------------------------------------------------------ | | Name | 运行配置名称,用户可以自定义。 | | Test Type | 选择ut_impl。 | | Compute Unit | 选择计算单元:l AI Core/Vector Core;l AI CPU。选择不同的计算单元可以实现AI Core/Vector Core和AICPU_UT测试配置界面的切换。 | | Operator Name | 选择运行的测试用例。all表示运行所有用例。其他表示运行某个算子下的测试用例。 | | Case Names | 勾选需要运行的测试用例,即算子实现代码的UT C++测试用例。支持全选和全不选所有测试用例。 | ## 九.LogSpace算子ST测试 1. **概述** MindStudio提供了新的ST(System Test)测试框架,可以自动生成测试用例,在真实的硬件环境中,验证算子功能的正确性和计算结果准确性,并生成运行测试报告,包括: - 基于算子信息库生成算子测试用例定义文件。 - 基于算子测试用例定义文件生成不同shape、dtype的测试数据和基于AscendCL的测试用例。 - 编译算子工程并将算子部署到算子库,最后在硬件环境中执行测试用例,验证算子运行的正确性。 - 自动生成运行报表(st_report.json)功能,报表记录了测试用例信息及各阶段运行情况。 - 根据用户定义并配置的算子期望数据生成函数,回显期望算子输出和实际算子输出的对比测试结果,验证计算结果的准确性。 2. **前提条件** - 完成自定义算子的开发,请参见算子代码实现、算子原型定义、算子信息库定义。 - lMindStudio已连接硬件设备。 3. **生成ST测试用例定义文件** - 创建ST测试用例。有以下三种入口: 1) 右键单击算子工程根目录,选择“**New Cases > ST Case**”。 2) 右键单击算子信息定义文件:{工程名}**/cpukernel/op_info_cfg/aicpu_kernel/ xx.ini**,选择“**New Cases > ST Case**”。 3) 若已经存在了对应算子的ST Case,可以右键单击“testcases”目录,或者“**testcases > st**”目录,选择“**New Cases > ST Case**”,追加ST测试用例。 - 在弹出的“Create ST Cases for an Operator”界面中选择需要创建ST测试用例的算子。如下图所示。  1. Operator Name:下拉选择算子名称。 2. SoC Version:下拉选择昇腾AI处理器的类型。若对AI CPU算子进行ST测试,默认选择aicpu_kernel。 3. 单击“OK”后,工具会自动根据首层shape信息dump出选择算子的shape信息,生成对应的算子测 试用例定义文件。  - 配置算子测试用例定义文件。在算子测试用例文件中配置算子期望数据生成函数。有两种场景,分别为Design视图和Text视图下进行配置。 - 若在Design视图下,可以手动编写输入输出设置,以及属性的设置。 - 若在Text视图下,可以以编写json文件的方式,设置输入输出和属性的设置 2.修改Case信息后,单击“Save”,修改会保存到算子测试用例定义文件。算子测试用例定义文件存储目录为算子工程根目录下的“ testcases/st/OpType/ aicpu_kernel”文件夹下,命名为LogSpace_case_20220415185113.json ``` { "case_name":"Test_Cast_002", "op":"Cast", "calc_expect_func_file":"", "gui_calc_expect_func_file":"", "input_desc":[ { "name":"x_tensor", "format":[ "ND" ], "type":[ "int32" ], "shape":[ 2, 3 ], "value_range":[ [ 0.1, 10.0 ] ], "data_distribute":[ "uniform" ], "value":[ [ 2, 3, 5 ], [ 6, 80, 20 ] ] } ], "output_desc":[ { "format":[ "ND" ], "type":[ "int64" ], "shape":[ 2, 3 ] } ], "attr":[ { "name":"dst_type", "value":9, "type":"int" } ] }, ``` 6. **运行ST测试用例。**右键单击生成ST测试用例定义文件中生成的ST测试用例定义文件(路径:“**testcases> st > add > aicpu_kernel >xxxx.json**”),选择“**Run ST Case 'xxx**'”。 表7运行配置信息| **参数** | **说明** | | ---------------------------- | ------------------------------------------------------------ | | **Name** | 运行配置名称,用户可以自定义。 | | **Test Type** | 选择st_cases 。 | | **Execute Mode** | Remote Execute 远程执行测试Local Execute 本地执行测试说明:Local Execute不支持Windows操作系统。 | | **Deployment** | 当Execute Mode选择Remote Execute时deployment功能,详细请参见[Deployment](https://www.hiascend.com/document/detail/zh/mindstudio/304/atlasms_02_0371.html),可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 | | **CANN Machine** | CANN工具所在设备deployment信息。说明:该参数仅支持Windows操作系统。 | | **Environment Variables** | 在文本框中添加环境变量:PATH_1=路径1;PATH_2=路径2多个环境变量用英文分号隔开。也可以点击文本框后的图标,在弹出的对话框中填写。在Name中输入环境变量名称:PATH_1。在Value中输入环境变量值:路径1。勾选Instead system environment variables可以显示系统环境变量。 | | **Operator Name** | 选择需要运行的算子。 | | **SoC Version** | 配置 昇腾AI处理器的类型。 | | **Product Form** | 配置产品形态。若SoC Version配置为Ascend310时显示该配置项。EPRC | | **Executable File Name** | 下拉选择需要执行的测试用例定义文件。若对AI CPU算子进行ST测试,测试用例文件前有(AI CPU)标识。 | | **Target OS** | 针对Ascend EP:选择昇腾AI处理器所在硬件环境的Host侧的操作系统。针对Ascend RC:选择板端环境的操作系统。 | | **Target Architecture** | 选择Target OS的操作系统架构。 | | **Case Names** | 选择运行的Case Name。说明:默认全选所有用例,可以去除勾选部分不需要运行的用例。 | | **Enable Auto Build&Deploy** | 选择是否在ST运行过程中执行编译和部署。 | | **Advanced Options** | 高级选项 | | **ATC Log Level** | 选择ATC 日志级别INFODEBUGWARNINGERRORNULL | | **Precision Mode** | 精度模式force_fp16allow_mix_precisionallow_fp32_to_fp16must_keep_origin_dtype | | **Device Id** | 设备ID,设置运行ST测试的芯片ID。用户根据使用的AI芯片ID填写。 | | **Error Threshold** | 配置自定义精度标准,取值为含两个元素的列表:[val1,val2]val1:算子输出结果与标杆数据误差阈值,若误差大于该值则记为误差数据。val2:误差数据在全部数据占比阈值。若误差数据在全部数据占比小于该值,则精度达标,否则精度不达标。取值范围为[0.0,1.0]。 | | **Compile Settings** | 编译设置按钮,单击按钮后弹出对话框,可以在对话框中配置以下内容。Include Directories:第三方库的头文件路径,支持多路径输入,中间用英文冒号分隔。Link Directories:库路径,支持多路径输入,中间用英文冒号分隔。Link Libraries:库,支持多文件输入,中间用英文冒号分隔。须知:该出的配置项会添加到算子工程目录下“cpukernel/CMakeLists.txt”文件中。最新的配项会覆盖上一次配置项。第三方库在Ascend310和Ascend910处理器上需用Hccl编译器生成,在RC场景需用交叉编译器生成。仅算子实现文件编译时使用该配置。 | 7. **运行后会输出测试用例总数**,成功用例总数,失败用例总数,错误用例总数。  ## 十.经验总结 1. 编写算子信息库文件**cpukernel/op_info_cfg/aicpu_kernel/log_space.ini**时,要确保文件没有多余的空行或者其他符号,否则编译会报如下错误。  2. 编译算子工程前,先检查一下配置参数,如果缺少环境变量直接编译会报如下错误  点击Build > Edit Build Configuration...进入编译配置页面。检查Environment Variables配置是否配置完整,点击输入框右边文档图标,查看环境变量配置,确保对应参数路径正确,如图:  3. 算子部署前需要先编译成功,生成custom_opp_××××.run,部署的时候会自动检测Operator Package是否存在,否则Operator Package检测不到,会导致如下图所示  这时候直接运行会导致如下错误。  ## 十一.关于MindStudio更多的内容 如果需要了解关于MindStudio更多的信息,请查阅昇腾社区中MindStudio的[用户手册](https://www.hiascend.com/document/detail/zh/mindstudio/304/progressiveknowledge/index.html),里面有算子开发、模型开发等各种使用操作的详细介绍。 如果在使用MindStudio过程中遇到任何问题,也可以在昇腾社区中的[昇腾论坛](https://www.huaweicloud.com/s/JU1pbmRTdHVkaW_mkK3lu7ol/t_60_p_1)进行提问,会有华为内部技术人员对其进行解答,如下图。 
-
【功能模块】【操作步骤&问题现象】1、我在本机idea上 执行sparksql 查询hive库的数据 报错2、已经hive的相关配置文件放在resources下、 jar包也是从集群上的spark下的lib下导出来的,请问还需要配置说明东西 谢谢【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
### 一、概述 算子开发通常包括以下步骤: - 算子分析 - 创建算子工程 - 算子实现 - 编译 - UT测试 - ST测试 - 部署 下面介绍使用MindStudio完成一个简单TBE算子的整个开发过程。我们可以从 _[这里](https://www.hiascend.com/software/mindstudio/download)_ 获取MindStudio的版本,CANN的版本需要跟MindStudio配套。 注意:如果图片看不见,可以直接到[这里](https://gitee.com/ascend/mindstudio-samples/wikis/%E4%B8%9A%E5%8A%A1%E5%BC%80%E5%8F%91%E6%8C%87%E5%AF%BC/%E7%AE%97%E5%AD%90%E5%BC%80%E5%8F%91%E6%8C%87%E5%AF%BC)查看原文; ### 二、算子分析 进行算子开发前,开发者应首先进行算子分析,算子分析包含:明确算子的功能及数学表达式,选择算子开发方式(DSL方式或者TIK方式),最后细化并明确算子规格,分析流程如下所示: 图4-1 算子分析流程  如何分析可以参考[算子分析](https://support.huawei.com/enterprise/zh/doc/EDOC1100234139/f43ef24b) 这里我们举例开发一个支持计算两个输入tensor的和的算子Add。 ### 三、创建算子工程 1.启动MindStudio,在欢迎界面点击New Project按钮,弹出创建工程的界面;  2.左边的选项卡选择Ascend Operator,右边界面中Name编辑框填写Add,点击Next按钮;  3.填写相关参数,New Operator选择Empty Template,表示创建一个空的工程模板;Operator Type填Add;Plugin Framework选择TensorFlow,表明该算子是原始框架为TensorFlow的自定义算子;Unit Type根据实际情况选择,如果算子要支持运行在Ascend310芯片上,那么就选择Ascend310-AI Core,可以多选其他芯片类型,这里使用训练服务器,所以勾选Ascend910A-AI Core;点击Finish按钮,会生成一个模板工程。  工程目录下主要包括算子原型文件、实现文件、信息库文件和插件适配文件。算子的实现开发主要是针对这四类文件进行开发。  ### 四、算子实现 1. 算子原型定义 算子原型定义规定了在昇腾AI处理器上可运行算子的约束,主要体现算子的数学含义,包含定义算子输入、输出、属性和取值范围,基本参数的校验和shape的推导,原型定义的信息会被注册到GE的算子原型库中。离线模型转换时,GE会调用算子原型库的校验接口进行基本参数的校验,校验通过后,会根据原型库中的推导函数推导每个节点的输出shape与dtype,进行输出tensor的静态内存的分配。 Add算子原型头文件add.h: ``` /** * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the Apache License Version 2.0.You may not use this file except in compliance with the License. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Apache License for more details at * http://www.apache.org/licenses/LICENSE-2.0 * * Description: Huawei Code * * Author: Huawei * * Create: 2020-01-01 * */ #ifndef GE_OPS_OP_PROTO_ADD_H_ #define GE_OPS_OP_PROTO_ADD_H_ #include "graph/operator_reg.h" namespace ge { REG_OP(Add) .INPUT(x1, TensorType({DT_FLOAT, DT_INT32, DT_INT64, DT_FLOAT16, DT_INT16, DT_INT8, DT_UINT8, DT_DOUBLE, DT_COMPLEX128, DT_COMPLEX64, DT_STRING})) .INPUT(x2, TensorType({DT_FLOAT, DT_INT32, DT_INT64, DT_FLOAT16, DT_INT16, DT_INT8, DT_UINT8, DT_DOUBLE, DT_COMPLEX128, DT_COMPLEX64, DT_STRING})) .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT64, DT_FLOAT16, DT_INT16, DT_INT8, DT_UINT8, DT_DOUBLE, DT_COMPLEX128, DT_COMPLEX64, DT_STRING})) .OP_END_FACTORY_REG(Add) } #endif //GE_OPS_OP_PROTO_ADD_H_ ``` Add算子原型源文件add.cc: ``` /** * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the Apache License Version 2.0.You may not use this file except in compliance with the License. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Apache License for more details at * http://www.apache.org/licenses/LICENSE-2.0 * * Description: Huawei Code * * Author: Huawei * * Create: 2020-01-01 * */ #include "./add.h" #include #include namespace ge { bool InferShapeAndTypeAdd(Operator &op, const string &inputName1, const string &inputName2, const string &outputName) { TensorDesc vOutputDesc = op.GetOutputDescByName(outputName.c_str()); DataType inputDtype = op.GetInputDescByName(inputName1.c_str()).GetDataType(); Format inputFormat = op.GetInputDescByName(inputName1.c_str()).GetFormat(); // 针对shape维度大小进行交换 ge::Shape shapeX = op.GetInputDescByName(inputName1.c_str()).GetShape(); ge::Shape shapeY = op.GetInputDescByName(inputName2.c_str()).GetShape(); std::vector dimsX = shapeX.GetDims(); std::vector dimsY = shapeY.GetDims(); if (dimsX.size() dimsY.size()) { std::vector dimsTmp = dimsX; dimsX = dimsY; dimsY = dimsTmp; } // 对小的shape进行1补齐 if (dimsX.size() != dimsY.size()) { int dec = dimsX.size() - dimsY.size(); for (int i = 0; i dec; i++) { dimsY.insert(dimsY.begin(), (int64_t)1); } } // 设置输出的shape维度 std::vector dimVec; for (size_t i = 0; i dimsX.size(); i++) { if ((dimsX[i] != dimsY[i]) && (dimsX[i] != 1) && (dimsY[i] != 1)) { return false; } int64_t dims = dimsX[i] > dimsY[i] ? dimsX[i] : dimsY[i]; dimVec.push_back(dims); } ge::Shape outputShape = ge::Shape(dimVec); vOutputDesc.SetShape(outputShape); vOutputDesc.SetDataType(inputDtype); vOutputDesc.SetFormat(inputFormat); op.UpdateOutputDesc(outputName.c_str(), vOutputDesc); return true; } // ----------------Add------------------- IMPLEMT_VERIFIER(Add, AddVerify) { if (op.GetInputDescByName("x1").GetDataType() != op.GetInputDescByName("x2").GetDataType()) { return GRAPH_FAILED; } return GRAPH_SUCCESS; } // Obtains the processing function of the output tensor description. IMPLEMT_COMMON_INFERFUNC(AddInferShape) { if (InferShapeAndTypeAdd(op, "x1", "x2", "y")) { return GRAPH_SUCCESS; } return GRAPH_FAILED; } // Registered inferfunction COMMON_INFER_FUNC_REG(Add, AddInferShape); // Registered verify function VERIFY_FUNC_REG(Add, AddVerify); // ----------------Add------------------- } // namespace ge ``` 更多可以参考[算子原型定义](https://support.huawei.com/enterprise/zh/doc/EDOC1100234139?section=j00s) 2. 算子代码实现 算子计算逻辑及调度的实现。 Add算子实现文件add.py: ``` #!/usr/bin/env python # -*- coding:utf-8 -*- """ Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the Apache License Version 2.0.You may not use this file except in compliance with the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache License for more details at http://www.apache.org/licenses/LICENSE-2.0 add """ from __future__ import absolute_import import tbe.dsl as tbe from functools import reduce from tbe import tvm from tbe.common.register import register_op_compute from tbe.common.utils import para_check from tbe.common.utils import shape_util # General limitation of the reduce size for input shape: 2**31 SHAPE_SIZE_LIMIT = 2147483648 # pylint: disable=locally-disabled,too-many-arguments,unused-argument @register_op_compute("Add", op_mode="dynamic", support_fusion=True) def add_compute(input_x, input_y, output_z, kernel_name="add"): """ calculating data's add, c = a + b Parameters ---------- input_x: TVM tensor the placeholder of first input data input_y: TVM tensor the placeholder of second input data output_data: dict shape and dtype of output, should be broadcast shape and type as input kernel_name: str cce kernel name, default value is add Returns ------- res : output of the data's add """ shape_x = shape_util.shape_to_list(input_x.shape) shape_y = shape_util.shape_to_list(input_y.shape) shape_x, shape_y, shape_max = \ shape_util.broadcast_shapes(shape_x, shape_y, param_name_input1="input_x", param_name_input2="input_y") shape_size = reduce(lambda x, y: x * y, shape_max[:]) if shape_size > SHAPE_SIZE_LIMIT: raise RuntimeError("the shape is too large to calculate") input_x = tbe.broadcast(input_x, shape_max) input_y = tbe.broadcast(input_y, shape_max) res = tbe.vadd(input_x, input_y) return res @para_check.check_op_params(para_check.REQUIRED_INPUT, para_check.REQUIRED_INPUT, para_check.REQUIRED_OUTPUT, para_check.KERNEL_NAME) def add(input_x, input_y, output_z, kernel_name="add"): """ algorithm: add calculating data's add, c = a + b Parameters ---------- input_x : dict shape and dtype of first input, only support float16, float32, int32 input_y : dict shape and dtype of second input, only support float16, float32, int32 output_z: dict shape and dtype of output, should be broadcast shape and type as input kernel_name : str cce kernel name, default value is add Returns ------- None """ shape_x = input_x.get("shape") shape_y = input_y.get("shape") check_tuple = ("float16", "float32", "int32") input_data_type = input_x.get("dtype").lower() para_check.check_dtype(input_data_type, check_tuple, param_name="input_x") shape_x, shape_y, shape_max = \ shape_util.broadcast_shapes(shape_x, shape_y, param_name_input1="input_x", param_name_input2="input_y") if shape_x[-1] == 1 and shape_y[-1] == 1 and shape_max[-1] == 1: shape_x = shape_x if len(shape_x) == 1 else shape_x[:-1] shape_y = shape_y if len(shape_y) == 1 else shape_y[:-1] shape_max = shape_max if len(shape_max) == 1 else shape_max[:-1] data_x = tvm.placeholder(shape_x, name="data_1", dtype=input_data_type) data_y = tvm.placeholder(shape_y, name="data_2", dtype=input_data_type) res = add_compute(data_x, data_y, output_z, kernel_name) with tvm.target.cce(): schedule = tbe.auto_schedule(res) config = {"print_ir": False, "name": kernel_name, "tensor_list": (data_x, data_y, res)} tbe.build(schedule, config) ``` 3. 算子信息库定义 算子信息库文件用于将算子的相关信息注册到算子信息库中,包括算子的输入输出dtype、format以及输入shape信息。离线模型转换时,FE会根据算子信息库中的算子信息做基本校验,判断是否需要为算子插入合适的转换节点,并根据算子信息库中信息找到对应的算子实现文件进行编译,生成算子二进制文件进行执行。 算子信息库文件add.ini: ``` [Add] input0.name=x1 input0.dtype=float16,float16,float16,float16,float,float,float,float,int32,int32,int32,int32 input0.shape=all input0.paramType=required input0.format=NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND input1.name=x2 input1.dtype=float16,float16,float16,float16,float,float,float,float,int32,int32,int32,int32 input1.shape=all input1.paramType=required input1.format=NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND output0.name=y output0.dtype=float16,float16,float16,float16,float,float,float,float,int32,int32,int32,int32 output0.shape=all output0.paramType=required output0.format=NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND opFile.value=add opInterface.value=add ``` 更多参考[算子信息库定义](https://support.huawei.com/enterprise/zh/doc/EDOC1100234139?section=j01i) 4. 算子适配 基于第三方框架(TensorFlow/Caffe)进行自定义算子开发的场景,开发人员需要进行插件的开发,将基于第三方框架的算子属性映射成适配昇腾AI处理器的算子属性。 Add算子插件适配文件tensorflow_add_plugin.cc: ``` /** * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the Apache License Version 2.0.You may not use this file except in compliance with the License. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Apache License for more details at * http://www.apache.org/licenses/LICENSE-2.0 * * Description: Huawei Code * * Author: Huawei * * Create: 2020-01-01 * */ #include "register/register.h" namespace domi { REGISTER_CUSTOM_OP("Add") .FrameworkType(TENSORFLOW) .OriginOpType({ge::AscendString("Add")}) .ParseParamsByOperatorFn(AutoMappingByOpFn) .ImplyType(ImplyType::TVM); } // namespace domi ``` 更多参考[算子适配插件开发](https://support.huawei.com/enterprise/zh/doc/EDOC1100234139?section=j01k) ### 五、编译 点击Build->Edit Build Configuration..菜单,弹出的对话框中选择Local Build,Target Architecture选择AI服务器的架构,我们这里的服务器是鲲鹏的训练服务器,所以选aarch64(需要提前安装好对应版本的CANN),点击Build按钮。   查看输出窗口,看到编译成功,且在cmake-build目录下生成了自定义算子Run包custom_opp_Linux_x86_64.run,该run包可以单独拿到其他开发或者运行环境部署。  ### 六、UT测试 我们可以对算子的实现进行UT单元测试,验证算子实现是否正确。算子的UT是通过在开发机器上将算子运行在昇腾芯片的仿真器来验证的。 在工程树的根目录鼠标右键,弹出的菜单中选择New Cases->TBE UT Case,弹出的窗口中Operator Name选择add算子,点击OK,创建UT文件模板。    针对test_add_impl.py文件,我们可以修改这个文件增加算子实现的UT测试用例代码。 test_add_impl.py内容: ``` #!/usr/bin/env python # -*- coding:utf-8 -*- """ Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the Apache License Version 2.0.You may not use this file except in compliance with the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache License for more details at http://www.apache.org/licenses/LICENSE-2.0 test_add_impl """ from op_test_frame.ut import BroadcastOpUT ut_case = BroadcastOpUT("Add") def calc_expect_func(input_x, input_y, output_z): """ get expect output :param input_x:tensor x :param input_y: tensor y :param output_z: output placeholder :return:output tensor """ res = input_x["value"] + input_y["value"] return [res, ] ut_case.add_precision_case("all", { "params": [{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "input"}, {"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "input"}, {"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "output"}], "calc_expect_func": calc_expect_func }) ``` 修改完成后,鼠标右键点击test_add_impl.py文件,弹出的菜单中选择Run TBE Operator,弹出配置窗口,SoC Version选择Ascend910,Target 选择Simulator_TMModel,Operator Name选择add,Case Names中全选用例,然后点击Run。查看输出窗口,可以看到用例是否都跑成功了。  算子原型也可以进行UT测试,修改test_add_proto.cpp如下: ``` #include gtest.h> #include #include "add.h" class AddTest : public testing::Test { protected: static void SetUpTestCase() { std::cout "add test SetUp" std::endl; } static void TearDownTestCase() { std::cout "add test TearDown" std::endl; } }; TEST_F(AddTest, add_test_case_1) { // define op ge::op::Add addOp; ge::TensorDesc tensorDesc; ge::Shape shape({2, 3, 4}); tensorDesc.SetDataType(ge::DT_FLOAT16); tensorDesc.SetShape(shape); tensorDesc.SetOriginShape(shape); // update op input addOp.UpdateInputDesc("x1", tensorDesc); addOp.UpdateInputDesc("x2", tensorDesc); // call InferShapeAndType function auto ret = addOp.InferShapeAndType(); EXPECT_EQ(ret, ge::GRAPH_SUCCESS); // compare dtype and shape of op output auto outputDesc = addOp.GetOutputDescByName("y"); EXPECT_EQ(outputDesc.GetDataType(), ge::DT_FLOAT16); std::vector expectedOutputShape = {2, 3, 4}; EXPECT_EQ(outputDesc.GetShape().GetDims(), expectedOutputShape); } ``` ### 七、ST测试 在工程树的根目录鼠标右键,弹出的菜单中选择New Cases->ST Case,弹出的窗口中Operator Name选择add算子,SoC Version选择ascend910,点击OK。  创建ST用例json文件。 默认生成了一个ST用例,修改输入输出的shape为[8,16,8,16]。点击Run按钮,弹出运行配置窗口,选择Local Execute,勾选用例,点击Run按钮。在最下方的Run窗口,可以看到运行结果,所有的用例是否都运行通过了。    ### 八、部署 点击Ascend->Operator Deployment菜单,弹出的窗口中选择Operator Deploy Locally,Operator Package默认是我们刚才编译出来的算子Run包,点击Operator deploy按钮,算子相关交付件会部署到CANN的opp的自定义算子目录下。 
-
很荣幸参加《鲲鹏Java性能分析工具IntelliJ插件实现》项目开发工作的,我们项目主要是做Inellij插件开发实现性能分析工具功能。由于插件开发的特殊性,常常需要和一些命令行打交道,下面记录一次通过Java代码打开Windows证书安装窗口安装证书cer文件。思路如下:第一步:下载证书,保存到本地 通过cer文件下载接口将文件保存到本地,记录文件的保存位置第二步:通过代码在IDEA的Terminal命令窗口输入命令打开证书安装窗口 // 将项目对象,ToolWindow的id传入,获取控件对象 ToolWindow toolWindow = ToolWindowManager.getInstance(e.getProject()).getToolWindow("Terminal"); if (toolWindow != null) { // 无论当前状态为关闭/打开,进行强制打开ToolWindow toolWindow.show(new Runnable() { @Override public void run() { Process p = Runtime.getRuntime().exec("rundll32.exe cryptext.dll,CryptExtAddCER "+ path); } }); } }第三步:提醒用户重启IDEA,使证书生效 Messages.showMessageDialog("安装证书", "安装证书后请重启IDEA,证书才能生效", Messages.getInformationIcon());
-
IDEA是目前Java开发人员最受欢迎的工具开发之一,很重要的原因是其提供了很多插件,这让开发人员降低了开发难度,能更有效更高质量的开发代码,我也很荣幸成为IDEA插件开发的一员。 我所在的是鲲鹏Java性能分析工具IntelliJ这个开源项目,刚开始参与进来的时候感觉这个项目很难,因为对Java Swing这块的技术了解的很少。长时间下来感觉挺有意思的,以下我是我对Swing这块的总结: Swing图形组件是java中一套图形界面类,主要分为两类:容器类和元素类。容器类表示可以放置其他的元素组件或者容器组件,JFrame 窗体组件,JPanel 面板容器,JMeauBar 菜单栏;元素类表示不可以放其他的组件,比如:JButton 按钮组件,JLable 文本标签组件,JTextField 文本输入框组件,JPasswordField 密码输入框组件,JCheckBox 复选框组件等。主要就是在合理布局下各种组件之间的搭配,其中还有很多重要的事件,如:ActionEvents,ChangeEvents,ItemEvents等,来响应用户的鼠标点击等行为。 每当感觉自己已经掌握了Swing这门技术的时候,但是在开发过程中处处有惊喜,总会碰到这样或那样的难题,因此还是得通过不断的学习来提高自己,这样才能更好、更有效更轻松的为这个团队服务。加油!
-
新版Notebook提供了远程开发功能,通过开启SSH连接,用户本地IDE可以远程连接到ModelArts的Notebook开发环境中,调试和运行代码。对于使用本地IDE的开发者,由于本地资源限制,运行和调试环境大多使用团队公共搭建的CPU或GPU服务器,并且是多人共用,这带来一定的环境搭建和维护成本。而ModelArts的Notebook的优势是即开即用,它预先装好了不同的AI引擎,并且提供了非常多的可选规格,用户可以独占一个容器环境,不受其他人的干扰。只需简单配置,用户即可通过本地IDE连接到该环境进行运行和调试。图1 本地IDE远程访问Notebook开发环境ModelArts的Notebook可以视作是本地PC的延伸,均视作本地开发环境,其读取数据、训练、保存文件等操作与常规的本地训练一致。对于习惯使用本地IDE的开发者,使用远程开发方式,不影响用户的编码习惯,并且可以方便快捷的使用云上的Notebook开发环境。本地IDE当前支持VSCode、PyCharm、SSH工具。还有专门的插件PyCharm Toolkit和VSCode Toolkit,更方便将云上资源作为本地的一个扩展。
-
# `npustat` 链接:[https://github.com/wmc1992/npustat](https://github.com/wmc1992/npustat) 一个能够简洁的显示华为atlas设备状态的命令行工具; 之前使用GPU时习惯了使用工具 [`gpustat`](https://github.com/wookayin/gpustat) 查看GPU状态,使用华为的Atlas设备之后发现并没有类似的工具,于是仿照 [`gpustat`](https://github.com/wookayin/gpustat) 自己写了一个; 显示效果如下图: 主要解决命令 `npu-smi info` 的两个缺点: * 显示的信息总是特别长,笔记本单屏显示不下; * `watch` 下,同一芯片每次展示不在屏幕的同一位置,观察该芯片的变化较困难; ## 依赖说明 python版本要求:`python>=3.6`; 基础软件方面依赖说明: 华为Atlas设备目前有两种方式可以获取加速卡的状态信息:`ascend-dmi -i` 和 `npu-smi info`,这两者的区别为: * 命令 `ascend-dmi -i`: * 优点: * 查询结果为json格式,易于解析,不会出错; * 查询结果中包含实时功率信息; * 缺点: * 速度较慢,每次查询耗时约2~3秒; * 需要安装了 `toolbox` 工具包并正确配置了环境变量; * 命令 `npu-smi info`: * 优点: * 查询速度快,每次查询小于1秒; * 只要正确安装了驱动即可,不需要额外安装其他包; * 缺点: * 查询结果中不包含实时功率信息; * 查询结果无法以json格式返回,解析容易出错,遇到错误时欢迎反馈; 默认使用命令 `ascend-dmi -i` 做查询,可以使用参数 `--use-npu-smi` 修改为使用命令 `npu-smi info` 做查询; 目前仅在配备了4张 `Atlas 300I-3000` 推理卡的 Atlas 500 服务器上进行过测试;所以在其他设备上难免会有问题,欢迎反馈问题;有任何优化建议也欢迎反馈; > 注:若要安装 `toolbox` 需要注意,华为的 `toolbox` 工具包相关的版本体系出现过多次变迁: > > * 在`CANN`的`v5.0.1`及以前版本,`toolbox` 工具包归属到`CANN`中,可在`CANN`的软件下载链接中进行下载; > * 在`CANN`的`v5.0.2`及以后的版本中不再包含`toolbox` 工具包,而是迁移到了`mindx`中,需要到`mindx`的软件下载链接中进行下载; ## 安装说明 从 [PyPI](https://pypi.org/project/npustat/) 进行安装: ``` pip install npustat ``` ## 使用说明 使用如下命令单次获取当前atlas设备信息: ``` npustat ``` 使用如下命令动态刷新当前atlas设备信息,默认每2秒刷新一次: ``` npustat --watch ``` 可选参数如下: ``` usage: cli.py [-h] [--json] [-i [INTERVAL]] [--no-header] [--no-title] [--use-npu-smi] [--show-power] [--compact] [--debug] [-v] optional arguments: -h, --help show this help message and exit --json 将所有结果输出为JSON格式; -i [INTERVAL], --interval [INTERVAL], --watch [INTERVAL] 动态刷新模式;INTERVAL为刷新间隔,单位:秒;默认每2秒刷新一次; --no-header 是否隐藏 header 信息;header 信息包含机器名称、当前时间、版本号;默认展示 header 信息,配置该参数后 header 信息不再展示; --no-title 是否隐藏 title 信息;title 信息为对当前设备状态值各字段的说明;默认展示 title 信息,配置该参数后 title 信息不再展示; --use-npu-smi 使用命令"npu-smi info"获取当前设备状态值;注意该命令无法获取到加速卡的实时功率信息; --show-power 是否展示加速卡的功率信息,默认为展示;配置了参数 "--use-npu-smi" 之后该参数无效; --compact 是否采用紧凑模式展示信息,默认为不采用;紧凑模式下会去掉空白行及其他无意义的行,适用于加速卡较多,显示器较小,屏幕显示不下的情况; --debug Debug模式时允许在程序出错的情况下打印更多的调试信息; -v, --version show program's version number and exit ``` #### 常规模式与紧凑模式对比 | `npustat --watch` | `npustat --watch --compact` | | :-: | :-: | |  |  | #### 另外: 比较遗憾的是,目前我没有在任何华为的官方文档中找到获取每个设备上运行了哪些进程的功能,在昇腾论坛的询问结果也是如此:[【Atlas 300I 推理卡】怎样查看有哪些进程正在上面运行? ](https://bbs.huaweicloud.com/forum/thread-173510-1-1.html) 所以本项目也不具有显示每个设备上运行了哪些进程的功能;如有人知道如何获取每个atlas上运行了哪些进程,还请告知; ## 显示内容说明 ``` machine_name Mon Dec 20 22:38:59 2021 ascend-dmi version: 2.0.3 ======================================================== [加速卡ID], 加速卡类型, 功率 [芯片ID] [DeviceID] Health, 芯片名称 | 温度, AICore, 内存 ======================================================== [1], Atlas 300I-3000, 16.30 W [0] [1] OK, Ascend 310 | 51°C, 0 %, 2621 MB / 8192 MB ``` * header:第1行为header,可以使用参数 `--no-header` 不展示该信息;展示的信息从左到右依次为机器名称、当前时间、软件 `ascend-dmi/npu-smi` 的版本; * title:第2~5行为title,可以使用参数 `--no-title` 不展示该信息;title是对后面展示的信息的各字段的说明; * `[1], Atlas 300I-3000, 16.30 W`:每个加速卡的信息 * `[1]`:加速卡ID; * `Atlas 300I-3000`:加速卡类型; * `16.30 W`: 加速卡实时功率; * `[0] [1] OK, Ascend310| 51°C, 0%,2621MB/8192MB`:每个芯片的信息 * `[0]`:芯片ID; * `[1]`:DeviceID; * `OK`:芯片健康状态; * `Ascend 310`:芯片名称; * `51°C`:温度; * `0 %`:AICore; * `2621 MB / 8192 MB`:内存;
-
今日热文:原文链接:https://blog.csdn.net/qq_43529978/article/details/122415668你觉得说的对吗?俗话说,工欲善其事,必先利其器,一名好的开发者,必然要有一套好的开发工具,这样才能打造出最好的产品给用户。世界上的IDE种类繁多,要论那个IDE好用,可能有人会选择老牌的Visual Studio 或是Eclipse;也有人会选择使用者人数一路飙升的Intellij;也有人更偏爱Google发布的Android Studio。每位开发者都会按照自己的需求及爱好对IDE做出不同的选择。其中,对于老牌IDE Eclipse来说,众多开发者真的是又爱又恨。曾几何时,在当初那个IDE稀少又昂贵的时期,Eclipse给开发者带来了福音。作为一款免费且开源,速度相对更快,又有Google支持,在各种教科书中备受推崇的IDE,真的是想不流行都难。但在此之后各种IDE百花齐放,Eclipse的各种弊端也逐渐显现,慢慢开始走下神坛。Eclipse的优势Eclipse最初只是一个开源的框架平台,主要是作为Java语言的开发平台。它由IBM公司开发,其目的是为了替代商业软件Visual Age for Java,成为下一代开发环境。Eclipse在2001年被IBM公司贡献给开源社区,之后Eclipse联盟成立为现在的Eclipse基金会,Eclipse自此由其管理。作为一个开源框架,Eclipse拥有很高的灵活性,它可以通过众多插件来获取不同的功能与编程语言支持。也就意味着,开发者可以根据自己的需求,在Eclipse源代码的基础上开发插件,理论上Eclipse可以无限拓展,利用插件成为任何语言的开发工具,也可以通过新插件扩展现有插件的功能。现如今Eclipse就已经拥有插件支持其成为C++、Python、PHP等主流语言的开发工具。也有不少软件开发商以Eclipse为基础框架开发自己的IDE。这些也正是Eclipse所具有的优势。弊端明显,逐渐被取代但相比Eclipse的优势来说,它所拥有的弊端更加明显,其实在2012年Eclipse 发布代号为Luna的4.2版本之前,Eclipse还没有这么多让人诟病的地方,也还没有开始走下坡路。自从4.2版本上线后,各种弊端逐渐显现,但开发者们对此也只能忍着,毕竟Eclipse是为数不多的免费IDE中比较好用的一个,随着Intellij社区版本,免费的Android Studio以及微软的Visual Studio Code的发布,这些新兴IDE疯狂的占据Eclipse的市场份额。使Eclipse神坛上的地位彻底被摧毁。下图是来自PYPL PopularitY of Programming Language index 的TOP 10 IDE排名,该网站的IDE指数是通过分析集成开发环境(IDE)在Google上被搜索下载的频率而创建的。IDE被搜索的次数越多,就认为该IDE越受欢迎。该指数原始数据来源于Google。图片来源PYPL PopularitY of Programming Language index图片来源PYPL PopularitY of Programming Language index从以上数据我们可以看到自2011年1月至2022年1月,Eclipse的搜索下载频率大幅度降低,从51.54%降低至14.05%,这说明人们对于Eclipse的关注度在飞速降低。而相反的Visual Studio Code自从2015年发布以来搜索率飞速上涨。Visual Studio 也再缓慢稳步上升。相比其他的主流IDE,Eclipse的运行占用了更多的内存空间,由于Eclipse的众多插件的存在,每次运行都会占据大量的设备运行内存,这就会导致配置稍微差点的设备在运行Eclipse的时候非常卡。除此之外Eclipse的运行速度相比较其他新兴的IDE也更加缓慢。Eclipse P2的项目的目的是为了让插件的升级更加简单。插件作为Eclipse赖以生存的重要组成部分。Eclipse P2项目可说是非常重要。然而,它最终却让插件升级变得复杂。由于这个原因它最主要的功能安装Eclipse插件,也不像以前那么好用了。在安装插件的时候,这样的对话框随处可见。在著名的计算机新闻网站Hacker News上就有人在为Eclipse的衰落感到悲哀,但是下面的评论却基本没有对此的惋惜,反而是在表示Eclipse的结局本就该如此,毕竟相比优势来说,它的缺陷真的太多了。其实Eclipse的衰落对各种开发人员来说并不算是好事,毕竟没有了Eclipse的竞争,其他的IDE也不会像以前那样为了超越它,去努力的创新了。希望Eclipse基金会能改变现如今Eclipse的弊端,重新走上神坛。参考链接:https://news.ycombinator.com/item?id=29867360
上滑加载中
推荐直播
-
探秘仓颉编程语言:华为开发者空间的创新利器
2025/02/22 周六 15:00-16:30
华为云讲师团
本期直播将与您一起探秘颉编程语言上线华为开发者空间后,显著提升开发效率,在智能化开发支持、全场景跨平台适配能力、工具链与生态完备性、语言简洁与高性能特性等方面展现出的独特优势。直播看点: 1.java转仓颉的小工具 2.仓颉动画三方库lottie 3.开发者空间介绍及如何在空间用仓颉编程语言开发
即将直播 -
大模型Prompt工程深度实践
2025/02/24 周一 16:00-17:30
盖伦 华为云学堂技术讲师
如何让大模型精准理解开发需求并生成可靠输出?本期直播聚焦大模型Prompt工程核心技术:理解大模型推理基础原理,关键采样参数定义,提示词撰写关键策略及Prompt工程技巧分享。
去报名 -
华为云 x DeepSeek:AI驱动云上应用创新
2025/02/26 周三 16:00-18:00
华为云 AI专家大咖团
在 AI 技术飞速发展之际,DeepSeek 备受关注。它凭借哪些技术与理念脱颖而出?华为云与 DeepSeek 合作,将如何重塑产品与应用模式,助力企业数字化转型?在华为开发者空间,怎样高效部署 DeepSeek,搭建专属服务器?基于华为云平台,又该如何挖掘 DeepSeek 潜力,实现智能化升级?本期直播围绕DeepSeek在云上的应用案例,与DTSE布道师们一起探讨如何利用AI 驱动云上应用创新。
去报名
热门标签