精华内容
下载资源
问答
  • 通过对传感器与氟嘴密封结构进行分析,确定了整改方案并进行相关实验验证,找到了压力传感器与氟嘴密封效果的配合结构,并且对所有的压力传感器、氟嘴结构进行改型,降低了售后的泄露和投诉。  1 压力...
  • 、塑件材料的选择及其结构分析 1、塑件(手机外壳)模型图: 图1-1 塑件图 2、塑件材料的选择:选用ABS(即丙烯腈-丁二烯-苯乙烯共聚物)。 3、色调:黑色。 4、生产批量:大批量。 5、塑件的结构与工艺性...
  • voltdb mysql_VoltDB安装

    2021-01-30 12:55:20
    1.什么是VoltDB?是个优化吞吐的高性能集群开源SQLRDBMS(Database Management System),它是个内存...VoltDB基于PC+以太网+本地存储,从体系结构来看其内部是个ShareNothing(1)的内存数据库,通过并行单线程...

    1.什么是VoltDB?

    是一个优化吞吐率的高性能集群开源SQLRDBMS(Database Management System),它是一个内存关系型数据库,既获得了nosql的良好可扩展性,高吞吐量的数据处理,又没有放弃原传统关系型数据库的事务支持--ACID

    从硬件上来看,VoltDB基于PC+以太网+本地存储,从体系结构来看其内部是一个ShareNothing(注1)的内存数据库,通过并行单线程来保证事务的一致性和高性能,所有事务被实现为java存储过程,所有存储过程(事务)都全局有序,由于避免了锁的使用,因此可以保证每个事务在所有分区上并行执行完成后才继续执行下一个事务,事务不会乱序执行。存储过程内部支持分组,多路join,聚合,函数等等,

    VoltDB---自动数据分区,数据表会自动分配到集群节点,可以看成是传统sharding的升级整合版本。

    ---自动快照,意味着一个事务内部无需进行IO操作,可在微秒级别完成事务,

    ---异步事务提交,从某种意义上看,VoltDB是一个共享内存的集群(?),支持多节点并行事务处理,理论上不存在节点上限

    2.VoltDB部署安装环境

    voltdb的代码以及系统构建都是在64位的linux/OS X之上的,它的编译需要如下环境:

    java 1.8

    Apache Ant 1.7 或者更高版本

    一个支持C++11的编译器

    Python 2.6 或者更高版本

    cmake 2.8 或者更高版本

    安装ant:

    tar -xzvf apache-ant-1.9.13-bin.tar.gz

    # 配置环境变量vi /etc/profile

    export ANT_HOME=/data/webserver/apache-ant-1.9.13

    export PATH=$ANT_HOME/bin:$PATH

    VoltDB安装:

    unzip voltdb-voltdb-9.0.zip

    cd voltdb-voltdb-9.0

    ant clean

    ant

    配置VoltDB环境变量:

    export VOLTDB_PATH=/data/webserver/voltdb-voltdb-9.0

    export PATH=$VOLTDB_PATH/bin:$PATH

    export CLASSPATH=.:$VOLTDB_PATH/lib/*:$VOLTDB_PATH/voltdb/*:$CLASSPATH

    初始化VoltDB并启动:

    voltdb init

    voltdb start

    启动成功后,通过浏览器http://localhost:8080访问VoltDB管理控制台:

    225a0edc6d4ede3e0827379bde6e4e88.png

    展开全文
  • 摘要:随着深度学习不断普及,数据对象更多的通过一个高维向量来表达,通过最近邻的查找,丰富了图片搜索、UGC视频版权保护、人脸识别、搜索&推荐等诸多应用;另方面随着数据的爆发式增长对最近邻检索的时延和...
    摘要:随着深度学习不断普及,数据对象更多的通过一个高维向量来表达,通过最近邻的查找,丰富了图片搜索、UGC视频版权保护、人脸识别、搜索&推荐等诸多应用;另一方面随着数据的爆发式增长对最近邻检索的时延和召回率又提出了更高的要求。最近几年向量检索成为一个研究的热点,本文对向量检索涉及的相关技术做一个概览,在最后给出华为云在向量检索的一些实践。

    注1:本文部分索引结构示例图源自https://yongyuan.name/blog/vector-ann-search.html

    注2:本文是本人发表在华为云开发者社区的文章,最早链接见一文纵览向量检索_博客_云社区_开发者中心-华为云,知乎链接见华为云开发者社区:一文纵览向量检索,其他渠道都是华为云开发者社区发布。

    什么是向量检索

    首先我们了解下什么是向量,所谓向量就是由n个数字(二值向量由n个比特组成)组成的数组,我们称之为n维向量。而向量检索就是在一个给定向量数据集中,按照某种度量方式,检索出与查询向量相近的K个向量(K-Nearest Neighbor,KNN),但由于KNN计算量过大,我们通常只关注近似近邻(Approximate Nearest Neighbor,ANN)问题。

    向量度量

    常见的向量度量有四种:欧式距离、余弦、内积、海明距离

    不同的度量方式对应不同的场景,通常欧式距离用于图片检索,余弦用于人脸识别,内积多用于推荐,海明距离由于向量比较小,通常用于大规模视频检索场景。

    有了度量以后,我们通常会用召回率(也通常叫精度)来评估向量检索的效果,对于给定的向量q,其在数据集上的K近邻为N,通过检索召回的K个近邻集合为M,则

    5f7e06a2b762223496feed64ebf3e4a8.png

    召回越接近100%代表索引效果越好。

    向量检索解决的问题

    向量检索从本质上讲,其思维框架和传统的检索方法没有什么区别,后面在讲解向量检索的索引结构部时,体会能更深刻一些。

    1. 减少候选向量集

    和传统的文本检索类似,向量检索也需要某种索引结构来避免在全量的数据上做匹配,传统文本检索是通过倒排索引来过滤掉无关文档,而向量检索是通过对向量建立索引结构来绕过不相关的向量,本文重点讨论相关的向量索引结构。

    2. 降低单个向量计算的复杂度

    传统文本检索在排序时通常会采用漏斗模型,上层计算比较轻量,越往下计算越精细,但随着过滤的进行,需要计算的文档数也逐级下降,对高维向量而言,单个向量的计算量还是比较重,通常会对向量进行量化,对向量做近似计算,最后在一个很小的数据集上做原始向量的排序。

    下面我们围绕这两个问题来展开向量检索的相关讨论。

    向量检索索引结构

    为向量建立高效的索引结构是向量检索面对的头号问题,在开始展开前我们看一个Benchmark项目,这个项目在多个公开的向量数据集对比了相关索引结构的召回性能指标,使我们能够快速对各种索引结构的性能表现有个直观的认识。

    暴力计算

    暴力计算是最简单但复杂度最高的一种方式,在计算召回的时候,暴力计算的结果是作为答案的基准数据,在人脸识别的场景中经常要求100%的召回率,这种情况下一般直接暴力计算。

    基于树的方法

    基于树的方法有很多种,比较典型的有KDTree、BallTree、VPTree,类比传统的二叉树,树结构无非是在建树的时候是决定往左还是往右扩展,不同的向量树索引在于按照什么标准去决策,KDTree(如图1所示)会选取向量中某个方差最大的维度取中值作为判定标准,也就是以超平面去划分空间,而BallTree则以球面去划分空间,VPTree会先选取一个制高点,然后计算每个点和制高点的距离,取距离中值作为判定标准。通常这些方法在检索的时候都会利用三角形不等式来去除不必要的探索。

    基于树的方法还有很多其他类型,但万变不离其宗,无非就是按照某个判定标准,对向量空间进行划分,但不管怎么划分,由于需要回溯的,都决定了基于树的方法在性能上要稍逊一筹。

    db2d6b55df4333fa84ad39d7edc6286e.png
    图1 KDTree

    哈希方法

    哈希对大家再熟悉不过,向量也可以采用哈希来加速查找,我们这里说的哈希指的是局部敏感哈希(Locality Sensitive Hashing,LSH),不同于传统哈希尽量不产生碰撞,局部敏感哈希依赖碰撞来查找近邻。

    满足如下两个条件的哈希函数称为(d1,d2,p1,p2)-sensitive:

    1. 如果d(x,y) <= d1,则h(x) = h(y)的概率至少为p1;

    2. 如果d(x,y) >= d2,则h(x) = h(y)的概率至少为p2;

    上面的表达式用人话来说就是:高维空间的两点若距离很近,那么设计一种哈希函数对这两点进行哈希值计算,使得他们哈希值有很大的概率是一样的,若两点之间的距离较远,他们哈希值相同的概率会很小。不同距离度量的哈希函数不同,不是所有距离度量(如内积)都能找到对应局部敏感哈希

    基于倒排方法

    传统倒排索引是根据文档包含某个词,然后将当前文档放入改词的倒排索引中来建立索引结构,那向量是如何建立起倒排索引呢?通过聚类把整个向量空间划分为K个区域,每个区域用一个中心点C代替,这样每个向量和所有中心点对比,将自身归入到距离自己最近的中心点对应的倒排,整个索引结构就建立起来了,如图2。

    61af993b6f67e17ff2f6a5f73902d5ef.png
    图2 基于倒排的索引

    另一种基于倒排的索引是BOW,原理大体相同,例如一张图片会抽取出几百个局部特征,先对所有的特征聚类,形成中心点,这些中心点作为倒排的基础,建立索引时,把图片的每个局部特征归类到其最近的中心点,建立倒排,检索时会根据命中的次数来过滤结果。

    基于图的方法

    前面介绍的索引结构都可以归类为基于空间划分的方法,每个向量只会属于某个划分好的一个区域,这些方法最大的的问题是为了提高召回需要考察很大一块区域的向量,导致计算量激增,那有没有更好的方法来解决这个问题呢?基于图的方法就可以比较好的实现这一目标,图方法最朴素的想法是邻居的邻居也可能是邻居,这样把最近邻的查找转化为图的遍历,由于其连通性,可以针对性的考察部分向量而不是按区域来考察,因此可以大幅降低向量的考察范围。

    最近几年图方法是向量检索研究的一个热点,出现了如KGraph、NSG、HNSW、NGT等一批图索引方法,但实际上这些图方法的主要区别在构建过程,不同图方法采用不同的手段来提升图的质量,但图检索的步骤基本是一致的:a.选好入口点;b.遍历图;c.收敛。在不断实践中我们观察到一些特性来评判图索引质量,指引我们在图方法改进的方向:

    1. 邻居点接近K近邻

    2. 邻居点数量尽可能少,即减少出度

    3. 尽可能保证图的连通性,增加入度

    下面我们以HNSW为例介绍一下图方法的原理,之所以选取HNSW在于该方法易于理解,比较容易实现流式索引构建和更新,属于传统方法在向量上的完美体现。

    HNSW背后其实是跳表在图上的应用,跳表作为一种简单高效的索引结构在Redis、LevelDB等系统中获得广泛应用,如图3所示:

    5d34626f8651e816e3539cd213e35eaa.png
    图3 传统跳表结构

    第一层上有全量的数据,在上层根据随机投币决定,越往上投到的概率越小,投到高层的节点往下都有一条记录,作为检索的高速公路快速前进。

    HNSW的原理也类似,不同于传统跳表在每层用链表来串联节点,HNSW在每层都是一个NSW(Navigable Small World Graph),通过图数据结构组织,上层节点也是通过投币决定在哪一层,并且它们在下层图中都有记录,上层图可以看做下层图的一个缩影,检索时,从上到下,不断指引检索过程逐步靠近想要探寻的向量空间。另外在构图过程中HNSW通过边的裁剪来保证图的连通性,这里顺便提一下,纵观多篇图方法的论文,都从自己的视角表述了边裁剪方法, 但不管各种方法对裁边描述的有多酷炫,其方法本质都是一模一样的,只是视角不一样而已。

    d8bffcf4dfdb227d28c7f254e9f67c0d.png
    图4 HNSW

    向量量化

    前面把主流的向量检索的索引技术基本都概述了一遍,经过索引结构对考察的向量做了裁剪以后,对高维向量而言,单个的计算量还是很大,有没有方法来减少计算量呢?量化正是基于这个目的技术,所谓量化是指把一个很大的值空间量化到一个较小的值范围,举个简单的例子,全世界有60多亿人口,也就是地球人的表征有60多亿种,我们可以把人量化为男人和女人两种类型,这样就把一个60多亿的空间量化成只有两个值的范围。

    常用的量化一般包括PQ(及其优化OPQ、LOPQ)和二值两种。

    PQ原理如图,PQ中的P是乘积的意思,那怎么就冒出个乘积呢?在下图中一个128维的向量空间在经过PQ处理后,向量空间切分成了4段,每段内由256个中心点来量化表达,因此原始的128维空间现在可以用每段里的中心点组合,也即256 * 256 * 256 * 256种组合来表达,这就是所谓的乘积。

    41276bf1209adf79922a3dfa3db4755e.png
    图5 乘积量化

    对于二值向量,由于现代CPU都提供了专门的指令,计算海明距离非常快速,在海量的向量检索中通常会直接生成二值向量,生成二值向量方法常见的有ITQ(Iterative Quantization)、DeepHash等方法。

    其他技术

    聚类

    向量聚类主要指的是K-means系列方法,如经典的K-means、K-means++、K-means#、One pass K-means、YinYang k-means等,在实践中我们也使用过分层的方法来获得海量中心点。

    内积转换

    前面在哈希章节我们已经看到对内积是没有办法找到对应的局部敏感哈希函数,内积也不满足三角形不等式,因此导致很多索引结构无法直接使用内积作为度量,大多数做法是先对向量做归一化再检索,但归一化会转换向量空间分布。研究人员通过一个数学观察发现了一个方法,通过一定规则变换,可以使得内积和欧式能够实现负相关,如图6所示:

    34637fe3fde05d1aea7bda6887707a0d.png
    图6 内积转化

    对向量转换后,可直接用欧式距离度量方式检索。不过时至今日,已经证明可以在图上直接使用内积。

    向量检索发展趋势

    本文开头我们提到向量检索的思维框架和传统检索没有什么区别,到目前为止传统方法应用到向量检索的红利也基本吃完。这两年的一个发展趋势是各种方法的组合,通过吸收各种方法的长处,来获得更好的性能、承载更大规模的向量。

    量化图

    从Benchmark上我们可以清晰的看到,处在优势地位的方法基本被图方法霸屏,同时我们知道量化可以降低单个向量的计算量,因此很自然的一种想法是让两者强强联手,在图遍历过程中使用量化计算来加速,这种方法对于在高维度方法上优势明显,加速比能达到三倍以上。

    图+倒排

    图的性能虽然卓越,但缺点也非常明显,为了保证检索效果,图上边的保存消耗大量的存储

    8dc2527f53a57fa3b3f14de3a91cfa6b.png
    图7 组合索引

    尤其在向量本身很小的二值向量上,这是不能承受之重,另外图的邻居本身具有随机性,对硬件处理向量也非常不利。倒排方式则恰恰相反,索引结构基本不消耗太多空间,但缺点是空间划分方法容易导致召回率不高,但我们从暴力计算的观察获得一些启发,暴力计算从空间划分角度有两种视角:可以将暴力计算看做成把所有向量聚类为一个;也可以将暴力计算看做聚类为N(N为向量数据集的大小)个中心,每个中心点是向量本身。这两种方法都能100%召回,但他们一个是因为中心点下面的向量太多,另一个因为聚类的中心点太多,而导致计算量不可接受,那我们是否可以找到一个平衡点?适当的中心点数目使得召回和性能取得一个比较好的平衡?图+倒排方式应运而生,用海量中心点去分割向量空间,图方法来组织海量中心点。

    华为云向量检索实践

    向量检索的应用出现了空前的繁荣,华为云搜索服务(Cloud Search Service,CSS)目前已经对外开放向量检索的能力,我们针对高性能和海量数据两种典型的场景都提供了解决方案。

    实现上我们主要基于图方法,在裁边优化,连通性增强,指令加速,多线程处理等方面做了大量增强。对比测试中,我们召回率远高于Faiss,在高维度数据上差距更为明显,在同样召回下,我们性能在SIFT,GIST等公开数据集上是Faiss 2.3倍以上。对比测试采用的是相同的机器,相同的算法。

    总结:

    本文针对向量检索要解决的问题,梳理了主流向量检索相关的技术,分析了向量检索目前的一个趋势。在向量检索的发展历程中,还有很多相关的方法没有囊括进来,但万变不离其宗,这些方法要么还是传统方法的扩展或者应用三角不等式的优化或者应用层次方法等等。期盼本文能帮助梳理向量检索的脉络。

    参考文献:

    1. J. L. Bentley. Multidimensional binary search trees used for associative searching. Communications of the ACM, 18:509–517,1975

    2. P. N. Yianilos. Data structures and algorithms for nearest neighbor search in general metric spaces. In Proc. of the 4th annual ACM-SIAM Symposium on Discrete Algorithms, pages 311–321, 1993

    3. Liu, T.; Moore, A. & Gray, A. (2006). New Algorithms for Efficient High-Dimensional Nonparametric Classification. Journal of Machine Learning Research. 7: 1135–1158.

    4. P. Indyk and R. Motwani. Approximate nearest neighbors: Towards removing the curse of dimensionality. In STOC, pages 604–613, Dallas, TX, 1998.

    5. W. Dong, C. Moses, and K. Li. Efficient k-nearest neighbor graph construction for generic similarity measures. In Proceedings of the 20th international conference on World wide web, pages 577–586. ACM, 2011.

    6. Y. A. Malkov and D. A. Yashunin. Efficient and robust approximate nearest neighbor search using hierarchical navigable small world graphs. CoRR,abs/1603.09320, 2016.

    7. https://arxiv.org/abs/1707.00143

    8. https://yongyuan.name/blog/vector-ann-search.html

    9. A. Shrivastava and P. Li. An improved scheme for asymmetric lsh. Technical report, arXiv:1410.5410, 2014.

    10. H. Jegou, M. Douze, and C. Schmid. Product quantization for nearest neighbor search. IEEE transactions on pattern analysis and machine intelligence, 33(1):117{128, 2011.

    11.https://arxiv.org/abs/1810.07355

    展开全文
  • (34) 在面向对象方法中,个对象请求另对象为其服务的方式是通过发送(D) :P56 A. 调用语句 B. 命令 C. 口令 D. 消息 (35) 检查软件产品是否符合需求定义的过程称为(A) :P95 A. 确认测试 B. 集成测试 C. ...
  • 结合双壳锚固支护理论和现场工程条件,确立该矿深部煤巷连续双壳锚支护原则,优化巷道断面形状,通过向围岩体中进行注浆,在巷道浅部围岩和深部围岩中形成连续双壳支护结构,提高巷道围岩的自承能力,实现了围岩注浆与...
  • ​ PMD是种代码静态分析工具,当使用PMD规则分析Java源码时,PMD首先利用JavaCC和EBNF文法产生了个语法分析器,用来分析普通文本形式的Java代码,产生符合特定语法结构的语法,同时又在JavaCC的基础上添加了语义...

    java后端项目代码质量检测集成插件

    1. 静态代码分析:PMD
    2. 代码测试用例覆盖率:jacoco
    3. 持续代码质量检查:sonar

    注:后续主要介绍,如何在maven和idea上提成上述插件

    二、静态代码分析插件集成

    ​ PMD是一种代码静态分析工具,当使用PMD规则分析Java源码时,PMD首先利用JavaCC和EBNF文法产生了一个语法分析器,用来分析普通文本形式的Java代码,产生符合特定语法结构的语法,同时又在JavaCC的基础上添加了语义的概念即JJTree,通过JJTree的一次转换,这样就将Java代码转换成了一个AST,AST是Java符号流之上的语义层,PMD把AST处理成一个符号表。然后编写PMD规则,一个PMD规则可以看成是一个Visitor,通过遍历AST找出多个对象之间的一种特定模式,即代码所存在的问题。

    ​ 静态代码分析是指在不运行程序的前提下,对源代码进行分析或检查,范围包括代码风格、可能出现的空指针、代码块大小、重复的代码等。

    PMD 特点:

    ​ 可扩展的静态代码分析器,不仅可以对代码风格进行检查,还可以检查设计、多线程、性能等方面的问题

    2.1 maven 集成PMD

    2.1.1 PMD中是用了阿里巴巴Java代码规约插件p3c-pmd

    P3C-PMD插件基于PMD实现了《阿里巴巴Java开发手册》中涉及的48条规则。

    1. 编程规约(一)命名风格,实现了1、2、3、4、5、6、7、8、9、13等10条规则;
    2. 编程规约(二)常量定义,实现了1、2等2条规则;
    3. 编程规约(四)OOP规约,实现了5、6、7、8、9、12、17等7条规则;
    4. 编程规约(五)集合处理,实现了4、5、6、7、9、11等6条规则;
    5. 编程规约 (六)并发处理,实现了1、2、3、4、5、10、11、12等8条规则;
    6. 编程规约(七)控制语句,实现了1、2、4等3条规则;
    7. 编程规约(八)注释规约,实现了1、2、3、4、5等5条规则;
    8. 编程规约(九)其他,实现了1、3、4、5等4条规则;
    9. 异常日志 (一)异常处理,实现了5、7、10等3条规则;

    2.1.2 maven 对应的pom.xml中集成PMD插件

    <!-- 属性定义,定义编译环境以及第三方依赖的版本 -->
    <properties>
         <!-- 字符编码 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <!-- pmd 静态代码检测 -->
            <maven.pmd.version>3.13.0</maven.pmd.version>
            <p3c.pmd.version>2.0.1</p3c.pmd.version>
    </properties>
    <plugins>
        <!-- 编码规约扫描命令: mvn pmd:pmd-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-pmd-plugin</artifactId>
            <version>${maven.pmd.version}</version>
            <configuration>
                <!-- enable incremental analysis -->
                <analysisCache>true</analysisCache>
                <!-- analysisCacheLocation: optional - points to the following location by default -->
                <analysisCacheLocation>${project.build.directory}/pmd/pmd.cache</analysisCacheLocation>
                <!-- failOnViolation is actually true by default, but can be disabled-->
                <failOnViolation>false</failOnViolation>
                <!-- printFailingErrors is pretty useful-->
                <printFailingErrors>true</printFailingErrors>
                <sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
                <targetJdk>${project.build.version}</targetJdk>
                <linkXRef>true</linkXRef>
                <rulesets>
                    <ruleset>rulesets/java/ali-comment.xml</ruleset>
                    <ruleset>rulesets/java/ali-concurrent.xml</ruleset>
                    <ruleset>rulesets/java/ali-constant.xml</ruleset>
                    <ruleset>rulesets/java/ali-exception.xml</ruleset>
                    <ruleset>rulesets/java/ali-flowcontrol.xml</ruleset>
                    <ruleset>rulesets/java/ali-naming.xml</ruleset>
                    <ruleset>rulesets/java/ali-oop.xml</ruleset>
                    <ruleset>rulesets/java/ali-orm.xml</ruleset>
                    <ruleset>rulesets/java/ali-other.xml</ruleset>
                    <ruleset>rulesets/java/ali-set.xml</ruleset>
                </rulesets>
            </configuration>
            <executions>
                <!-- 绑定pmd:check到verify生命周期 -->
                <execution>
                    <id>inspection-code-by-pmd</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>check</goal>
                    </goals>
                </execution>
                <!-- 绑定pmd:pmd到site生命周期 -->
                <execution>
                    <id>pmd-pmd-site</id>
                    <phase>site</phase>
                    <goals>
                        <goal>pmd</goal>
                    </goals>
                </execution>
            </executions>
            <!-- p3c依赖 -->
            <dependencies>
                <!-- https://mvnrepository.com/artifact/com.alibaba.p3c/p3c-pmd -->
                <dependency>
                    <groupId>com.alibaba.p3c</groupId>
                    <artifactId>p3c-pmd</artifactId>
                    <version>${p3c.pmd.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
    
    • mvn pmd:check

      • 红框中则是代码检查结果

    2.2 IDEA集成插件

    由于我们使用了阿里提供的p3c-pmd插件,理论上IDEA上只需要按照Alibaba Java Coding Guidelines即可,但是建议也把PMD插件安装上

    2.2.1 IDEA安装阿里巴巴Java代码规约插件

    • IDEA版的插件已发布到IDEA官方仓库中(最低支持版本14.1.7,JDK1.7+),只需打开File-- Settings --Plugins – Browse repositories 输入 Alibaba 搜索便可以看到对应插件,点击安装等待安装完成。IDEA会自动检测插件新版并提示。
      • File–Setting–Plugins–Marketplace

    检索alibaba,第一个就是Alibaba Java Coding Guidelines,点击右侧Install即可,安装完毕后重启IDEA即可。

    重启IDEA后,可以看到Tools菜单下面有阿里编程规约的插件,有三项子功能:

    • 编程规约扫描(快捷键Ctrl+Alt+Shift+J)

    • 关闭/打开实时检测功能

    • 切换语言至英文(English):点击后提示:SmartFox Intellij IDEA Plugin切换语言成功,重启后生效

    2.2.2 阿里代码规约插件的使用

    1. 代码检查 Inspections

      File-Settings-Editor- Inspections,打开后右侧找到Ali-Check,可以看到很多代码检查规则,可以修改规则对应提示的颜色。这里一共有55条规则。

      • 变量test_Double命名不符合驼峰形式,高亮显示,Ctrl+F1给出修改提示
      • 常量Test_CONSTANT命名不符合规范,高亮显示,Ctrl+F1给出修改提示

    1. 代码分析Code Analyze

      在当前类中右键或者在左侧Project视图中类名称上右键,选择Alibaba Coding Guidelines Analyze, 可以对某一个类进行代码分析;也可以直接在Project视图中,项目的包上面单击右键,选择Alibaba Coding Guidelines Analyze,可以批量分析包中所有类

    2.2.3 安装PMD插件

    • File–Setting–Plugins–Marketplace 搜索PMDPlugin插件,并点击installed后重启idea

    • 在当前类中右键或者在左侧Project视图中类名称上右键,选择Run PMD行代码分析;也可以直接在Project视图中,项目的包上面单击右键,选择Run PMD,可以批量分析包中所有类

    在这里插入图片描述

    三、JaCoCo 代码测试用例覆盖率

    3.1 JaCoCo简介

    • JUnit只是编写单元测试的一个框架,并没有涉及到代码覆盖率,而JaCoCo提供了该功能;
    • JaCoCo是一个免费的Java代码覆盖率的库,能帮助检测出代码覆盖率,并输出覆盖率报告
    • JaCoCo提供了以下几个维度的覆盖率分析
      • 指令覆盖率(Instruction Coverage)
      • 分支覆盖率(Branch Coverage)
      • 圈复杂度覆盖率(Cyclomatic Complexity Coverage)
      • 行覆盖率(Line Coverage)
      • 方法覆盖率(Method Coverage)
      • 类覆盖率(Class Coverage)

    3.2 IDEA集成JaCoCo

    3.2.1 在Maven项目最外层pom.xml中引入JaCoCo插件

    <properties>
        <jacoco.version>0.8.5</jacoco.version>
    </properties>
    <plugins>
    	<plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
            <configuration>
                <append>true</append>
            </configuration>
            <executions>
                <execution>
                    <id>jacoco-initialize</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                    <phase>test-compile</phase>
                </execution>
                <execution>
                    <id>jacoco-site</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    

    3.2.2 执行maven jacoco生成代码覆盖率报告

    • maven执行命令:

      mvn clean test
      
    • 本地生成JaCoCo代码覆盖率文件(jacoco.exec)

    • 生成可视化jacoco文件(sonar也可以可视化jacoco文件,将在介绍sonar时介绍)

      mvn clean verify
      
      1. target/site/jacoco目录生成index.html文件

      • 网页可视化视图展示代码覆盖率

    注:IDEA 没有JaCoCO插件

    四、sonar持续代码质量检查

    SonarQube是一个代码质量管理工具,能对20多种编程语言源码进行代码味道(CodeSmells)、Bug、安全漏洞方面的静态分析。官方网站(https://www.sonarsource.com/plans-and-pricing/)

    主要特点:

    1. 代码覆盖:通过单元测试,将会显示哪行代码被选中改善编码规则
    2. 搜寻编码规则:按照名字,插件,激活级别和类别进行查询
    3. 项目搜寻:按照项目的名字进行查询
    4. 对比数据:比较同一张表中的任何测量的趋势

    4.1 Maven与SonarQube集成

    4.1.1 在多模块的项目的最外层pom.xml设置sonar配置

    <properties>
        <!-- sonar key -->
    	<sonar.projectKey>sonar:cornerstone</sonar.projectKey>
        <!-- sonar name -->
        <sonar.projectName>cornerstone</sonar.projectName>
        <!-- sonar 把jacoco测试用例上传 -->
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <!-- sonar host -->
        <sonar.host.url>http://10.0.204.90:9000</sonar.host.url>
        <!-- sonar token -->
       <sonar.login>*********************************</sonar.login>
       <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
        <!--将所有jacoco定位到同样的父目录位置-->
      <sonar.jacoco.reportPaths>target/jacoco.exec</sonar.jacoco.reportPaths>
      <sonar.language>java</sonar.language>	
    </properties>
    

    4.1.2 对要上传的model(cornerstone-edge)的pom.xml进行配置

    <properties>
         <!-- sonar config: key-->
        <sonar.projectKey>css:cornerstone-edge</sonar.projectKey>
        <!-- sonar config: name-->
        <sonar.projectName>cornerstone-edge</sonar.projectName>
    </properties>
    

    4.1.3 执行mvn命令,把sonar关于代码检测和JaCoCo代码覆盖率上传到sonar服务器中

    1. 执行mvn命令
    # 到cornerstone-edge模块的目录
    cd cornerstone-edge
    # 执行sonar
    mvn sonar:sonar
    
    1. 把sonar关于代码检测和JaCoCo代码覆盖率上传到sonar服务器中

      • target/sonar 目录生成
      • 控制台会有sonar服务器中该项目的访问地址

    • sonar服务器页面可视化查看sonar执行结果

      • 其中页面上的Coverage为JaCoCo的代码测试用例覆盖率
      • 其它为sonar自身分析的模块
    ![](https://img-blog.csdnimg.cn/20200622181042871.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpdXpodXBlbmc=,size_16,color_FFFFFF,t_70)
    

    4.2 IDEA集成SonarLint插件(如果sonar服务器已经集成阿里P3C,则不太推荐)

    4.2.1 SonarLint使用初步体验:

    • SonarLint发现的问题后,会根据问题类型给出推荐的的范例代码协助开发人员找到合适的修改思路.

    • 但是默认规则从代码规范,命名,可以省略不必要代码,方法逻辑复杂度等多个维度进行规范评估,给出信息种类过于多,试用之后,根据需要先定制下使用哪些规则,才更好有针对性的使用.

    • 错误发现有时候不如FindBugs.
      见下图iqtAnalysisTsmMap是一个key类型是String的Map,KeySB是StringBuffer类型.SonarLint没有发现这个BUG.

       Map<String, IqtAnalysisTsm> iqtAnalysisTsmMap 	 = new HashMap<>();
       StringBuilder keySB = new StringBuilder();
      if(iqtAnalysisTsmMap.containsKey(keySB)){
      	//TODO:
      }
      

    4.2.2 IDEA安装插件SonarLint

    1. File–Setting–Plugins–Marketplace 搜索SonarLint插件,并点击installed后重启idea

    1. 配置SonarLint

      • File–setting–Tools–SonarLint-- +
        • 选择sonarqube,并填URL:http://10.0.204.90:9000

    • 选择token登录,并填写token文本框:ce270177f461509e0cb9c0ac6e4b343c96e1188a

    • 是否开启自动分析:

      • 这里上面红框Automatically trigger analysis有配置是否允许自动分析,默认是勾选上的,开启自动分析功能,根据自己需求选择是否需要勾选开启.
      • 更新获取远程SonarQube配置当远程SonarQube有更新,可以点击下面红框里的按钮Update Binding行更新.
      • 保存配置
        • 点击下图中的Apply否则配置不会保存!
        • 点击下图中的Apply否则配置不会保存!
        • 点击下图中的Apply否则配置不会保存!
          在这里插入图片描述
    1. 配置SonarLint Project Settings

      • 选择下图中SonarLint Project Settings的菜单
      • 勾选Enable binding to remote SonarQube server
      • 在Bind to server 右边下拉选择刚才配置的 sonar配置名称
      • 配置SonarQube project,可以点击Search in List,再弹出框里找到想使用的某个规则选择想使用的即可.
      • 点击Apply使得配置生效保存

    1. 查看SonarLint窗口

      默认会在IDEA底部打开sonarLint标签窗口菜单.

    如果没有,或者不小心关闭了.
    可以点击菜单 view->Tool Windows中找到 SonarLint.重新打开SonarLint窗口

    1. 使用SonarLint

      在项目目录结构中选择要分析的文件夹或是代码文件,右键菜单Anaylyze->**Analyze with SonarLint Https…**或者选中后使用快捷键 Ctrl+Shift+S
      在这里插入图片描述


    更多内容请关注微信公众号:
    在这里插入图片描述

    展开全文
  • 优点—— RBF神经网络有很强的非线性拟合能力,可映射任意复杂的非线性关系,而且 学习规则简单,便于计算机实现。...单中奖一般在2个以上,复试一般在4-6 个红球。预测可靠性远远高于网络彩票预测机构的水准。
  • 矿井自燃火区氮气灭火时发现,煤体的温度仍会在高温中维持段时间,高温下煤样对氮气的吸附影响着煤氧化自燃特性。以锡盟褐煤为研究对象,将煤样分别在200℃下吸附氮气6、12、18 h,通过分析实验煤样的气相产物及氧气...
  • 篇博文对缓存的思考——提高命中详细介绍了高速缓存的组织结构,并通过实例说详细明了cpu从高速缓存中取数据的过程,对于缓存的工作机制应该有了清晰的认识。这篇博文就来简单讨论以下对于缓存在实际开发中的...

    开篇

    上一篇博文对缓存的思考——提高命中率详细介绍了高速缓存的组织结构,并通过实例说详细明了cpu从高速缓存中取数据的过程,对于缓存的工作机制应该有了清晰的认识。这篇博文就来简单讨论以下对于缓存在实际开发中的应用,这里将告诉你如何让你的程序充分利用该缓存,即如何编写高速缓存友好的代码。
    提示:如果高速缓存的运行机制还没有清晰的认识,请参照前面文章。
    注1:关于文中提到的局部性的相关知识参照:局部性原理浅析——良好代码的基本素质
    注2:这是一个系列的文章,收录在 程序性能优化
    注3:文章知识有些地方不容易理解,所以用心才能看完噢。
     

    “用空间换时间”

    在搞算法的时候经常能听到这种说法,算法研究中通常要考虑算法的时间、空间复杂度。而这里“用空间换时间”说的是通过牺牲一些存储块代码更有效的利用缓存。从而提高程序的运行效率。可见,高效的代码不仅依赖于良好的算法,编写缓存有好代码也很重要
    我们将通过下面的例子来认识这一过程
    注:这里假设高速缓存是直接映射的,即每一组只有一行。

    通过”局部性“相关的知识,我们可以看出上面的代码有良好的空间局部性:一维向量 x[ ] 、y[ ]  都是对其元素进行步长为1的顺序访问。那么,拥有良好局部性的代码,是否就能有效的利用高速缓存呢。不一定。
    设上面代码运行在拥有直接映射缓存的计算机上。
    为了把问题描述清楚,这里有一些假设
    1、float 是4 byte,所以数组x[ ]占用空间为32byte,y[ ]也一样
    2、x[ ]存储在内存中地址0-31的位置,y[ ]紧随其后在地址开始为32的连续位置。(如果觉得牵强你可理解为虚拟地址)
    3、直接映射高速缓存有两个组,每组的大小为16byte。也就是高速缓存中每组可存储4个元素。
     
    根据这些假设,每个x[i]、y[i]会被映射到相同的高速缓存组
    元素和缓存之间的映射关系如下图所示

    图被中间的双线条分为左右两栏,左边是x[ ]的情况,右边y[ ]的情况。
    看左边的一栏,左边的一列代表的x 中的元素,中间的是元素在内存中的地址,第三列是该元素映射在缓存中的组号。
    为什么会是这样分配的呢,其实在上一篇博文中就有提到。(参看前面的博客会有更好的效果)
    这里还是简单的说一下:
    主存中的数据是根据地址被映射到缓存的不同位置的,二进制地址的不同位代表不同的信息,一般来说从左到右分别代表:行、组、偏移
    缓存的每一行是16byte,从而可推断缓存的地址位是4 。因为4个二进制的组合共有16种情况(也即2的4次方是16)。
    下表是它们地址各个位及代表的信息。
    X[ ]:

    注:这里的地址不是元素的真实地址,指的是块地址。x有八个元素,每个元素占四个byte,我们把这四个byte当作一个整体, 那么x[0]就是第一块,x[1]为第二块,以此类推。y的情况相同。
    上图中,阴影部分的为地址的二进制表示形式。每个地址被表示成了四位的二进制数。
    其中:
    左边一位标记行。因为是直接映射,每组只有一行,所以一位就能表示。
    左边第二位标记组。我们讨论的这个缓存只有两个组,一位就能标记。
    右边两表示偏移。每行中有四个数据块,所以两位能标识。
    可以看出,x[ ]的前四个元素属于同一组,后四个为另一组。
    下面是y[]的情况:

    现在对于刚才那个图(如下)应该有更清楚的认识了把。

    x[i]和y[i]有相同的组标记、不同的行标记,这就意味着x[i]和y[i]不能同时存在于缓存中。
    下面模拟一下上述代码的执行过程。我们假设局部变量sum存于cpu寄存器中。
    计算x[0]*y[0]
    取x[0]
    刚开始的时候缓存还没预热,每一行的标记为都为不可用。所以取x[0]的时候缓存不命中,缓存从下一级存储中取出包括x[0]的整行,放入缓存第0组中,并返回x[0]给cpu。这时缓存第一组中的元素有x[0]、x[1]、x[2]、x[3]
    此时缓存的情况如下图所示

    缓存中的元素为蓝色背景的部分
    组序号为1的行都还没初始化。
    取y[0]
    y[0]对应的块地址是8,即1 0 00 组标记是0,行标记1,不命中。于是取出包括y[0]的行,并放入缓存中。此时的缓存情况:

    取x[1],缓存不命中,当取了x[0]本有x[1]在缓存中,当取y[0]的时候,这一行被覆盖了。所以只能把包括x[1]行的行取出放入缓存(覆盖y行),并返回x[1]。取了x[1]后的缓存情况和取出x[0]的情况一样:
    当取y[1]的时候,缓存不命中,又把上面x行替换为y行。
    可以推理出,取出x和y 的元素总是不命中。
    空间换时间
    因为x[i]、y[i]映射到了相同的组,现在的这种情况称为冲突不命中,每次对x和y 的引用都会造成冲突不命中。这一情况用“抖动”来描述。
    简单的说,即使程序有良好的时间局部性,且缓存也有足够大小的空间来缓存,也会发生抖动。因为x[i]、y[i]被映射到了相同的缓存组。
    幸运的是,可以修正这种情况,让x[i],y[i]映射到不同的缓存组。
    个简单的方法就是增加x的长度。给x分配12个float大小的空间。这样y的其实地址就是18而不是32
    如下图所示:

    这样当引用x[0]的时候把x[0]、x[1]、x[2]、x[3]放入组0中,引用y[0]的时候把y[0],y[1],y[2],y[3]放入组1 中。
    于是对引用x[1]~x[3]的引用就就能直接从缓存中获取,同样对y[1]~y[3]的引用也能从缓存中获取
    相比于刚开始的情况,大大增加了缓存的使利用。同时也提高了程序的性能,特别是当数据量很大的时候。
    实质通过在x的后面追加元素,让y的其实地址后移,让y对应的组号发生改变。当然在x后面追加元素只是占用了一部分空间,那些空间并没有被利用,但是提高了程序的性能。
    所以才说“用空间换时间”
     

    为什么用中间位作为组索引?

    用中间位作为组索引是有原因的。

     
    如果用最高位做索引
    情况如上图中的中间所示,连续的块都别映射到了同一个组中(特别的,如果是直接映射高速缓存,连续的块被映射到同一行中)这样的确也能利用缓 存,如上图所示,当引用第一个元素的时候,会把第1、2、3、4个拷贝到缓存的组0中,以后对2、3、4的引用就能直接在缓存中提取。引用第5个元素的时 候,把第5、6、7、8个拷贝到缓存的组1中,同样的,对4、5、6的引用能直接在缓存中提取。后面的情况类似就不再叙述。 
    通过上面的叙述,你可能已经发现一个问题:当对缓存的组1进行操作的时候,缓存中的其它组是没有被利用的,这和缓存中只有一个组其实效果是一样的。对缓存中的其他组没有很好的利用,也就是说,虽然也有缓存的利用,但有最大化。
    改用中间位做索引,如上图中的右图所示,同一组中的块不再是连续的,这样可以保证缓存中的所有组都能被有效的利用。
    引用第1个元素的时候,将把第1、5、9、13放入缓存组1中
    引用第2个元素的时候, 把第2、6、10、14放入缓存
    引用第3个,把3、7、11、15放入缓存
    引用第4个,把4、8、12、16放入缓存
    这样对前四个元素的引用都不会命中,而而对后面的引用都能命中。这种过程也就是所谓的缓存预热
     

    高速缓存友好代码

    一维数组
    上面的讨论我们假设了一种特殊的情况,下面将对如何编写高速缓存友好代码做更加泛化的讨论
    先看下面的代码

    很容易看出,上面的代码有良好的局部性。编译器对代码优化的时候 ,通常会将局部变量用寄存器保存(因为他们在函数结束时就会被释放)。一般来说,如果一个高速缓存块大小为Bbyte,那么在一个步长为k的引中,平均每 次迭代会有min (1; (wordsize k)=B )次缓存不命中。k=1时取最小值。
    Example
    假设v是块对齐的,字为4个字节,高速缓存块为4个字,高速缓存初始化为空。那么对v的步长为1 的引用情况如下所示

    图中的m,表示miss,即不命中;h表示hit 表示命中。
    这个例子中,对v[0]的引用不命中,而接下来对v[2]~v[4]的引用命中,
    对v[5]不命中,接下来对v[6]~v[7]引用命中。
    上面的叙述说明了两个问题:
    1、对局部变量的反复引用是好的,因为他们存在寄存器中,访问数度很快
    2、对步长为1的引用是好的,因为存储器结构中将数据存放为连续的块
     
    多维数组
    在对多维数组的操作中,空间局部性尤为重要。
    考虑下面的例子

    c语言以行序为主序的,所以上述代码刚好是对数组a[][]的步长为1的引用,和上一种情况一样,假设刚开始的缓存是冷缓存(刚开始的时候缓存里没有任何数据)。那么对数组a[][]的访问将得到如下图所示的命中和不命中模式:

    对缓存有良好的使用。

    然而,对代码做一个微小的改动之后:

    这时以步长4对数组a[][]的元素进行引用,这种情况对数组将是一列一列引用而不是一行一行引用的。他们在缓存中的命中情况如下所示

    较高的不命中率对程序的运行效率有显著影响,因为从第一层存储中取出数据将花费比缓存中取数据多很多的时钟周期。

     

    小结

     好的程序代码不仅要有好的算法,对计算机硬件的充分利用也是很关键的一步, 前面几篇文章主要只是从缓存角度做了分析。

    在缓存角度,要提高程序运行效率,编写缓存友好代码尤为关键,这也是区分程序员层次的一个标准,要求较高,需要你掌握缓存的工作原理,缓存内部的组 织形式,还需要编译相关的知识,前面还有很多知识等值我们去学习,这里只是总结了自己的学习成果,分享给大家,希望对各位园友有用。

    我觉得写博客不是我的目的,博客只是我学习过程中的副产品而已,对于某些知识,你知道它是一回事,要把它讲出来却非得把它弄透彻不可,我把写博客当作学习的一部分,在总结的过程中提高,还能把成果分享,我想这就是博客最大的价值把,我们都应该享受写博客的这个过程。

     预:下一篇博文中会从缓存角度对《编程之美》中的一道题目做个讨论,里面的算法很巧妙,表面上看性能是提高了,从缓存角度却不然。

     全文完。

     

    参看资料:computer systems

     

    转自:http://www.cnblogs.com/yanlingyin/archive/2012/02/15/thinkingincache.html






    本文转自夏雪冬日博客园博客,原文链接:http://www.cnblogs.com/heyonggang/archive/2012/12/17/2821593.html,如需转载请自行联系原作者

    展开全文
  • 章设计任务 1.1、零件设计任务 零件简图:如图1 所示 生产批量:小批量 材料:Q235 ...由于该零件的条料卸料力不大,故采用前结构,并且使用橡胶作为弹性零件。 5、导向装置 采用二导柱式模架。
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    .4 添 加 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型 .28 4.2 引 用 类 型 .33 4.3 装箱和拆箱 .39 4.4 小 结 .42 第五章 变量和常量 .44 5.1 变 量...
  • click:通过组合的方式来创建精美命令行界面的包。 cliff:个用于创建命令行程序的框架,可以创建具有多层命令的命令行程序。 clint:Python 命令行程序工具。 docopt:Python 风格的命令行参数解析器。 ...
  • C#微软培训资料

    2014-01-22 14:10:17
    .4 添 加 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型 .28 4.2 引 用 类 型 .33 4.3 装箱和拆箱 .39 4.4 小 结 .42 第五章 变量和常量 .44 5.1 变 量...
  • 论文检测系统软件,免费分享 反抄袭

    千次下载 热门讨论 2012-03-03 12:25:30
    通过对文档关键语义片段的识别、检测,可检测出文档中存在的不当引用、过度以用,甚至是抄袭等现象,并计算出文档的引用、复写和自写等重要指标,为各级论文评定、检测、发表机构提供论文评定和论文收录的检测...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    、Java基础知识 1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别。 2.字符串的操作: 写个方法,实现字符串的反转,如:输入abc,输出cba 写个方法,实现字符串的替换,如:输入...
  • DBX260中文说明书

    2013-04-24 11:07:35
    要想在个程序配置中漫游,可通过使用DriveRackTM 260奇才设置优化你的系统,DriveRackTM 260的这个特性使系统设置更快捷、更精确。奇才菜单提供系统设置、自动EQ和AFS/Advanced Feedback Suppression(先进的反馈...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    种分组机制,把各种各样的模型元素通过内在的语义连在一起成为个整体就叫做包 包的关系 包--软件比赛作品 架构图--包图的变形 任务4 UML动态建模机制 对象之间的交互 状态图 交互图 活动图 四种图的...
  • 年国际标准化组织也通过了这标准。以后通过对 的不断修改和完善,于年第二次公布了标准 年又公布了标准 即 。最新的标准是 (也称 年作为 《信息技术——数据库语言》发布。我国也相继 公布了数据库语言的...
  • 引入了更多的 Python 特性:单独加了章来介绍一些第版中没有提及的 Python 功能,比如列表解析和附加的数据结构。 这本书是本自由的书,遵循创作共用署名-非商业性使用-第三版协议,这意味着你可以自由地...
  • 默认情况下transform方法的cut参数为True,即采用分词匹配的方式,这种方式速度比较快,但是准确可能会比较低,如果追求准确而不追求速度的话,建议将cut设为False(全文模式),具体见下小节。 尝试着对代码...
  • 本文档还有个重要的特点,那就是根据自己看官方手册的经验,教大家如何看手册从而更有效!由于是初学,很多术语或解释难免理解有偏差,所以一定要看官方提供的文档与手册,那才是学习的最佳途径! 2. 开始学习 ...
  • 测试培训教材

    2014-04-01 12:10:48
    :由于Cruise Booking的测试是由Cruise Booking的需求转化而成的,所以需求覆盖中默认就覆盖了Cruise Booking的需求项 添加对“View Reservations”需求项的覆盖 -- Linking Tests to a Requiremnet 将测试...
  • 所谓软硬结合方式,就是首先通过专用的图像抓拍设备获取幅适合于计算机识别汽车牌照的高质量图像,然后用软件和硬件结合的方式对所获取的专用图像进行牌照识别,它的最大优点就是识别高,能够全天候工作。...
  • .Linux的文件系统结构.....................................................................................................6 二. 文件类型................................................................

空空如也

空空如也

1 2 3
收藏数 60
精华内容 24
关键字:

一注结构通过率