整理 | 苏宓出品 | CSDN(ID:CSDNnews)近日,来自多伦多大学和 YScope 公司(为软件系统提供创新的日志管理和故障排除工具。由一群计算机工程教授和博士创立)的 David Lion、多伦多大学 Adrian Chiu 和 Michael Stumm、多伦多大学和 YScope 公司 Ding Yuan 共同发布了一份《调查托管语言的运行时性能:为什么 JavaScript 和 Python 比 C++ 慢了 8 倍和 29 倍,而 Java 和 Go 却能更快》(https://www.usenix.org/system/files/atc22-lion.pdf)的论文分析报告,深度剖析了不同编程语言运行时在代码开发中真实的性能情况,由此方便开发者可以精确地测量执行任何字节码指令所花费的时间等。性能是系统软件不得不面对的挑战在报告中,研究人员指出,自 2015 年以来,具有集成运行时环境的编程语言越来越受欢迎,其中,全球知名的代码托管平台 GitHub 上最受欢迎的三种语言分别是 JavaScript、Java 和 Python。作为开发利器,编程语言帮助开发者快速构建各种应用程序和服务,也极大地提高了生产力。同时,这些语言自身也提供了各种功能,如动态类型检查、带有垃圾收集的内存管理,以及动态内存安全检查等等。为此,研究人员用「托管语言」(managed languages)专业术语来指代这些类型的编程语言。现实来看,托管语言越来越多地被用于实现性能至关重要的系统软件上,如Hadoop 和 Spark 都在 Java 虚拟机(JVM)上运行,因为它们分别用 Java 和 Scala 实现;Kubernetes、etcd(分布式键值存储)和 M3(由 Uber 建立的分布式时间序列数据库和查询引擎)都是用 Go 实现的。当前,甚至连操作系统(OS)的内核 Biscuit 也是用 Go 实现的 。Openstack、Paypal、Instagram 和 Dropbox 都大量使用 Python,其中,Python 是 Dropbox "在后台服务和桌面客户端应用中使用最广泛的语言",在一个存储库中就有近 400 万行 Python 代码;JavaScript 也被用于 Facebook 的 Bladerunner pub/sub 系统的性能关键路径中。在开发过程中,编程语言的性能在一开始很少会被考虑到项目中,部分原因是不少开发者认为性能问题可以在以后慢慢去解决,也许可以通过简单地增加硬件来进行横向扩展。不过,随着代码产品或服务使用规模的扩大,服务变得越来越慢或者硬件成本变高,性能成为一个不容忽视的问题。这也是为什么 Stream 要放弃了 Python 而改用 Go、 Discord 从 Go 切换到 Rust、Twitter 从 Ruby on Rails 切换到 Scala 和 Java 的主要原因。不少开发者往往为了提升性能,想破脑袋,但现实只有两条路,一条是从现有的代码中想尽办法尽可能地做优化,另一条是思考使用的编程语言是否已经达到了性能极限,看看有没有必要将旧的代码移植到一个新的性能更高的语言上。为了彻底解开系统软件中不同编程语言导致的性能问题,研究人员决定以 C++ 为极限,对 Java、Go、JavaScript 和 Python 四种编程,还有应用最广泛的运行时系统 CPython、OpenJDK。Node.js 与 JavaScript 的 V8 引擎进行深入的定量性能分析。同时,研究人员还从头开始建立了 6 个应用程序,并创建了一个名为 LangBench 基准(https://github.com/topics/langbench)。这些应用程序涵盖了各种不同的计算强度、内存使用、网络和磁盘 I/O 强度以及可用的并发性的应用场景等复杂性。对此,研究人员全面分析了它们的完成时间、资源使用和可扩展性。测试方法值得一提的是,研究人员指出,这份论文没有也不可能全面地回答与语言运行时的性能有关的每一个问题。本文只是评估了四种语言的运行时,而且对于每种语言,只评估了最广泛使用的实现。此外,研究人员只在一个单一的操作系统/硬件堆栈上运行了工作负载。其研究结果与使用的基准有关,这些基准模拟了现实生活中的应用,但可能不代表广泛的应用。在测试方法上,研究人员在两台内部服务器上进行了实验,每台服务器有 2 个Xeon E5-2630V3、16 个虚拟核心、2.4GHz CPU、256GB DDR4 内存和两个 7200 RPM 硬盘。它们运行的系统是 Linux 4.15.0,并通过 10Gbps 的互联网络连接。对于 C++ 程序,研究人员使用的是 GCC 9.3.0 根据 C++17 标准用 -O3 进行编译。对于 OpenJDK 13、CPython 3.8.1 和Go 1.14.1 ,其使用了各自语言的参考实现。同时,使用 Node.js 13.12.0 和 V8 7.9.317.25 版本。研究人员对每个基准进行了 5 次测试,取平均值。其中,在运行键-值存储、日志分析器和文件服务器的基准时,client 和 worker 线程的数量从 1 到 1024 不等。对于 OpenJDK 和 V8 来说,最小的内存量是通过确定不会导致崩溃的第一个堆配置来设置的;对于 Go 来说,GOGC 被设置为5%。然后研究人员不断增加堆的设置,直到性能不再提高。其使用第一个设置的结果(即最小的堆大小)得出最佳性能。对于日志解析器和文件服务器基准,所用的日志文件被存储在一个复制系数为 2 的分布式文件系统上。 在运行每个基准之前,研究人员都清除了 Linux 的页面缓存,以保证测试准确性。其中,优化的 GCC 平均速度最快,Go 和 OpenJDK 紧随其后,比 GCC 慢了 1.30 倍和 1.43 倍。令人印象深刻的是,在 12 项基准测试中,Go 和 OpenJDK 有 3 项超过了优化的 GCC。总体而言,研究人员发现 V8 / Node.js 和 CPython 表现最差,执行应用程序的平均速度分别比 C++ 应用程序慢 8.01 倍和 29.50 倍,这意味着运行时下,JavaScript、Python 要比 C++ 慢这么多。更糟糕的是,这两个运行时上的应用程序扩展性很差,因为它们无法有效地利用多个内核。在极端情况下,CPython 比 GCC 慢了 129.66 倍(在排序基准中)。V8/Node.js 和 CPython 只有在工作负载受到磁盘 I/O 的瓶颈时,即在文件服务器基准中,才与 GCC 有竞争力。相比之下,OpenJDK 和 Go 应用程序即 Java 和 Go 语言比 C++ 更具有性能竞争力,运行速度仅慢了 1.43 倍和 1.30 倍,并且可以轻松扩展到多个内核。在一些应用中,OpenJDK 和 Go 的性能超过了 C++ 的同类产品。更多完整报告内容详见:https://www.usenix.org/system/files/atc22-lion.pdf
1. 购买ECS云服务器2. 通过MobaXterm访问购买的云服务器3. 切换到HwHiAiUser用户4. 获取源码:命令行运行:git clone https://gitee.com/ascend/samples.git 可以看到目录中有samples文件夹5. 进行模型下载并转换(1)进入samples/cplusplus/level2_simple_inference/6_other/animeGAN_picture/model目录(2)下载三种shape的模型256*256:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_256_256.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_256_256.cfg512*512:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_512_512.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_512_512.cfg 1024*1024:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_1024_1024.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_1024_1024.cfg (3)模型转换atc --model="./AnimeGAN_256_256.pb" --output_type=FP32 --input_shape="test:1,256,256,3" --input_format=NHWC --output="AnimeGANv2_256" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_256_256.cfgatc --model="./AnimeGAN_512_512.pb" --output_type=FP32 --input_shape="test:1,512,512,3" --input_format=NHWC --output="AnimeGANv2_512" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_512_512.cfgatc --model="./AnimeGAN_1024_1024.pb" --output_type=FP32 --input_shape="test:1,1024,1024,3" --input_format=NHWC --output="AnimeGANv2_1024" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_1024_1024.cfg6. 样例部署, 执行编译脚本,进行样例编译进入/animeGAN_picture/scripts目录,运行samples_build.sh,同时测试图片mountain.jpg已下载到/animeGAN_picture/data目录下原图如下:7.样例运行进入/animeGAN_picture/scripts目录,运行samples_run.sh,需要输入shape大小,即 bash sample_run.sh 256。输出的图片在/animeGAN_picture/out/output目录下输出效果如下:
如果说C++在内存安全上做出了自己的努力,那么在线程并发安全上则努力程度还不够;而Rust则是从一开始就在内存安全和线程安全上下足了功夫,同时没有抛弃性能。在一些基本的语言表达方式上,Rust和C/C++存在一些不同,体现在:(1)变量默认是不可变绑定(let),需要修改变量,则需明确使用可变绑定(let mut);(2)没有实现Copy trait的对象,绑定、赋值、非引用传参时默认是移动语义;(3)支持函数内嵌定义;(4)支持函数表达式返回(最后不加分号);(5)在同一个作用域内,变量可以重新绑定(let),在Rust中叫做遮蔽机制;(6)支持零尺寸的结构体、空枚举、空数组([T, 0]);(7)两种字符串类型变量:&str相当于C++中的const char*,用于指向字符串字面常量;而String相对于C++中的std::string,支持可变引用&Mut String和不可变引用&String;(8)基本的数据类型都实现了Copy trait,默认在栈上分配,支持复制语义;而String、Vec等默认只支持移动语义,要进行深拷贝,需要显式调用clone函数;(9)不支持switch & case,使用match模式匹配代替;(10)不支持三目运算符;(11)支持?运算符,用于调用的函数返回异常时,直接退出当前函数并返回对应的错误Err
;……
1、C和C++的区别1)C是面向过程的语言,是一个结构化的语言,考虑如何通过一个过程对输入进行处理得到输出;C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。2)C和C++动态管理内存的方法不一样,C是使用malloc/free,而C++除此之外还有new/delete关键字。3)C++中有引用,C中不存在引用的概念2、C++中指针和引用的区别1)指针是一个新的变量,存储了另一个变量的地址,我们可以通过访问这个地址来修改另一个变量;引用只是一个别名,还是变量本身,对引用的任何操作就是对变量本身进行操作,以达到修改变量的目的2)引用只有一级,而指针可以有多级3)指针传参的时候,还是值传递,指针本身的值不可以修改,需要通过解引用才能对指向的对象进行操作引用传参的时候,传进来的就是变量本身,因此变量可以被修改3、结构体struct和共同体union(联合)的区别结构体:将不同类型的数据组合成一个整体,是自定义类型共同体:不同类型的几个变量共同占用一段内存1)结构体中的每个成员都有自己独立的地址,它们是同时存在的;共同体中的所有成员占用同一段内存,它们不能同时存在;2)sizeof(struct)是内存对齐后所有成员长度的总和,sizeof(union)是内存对齐后最长数据成员的长度、结构体为什么要内存对齐呢?1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常2.硬件原因:经过内存对齐之后,CPU的内存访问速度大大提升。4、#define和const的区别1)#define定义的常量没有类型,所给出的是一个立即数;const定义的常量有类型名字,存放在静态区域2)处理阶段不同,#define定义的宏变量在预处理时进行替换,可能有多个拷贝,const所定义的变量在编译时确定其值,只有一个拷贝。3)#define定义的常量是不可以用指针去指向,const定义的常量可以用指针去指向该常量的地址4)#define可以定义简单的函数,const不可以定义函数5、重载overload,覆盖(重写)override,隐藏(重定义)overwrite,这三者之间的区别1)overload,将语义相近的几个函数用同一个名字表示,但是参数列表(参数的类型,个数,顺序不同)不同,这就是函数重载,返回值类型可以不同特征:相同范围(同一个类中)、函数名字相同、参数不同、virtual关键字可有可无2)override,派生类覆盖基类的虚函数,实现接口的重用,返回值类型必须相同特征:不同范围(基类和派生类)、函数名字相同、参数相同、基类中必须有virtual关键字(必须是虚函数)3)overwrite,派生类屏蔽了其同名的基类函数,返回值类型可以不同特征:不同范围(基类和派生类)、函数名字相同、参数不同或者参数相同且无virtual关键字6、new、delete、malloc、free之间的关系new/delete,malloc/free都是动态分配内存的方式1)malloc对开辟的空间大小严格指定,而new只需要对象名2)new为对象分配空间时,调用对象的构造函数,delete调用对象的析构函数既然有了malloc/free,C++中为什么还需要new/delete呢?运算符是语言自身的特性,有固定的语义,编译器知道意味着什么,由编译器解释语义,生成相应的代码。库函数是依赖于库的,一定程度上独立于语言的。编译器不关心库函数的作用,只保证编译,调用函数参数和返回值符合语法,生成call函数的代码。malloc/free是库函数,new/delete是C++运算符。对于非内部数据类型而言,光用malloc/free无法满足动态对象都要求。new/delete是运算符,编译器保证调用构造和析构函数对对象进行初始化/析构。但是库函数malloc/free是库函数,不会执行构造/析构。7、delete和delete[]的区别delete只会调用一次析构函数,而delete[]会调用每个成员的析构函数用new分配的内存用delete释放,用new[]分配的内存用delete[]释放一.构造函数构造函数是和类名相同的一个函数,它的作用是实现对象的初始化。当对象被创建时,构造函数自动被调用。特点:没有类型没有返回值(也不用写void)名字与类名相同可重载!作用:完成类的对象的初始化Cdate d; //定义对象d注意:当对象d被创建时,会自动调用构造函数 d.Cdate()。当类中未定义构造函数时,编译器会自动假设存在以下两个默认构造函数:(此构造函数什么都不做,就是个形式)。如果作者自己定义了构造函数,则默认的构造函数不会存在。//默认构造函数一 Cdate::Cdate() { } //默认构造函数二 Cdate::Cdate(const Cdate& a) { }三.析构函数我们已经知道构造函数是在创建对象时,对其进行初始化。而析构函数与其相反,是在对象被删除前象由系统自动执行它做清理工作。作为一个类,可能有多个对象,每个对象生命结束时都要调用析构函数,且每个对象调用一次。特点:无类型无返回值名字与类名相同不带参数,不可重载,析构函数只有一个!析构函数前“~” (取反符,表示逆构造函数)作用:在对象被删除前做清理工作。注意:对象的析构函数在对象被销毁前被调用,对象何时销毁也与其作用域相关。例如,全局对象是在程序运行结束时销毁;自动对象是在离开其作用域时销毁;而动态对象是在使用delete运算符时销毁。析构函数特别适用于当一个对象被动态分配内存空间,而在对象被销毁前希望释放它所占用的内存空间的时候。我们不会忽略初始化的重要性,却常常忽略清除的重要性,然而对销毁变量的内存清理是非常重要的。例如,我们在堆中申请了一些内存,如果没有用完就释放,会造成内存泄露,会导致应用程序运行效率降低,甚至崩溃,不可掉以轻心。而在c++中提供有析构函数,可以保证对象清除工作自动执行。析构与构造的调用次序相反,即最先构造的最后被析构,最后构造的最先被析构。7.1、虚函数、纯虚函数虚函数:虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数,是C++中多态性的一个重要体现。利用基类指针访问派生类中的虚函数,这种情况下采用的是动态绑定技术。纯虚函数:纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”.纯虚函数不能实例化对象。抽象类的介绍抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。(1)抽象类的定义: 称带有纯虚函数的类为抽象类。(2)抽象类的作用: 抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。(3)使用抽象类时注意:抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。抽象类是不能定义对象的。总结:1、纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。2、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。4、实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。纯虚函数的引入,是出于两个目的:1、为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。2、为了效率,不是程序执行的效率,而是为了编码的效率。动态绑定:基类指针是调用派生类的中的成员函数还是调用基类中的成员函数要到程序运行时确定。主要看此时基类指针所指向的对象。 这里要涉及一些很重要的概念,也是我最近看完Effective C++才明白的东西,记录下来。这些概念就是静态类型和动态类型,静态绑定和动态绑定。静态绑定和动态绑定。静态绑定是说前期绑定。 所谓对象的静态类型,就是它在程序中被声明的时候采用的类型。 考虑下面的class继承体系:class Shape{ virtual void draw(color = Red) const=0; ... ... }; class Rectangle:public Shape{ virtual void draw(color = Red) const; ... ... }; class Circle:public Shape { virtual void draw(color = Red) const; ... ... }; 现在考虑以下这些指针: Shape* ps;//静态类型为Shape* Shape*pc =new Circle;//静态类型Shape* Shape*pr = new Rectangle;//静态类型Shape*在本例中,ps,pc,pr都被声明为Shape*类型的,所以它们的静态类型都是Shape*。注意:无论它们真正指向什么,它们的静态类型都是Shape*. 所谓的对象的动态类型是指“当前所指对象的类型”。也就是说,动态类型可以表现出一个对象将会有什么行为。根据上面的例子,pc的动态类型是Circle*,pr的动态类型是Rectangle*。ps没有动态类型,因为它没有指向任何对象。 动态类型一如其名所示,可以在执行过程中改变(通常是经过赋值运算):ps=pc; \\ps的动态类型如今是Circle* ps=pr; \\ps的动态类型如今是Rectangle*Virtual函数系动态绑定而来,意思是调用一个virtual函数的时候,究竟调用的是哪一个函数代码,取决于发出调用的那个对象的动态类型。ps->draw(); \\调用的是Rectangle::draw(Red)8、STL库用过吗?常见的STL容器有哪些?算法用过几个?STL包括两部分内容:容器和算法容器即存放数据的地方,比如array, vector,分为两类,序列式容器和关联式容器序列式容器,其中的元素不一定有序,但是都可以被排序,比如vector,list,queue,stack,heap, priority-queue, slist关联式容器,内部结构是一个平衡二叉树,每个元素都有一个键值和一个实值,比如map, set, hashtable, hash_set算法有排序,复制等,以及各个容器特定的算法迭代器是STL的精髓,迭代器提供了一种方法,使得它能够按照顺序访问某个容器所含的各个元素,但无需暴露该容器的内部结构,它将容器和算法分开,让二者独立设计。Vector是顺序容器,是一个动态数组,支持随机存取、插入、删除、查找等操作,在内存中是一块连续的空间。在原有空间不够情况下自动分配空间,增加为原来的两倍。vector随机存取效率高,但是在vector插入元素,需要移动的数目多,效率低下。注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。————————————————版权声明:本文为CSDN博主「Cpp编程小茶馆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/xu_fu_yong/article/details/122948379
【功能模块】MindSpore的CPU计算算子。【操作步骤&问题现象】我正在学习开发一个简单的算子以理解编译的全流程。我的尝试方法是实现一个叫做“eya”的算子,该算子除了名称以外与eye算子(其功能为创建单位矩阵)完全一致。我在算子前端、C++侧推导、底层实现等CPU开发涉及文件都仿照eye算子做了添加和修改(即,在算子开发涉及文件中,先将eye算子部分的代码完全复制一份,然后仅将“eye”名称替换为“eya”),并在编译后能顺利在python中导入该算子。但是在执行时出现了RuntimeError报错并提示“The evaluator of the primitive is not defined”。在尝试解决该报错的过程中,我还参阅了在网上能找到的所有相关issue的讨论如下,但未能为求解提供帮助:参考issue1:https://bbs.huaweicloud.com/forum/thread-136641-1-1.html结果:已检查“mindspore/core/core_ops.h”中对PrimitivePtr的定义,与原先eye算子的实现完全一致(见下面的【其它信息】说明),故未能提供帮助参考issue2:https://toscode.gitee.com/mindspore/mindspore/issues/I4NX69结果:由于该issue所参考的官网链接已404失效,且issue中没有交代具体求解方案,故未能提供帮助请问该问题所反映的出错程序可能会在哪个部分呢?或者为了解决该报错如何进行进一步调试呢?感谢。【截图信息】调试命令和返回报错结果如下:【其它信息】修改C++侧推导文件时,在\mindspore\core\ops\core_ops.h中插入的代码为(与eye算子除了名称以外其他完全一致):constexpr auto kEya = "Eya";GVAR_DEF(PrimitivePtr, kPrimEya, std::make_shared(kEya));其它如算子前端、底层实现等文件,同样是除了名称以外其他代码与eye算子完全一致。
第一步创建工程目录如下:其中main.cpp#include#include"solution.h"using namespace std;int main(int argc, char const *argv[]){ cout<<"hello world"<void Solution::play(){ int a=3+4; std::cout<Configure Default Build Task, 在下拉栏里选择C/C++: g++ build active file. 这会生成tasks.json文件。{ "tasks": [ { "type": "cppbuild", "label": "g++ build active file", "command": "make", //主要这里是make命令 "args": [ "-C", "${workspaceFolder}", "main" ], "options": { "cwd": "${fileDirname}" }, "problemMatcher": [ "$gcc" ], "group": "build", "detail": "调试器生成的任务。" }, { //删除二进制文件 "type": "shell", "label": "delete output file", "command": "make", //这个是make clean 命令 "args": [ "clean" ], "presentation": { "reveal": "silent", //删除过程不切换终端(专注程序输出) } } ], "version": "2.0.0"}第四步:创建launch.json文件选择debug>add Configuration内容如下:{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "g++ build and debug active file", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/main", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "g++ build active file", //这个必须要和task.json中的lable保持一致,前处理 "postDebugTask": "delete output file", //这个必须要和task.json中的lable保持一致,后处理 "miDebuggerPath": "/usr/bin/gdb" //运行环境中要安装gdb } ]}第五步debug调试:菜单栏中的run》start debugging
求助:C++编写应用于实时视频流的dynamic_batch推理程序,长时间运行会崩溃,报错507899程序是双模型,预处理和后处理用的是opencv,第一个模型已经得到多个目标,将各目标区域从源图像中抠出,是cv::Mat格式,放入vector对象srcImages中,再做如下处理:vector objMats;for(int i = 0; i0){ uint32_t pos = 0; void* imageDataBuf_ = nullptr; uint32_t totalSize = imageSize * objMats.size(); aclError aclRet = aclrtMalloc(&imageDataBuf_, totalSize, ACL_MEM_MALOOC_NORMAL_ONLY); if(aclRet != ACL_ERROR_NONE){ ATLAS_ERROR(“malloc failed”); return ATLAS_ERROR; } for(int i =0; i>> (tid:10712) Started to register profiling callbacks to acl[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.682 [log.cpp:148][TsdClient] enter into open process logicDeviceId[0] rankSize[0],[tsd_client.cpp:906:Open]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.711 [log.cpp:148][TsdClient] start process through tsdaemon, begin check aicpu opkernel,[tsd_client.cpp:919:Open]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.737 [log.cpp:148][TsdClient][logicDeviceId_=0] can not find aicpu packages,[tsd_client.cpp:1233:LoadSysOpKernel]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.743 [log.cpp:148][TsdClient][logicDeviceId_=0] check aicpu opkernel success,[tsd_client.cpp:924:Open]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.750 [log.cpp:148][TsdClient] logicDeviceId=0 enter into Open hccp and computer process,[tsd_client.cpp:608:TsdClientInit]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.443.945 [log.cpp:148]VersionVerify: send client version to server,[version_verify.cpp:38:SetVersionInfo]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.444.388 [log.cpp:148]VersionVerify: Check client version info, server[1230], client[1230],[version_verify.cpp:63:PeerVersionCheck]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.444.395 [log.cpp:148]VersionVerify: pass client version info success,[version_verify.cpp:84:ParseVersionInfo]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.444.401 [log.cpp:148]Service[2] create hdc success,[hdc_client.cpp:406:CheckHdcConnection]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.444.447 [log.cpp:148]VersionVerify: previous type[6], supported,[version_verify.cpp:106:SpecialFeatureCheck]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.444.467 [log.cpp:148][TsdClient][logicDeviceId_=0] [sessionId=1][rankSize=0]wait hccp and computer process start respond,[tsd_client.cpp:948:Open]10712[EVENT] TDT(10712,main):2022-05-13-18:53:54.661.849 [log.cpp:148][TsdClient][logicDeviceId_=0] [sessionId=1] start hccp and computer process success,[tsd_client.cpp:972:Open]10712[EVENT] ASCENDCL(10712,main):2022-05-13-18:53:55.896.332 [video_processor.cpp:110]10718 VdecCreateChannel: success to call aclvdecCreateChannel, channelId=0, sendFrameNotifyId=517, getFrameNotifyId=519, sendStreamId=528, getStreamId=534.[EVENT] ASCENDCL(10712,main):2022-05-13-18:53:56.073.248 [video_processor.cpp:110]10721 VdecCreateChannel: success to call aclvdecCreateChannel, channelId=1, sendFrameNotifyId=516, getFrameNotifyId=518, sendStreamId=520, getStreamId=521.[EVENT] ASCENDCL(10712,main):2022-05-13-18:53:56.073.327 [video_processor.cpp:110]10720 VdecCreateChannel: success to call aclvdecCreateChannel, channelId=2, sendFrameNotifyId=512, getFrameNotifyId=514, sendStreamId=522, getStreamId=519.[EVENT] ASCENDCL(10712,main):2022-05-13-18:53:56.073.619 [video_processor.cpp:110]10719 VdecCreateChannel: success to call aclvdecCreateChannel, channelId=3, sendFrameNotifyId=513, getFrameNotifyId=515, sendStreamId=527, getStreamId=536.[ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.556.221 [npu_driver.cc:1579]10849 MemCopySync:drvMemcpy failed: dst=0x100000022000, destMax=6067, src=0xfffdf80688c0, size=6067, kind=1, drvRetCode=8![ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.557.291 [npu_driver.cc:1579]10852 MemCopySync:drvMemcpy failed: dst=0x100000000000, destMax=930, src=0xfffde803a490, size=930, kind=1, drvRetCode=8![ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.558.025 [logger.cc:500]10849 MemCopySync:MemCopySync failed, dst=0x100000022000, src=0xfffdf80688c0, count=6067, kind=1[ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.558.093 [logger.cc:500]10852 MemCopySync:MemCopySync failed, dst=0x100000000000, src=0xfffde803a490, count=930, kind=1[ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.558.517 [api_c.cc:921]10849 rtMemcpy:ErrCode=507899, desc=[driver error:internal error], InnerCode=0x7020010[ERROR] ASCENDCL(10712,main):2022-05-13-18:56:15.558.607 [memory.cpp:234]10849 aclrtMemcpy: synchronized memcpy failed, kind = 1, runtime result = 507899[ERROR] RUNTIME(10712,main):2022-05-13-18:56:15.558.632 [api_c.cc:921]10852 rtMemcpy:ErrCode=507899, desc=[driver error:internal error], InnerCode=0x7020010[ERROR] ASCENDCL(10712,main):2022-05-13-18:56:15.558.676 [memory.cpp:234]10852 aclrtMemcpy: synchronized memcpy failed, kind = 1, runtime result = 507899[ERROR] APP(10712,main):2022-05-13-18:56:15.558.731 [log_inner.cpp:66]10852 CopyData:src/atlas_utils.cpp:279: "Copy data to device failed, aclRet is 507899"[ERROR] APP(10712,main):2022-05-13-18:56:15.558.740 [log_inner.cpp:66]10849 CopyData:src/atlas_utils.cpp:279: "Copy data to device failed, aclRet is 507899"[ERROR] APP(10712,main):2022-05-13-18:56:15.559.055 [log_inner.cpp:66]10852 FrameDecodeCallback:src/video_decode.cpp:382: "Copy frame h26x data to dvpp failed"[ERROR] APP(10712,main):2022-05-13-18:56:15.559.416 [log_inner.cpp:66]10849 FrameDecodeCallback:src/video_decode.cpp:382: "Copy frame h26x data to dvpp failed"
【功能模块】执行推理时,需要对数据进行预处理,但是预处理部分在python的eval代码当中实现过了,于是将eval代码当中即将输入模型当中的clips(tensor)转化成为numpy再使用tofile()函数转化为bin文件在推理代码main.cc当中使用预先写好的ReadFileToTensor()函数:mindspore::MSTensor ReadFileToTensor(const std::string &file) {
if (file.empty()) {
std::cout << "Pointer file is nullptr" << std::endl;
return mindspore::MSTensor();
std::ifstream ifs(file);
if (!ifs.good()) {
std::cout << "File: " << file << " is not exist" << std::endl;
return mindspore::MSTensor();
if (!ifs.is_open()) {
std::cout << "File: " << file << "open failed" << std::endl;
return mindspore::MSTensor();
ifs.seekg(0, std::ios::end);
size_t size = ifs.tellg();
mindspore::MSTensor buffer(file, mindspore::DataType::kNumberTypeUInt8, {static_cast(size)}, nullptr, size);
ifs.seekg(0, std::ios::beg);
ifs.read(reinterpret_cast(buffer.MutableData()), size);
ifs.close();
return buffer;
}读取先前写好的二进制文件但是遇到了奇怪的事件:原本可以在eval代码中运行的clips写成二进制文件再被读取为tensor之后与模型输入不匹配了CheckAndInitInput] Input 0 data size not match, required size 308281344, given count 1233125376大小差了4倍,不知道是什么原因请问这里是因为什么导致了这个错误呢,或者有没有更好的方法将py中的tensor用于c++当中呢?非常感谢
Roc 华为云云原生DTSE技术布道师
还在对CCE集群成本评估感到束手无策?还在担心不合理的K8s集群资源申请和过度浪费?华为云容器服务CCE全新上线云原生FinOps中心,为用户提供多维度集群成本可视化,结合智能规格推荐、混部、超卖等成本优化手段,助力客户降本增效,释放云原生最大价值。