运行期优化

前言

  在部分的商用虚拟机中,Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行特别频繁的时候,就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler),也就是JIT。

  即时编译器不是虚拟机必须的部分,但是,即时编译器编译性能的好坏、代码优化程度的高低却是衡量一款商用虚拟机优秀与否的最关键指标之一,它也是虚拟机中最核心且最能体现虚拟机技术水平的部分。

  HotSpot既包含解释器也包含即时编译器,本篇文章讲述的都是关于HotSpot虚拟机的运行期优化。

解释器和编译器

  解释器是一条一条的解释执行源语言。  

  编译器是把源代码整个编译成目标代码,执行时不再需要编译器,直接在支持目标代码的平台上运行,这样执行效率比解释执行快很多。

解释器的优势:

  1. 当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行;

  2.当程序运行环境中内存资源限制较大,可以使用解释执行节约内存;

  3.解释器还可以作为编译器激进优化时的一个“逃生门”,让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立,如加载了新类后类型继承结构出现变化、出现“罕见陷阱”时可以通过逆优化退回到解释状态继续执行。

编译器的优势:

  1.在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之中,可以获取更高的执行效率;

  2.在程序运行环境资源比较充足的时候,使用编译器可以提高代码的执行效率;

虽然上述把编译器和解释器分开来讲,但其实在整个的虚拟机执行架构中,解释器和编译器经常配合工作,如下图所示:

   HotSpot虚拟机中内置了两个即时编译器,分别称为Client Compiler 和 Server Compiler,或者简称为C1编译器和C2编译器(也叫Opto编译器)。目前主流的HotSpot虚拟机中,默认采用解释器与其中一个编译器直接配合的方式工作,程序使用哪个编译器,取决于虚拟机运行的模式,HotSpot虚拟机会根据自身版本与宿主机器的硬件性能自动选择运行模式,用户也可以使用“-client”或“-server”参数去强制指定虚拟机运行在Client模式或者Server模式。

编译对象和触发条件

  在运行过程中会被即时编译器编译的“热点代码”有两类,即:

    (1)被多次调用的方法;

    (2)被多次执行的循环体;

  对于第一种情况,由于是由方法调用触发的编译,因此编译器理所当然地会以整个方法作为编译对象,这种编译也是虚拟机中标准的JIT编译方式。

  对于第二种情况,尽管编译动作是由循环体所触发的,但编译器依然会以整个方法(而不是单独的循环体)作为编译对象。这种编译方式因为编译发生在方法的执行过程中,因此形象地称之为栈上替换(On Stack Replacement,简称为OSR编译,即方法栈帧还在栈上,方法就被替换了)。

那么到底执行多少次才算是多次执行呢?也就是说即时编译器触发的条件是什么呢?

  判断一段代码是不是热点代码,是不是需要触发即时编译,这样的行为称为热点探测(Hot Spot Detection),其实进行热点探测并不一定要知道方法具体被调用了多少次,目前主流的热点探测判定方式有两种:

    1.基于采样的热点探测(Sample Based Hot Spot Detection):采用这种方法的虚拟机会周期性地检查各个线程的栈顶,如果发现某个(或某些)方法经常出现在栈顶,那这个方法就是“热点方法”。

      优点:实现简单、高效,还可以很容易地获取方法调用关系(将调用堆栈展开即可);

      缺点:很难精确的确认一个方法的热度,容易受到线程阻塞或别的外界因素的影响而扰乱热点探测;

    2.基于计数器的热点探测(Counter Based Hot Spot Detection):采用这种方式的虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值就认定它是“热点方法”。

      优点:结果更加的精确和严谨;

      缺点:实现起来比上一种方式更加麻烦,需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系;

  在HotSpot中使用的是第二种—基于计数器的热点探测方法,它为每个方法准备了两类计数器:方法调用计数器(Invocation Counter)和回边计数器(Back Edge Counter)。在确定虚拟机运行参数的前提下,这两个计数器都有一个确定的阀值,当计数器超过阀值溢出了,就会触发JIT编译。来分别看一下:

❤ 方法调用计数器

  顾名思义,这个计数器就用于统计方法被调用的次数,它的默认阀值在Client模式下是1500次,在Server模式下是10000次,这个阀值可以通过-XX:CompileThreshold来人为设定。当一个方法被调用时,会先检查该方法是否存在被JIT编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加1,然后判断方法调用计数器与回边计数器之和是否超过调用计数器的阀值。如果已经超过阀值,那么将会向即时编译器提交一个该方法的代码编译请求。

  如果不做任何设置,执行引擎并不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成。当编译工作完成之后,这个方法的调用入口地址就会被系统自动改写成新的,下一次调用该方法时就会使用已编译的版本。

  如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,也就是一段时间之内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减,而这段时间就称为此方法统计的半衰周期。进行热度衰减的动作是在虚拟机进行垃圾回收时顺便进行的,可以使用虚拟机参数-XX:-UseCounterDecay 来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样,只要系统运行的时间足够长,绝大部分方法都会被编译成本地代码。另外,可以使用-XX:CounterHalfLifeTime参数设置半衰期的时间,单位是秒(S)。

❤ 回边计数器

  它的作用是统计一个方法体中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”。显然,建立回边计数器的目的就是为了触发OSR编译。HotSpot虚拟机也提供了一个类似于方法调用计数器阀值-XX:CompilerThreshold的参数-XX:BackEdgeThreshold供用户设置,但是当前的虚拟机实际上并未使用此参数,因此,我们需要设置另外一个参数-XX:OnStackReplacePercentage来间接调整回边计数器的阀值,其计算公式如下:

  Client模式下:方法调用计数器阀值 *  OSR比率 / 100。其中OnStackReplacePercentage默认值为933,如果都取默认值,那Client模式虚拟机的回边计数器的阀值为13995.

  Server模式下:方法调用计数器阀值 * (OSR比率 - 解释器监控比率)/ 100。其中OnStackReplacePercentage默认值为140,InterpreterProfilePercentage默认值为33,如果都取默认值,那Server模式下虚拟机回边计数器阀值为10700。

  当解释器遇到一条回边指令时,会先查找将要执行的代码片段是否有已经编译好的版本,如果有,它将会优先执行已编译的代码,否则就把回边计数器的值加1,然后判断方法调用计数器和回边计数器值之和是否超过回边计数器的阀值。当超过阀值的时候,将会提交一个OSR编译请求,并且把回边计数器的值降低一些,以便继续在解释器中执行循环,等待编译器输出编译结果。

  与方法计数器不同,回边计数器没有计数热度衰减的过程,因此这个计数器统计的就是该方法循环体执行的绝对次数。当计数器溢出的时候,它还会把方法计数器的值也调整到溢出状态,这样下次进入该方法的时候就会执行标准编译过程(就是将整个方法进行即时编译)。

编译过程

  在默认设置下,无论是方法调用产生的即时编译请求,还是OSR编译请求,虚拟机在代码编译器还未完成之前,都仍然按照解释方式继续执行,而编译动作则在后台的编译线程中进行。可以通过参数-XX:-BackgroundCompilation来禁止后台编译,在禁止后台编译后,一旦达到JIT的编译条件,执行线程向虚拟机提交编译请求后将会一直等待,直到编译过程完成后再开始执行编译器输出的本地代码。

  在后台编译的过程中,Server Compiler 和Client Compiler 两个编译器的编译过程是不一样的。

  对于Client Compiler 来说,它是一个简单快速的三段式编译器,主要的关注点在于局部性的优化,而放弃了许多耗时较长的全局优化手段。

  Server Compiler 是专门面向服务端的典型应用并为服务端的性能配置特别调整过的编译器,也是一个充分优化过的高级编译器,几乎能达到 GNU C++编译器使用 -O2参数时的优化强度,它会执行所有经典的优化动作。如无用代码消除、循环展开、循环表达式外提,消除公共子表达式、常量传播等。还会实施一些与Java语言特性密切相关的优化技术,如范围检查消除、空值检查消除等,另外还可能根据解释器或Client Compiler 提供的性能监控信息,进行一些不稳定的激进优化,如守护内联、分支频率预测等。

编译优化技术

  Java程序员有一个共识,以编译方式执行本地代码比解释方式更快,之所以有这样的共识,出去虚拟机解释执行字节码时额外消耗时间的原因外,还有一个很重要的原因就是虚拟机设计团队几乎把对代码的所有优化措施都集中在了即时编译器中,因此,一般来说,即时编译器产生的本地代码会比Javac产生的字节码更加优秀。

  在Sun官方的Wiki上,HotSpot虚拟机设计团队列出了一个相对比较全面的、在即时编译器中采用的优化技术列表,其中有不少经典编译器的优化手段,也有许多针对Java语言(准确的说是针对运行在Java虚拟机上的所有语言)本身进行的优化技术,下面列举几项具有代表性的优化技术:

    ❤ 语言无关的经典优化技术之一:公共子表达式消除

    ❤ 语言相关的经典优化技术之一:数组范围检查消除

    ❤ 最重要的优化技术之一:方法内联

    ❤ 最前沿的优化技术之一:逃逸分析

公共子表达式消除

  公共子表达式消除是一个普遍应用于各种编译器的经典优化技术,它的含义是:如果一个表达式E已经计算过了,并且从先前的计算到现在E中所有变量的值都没有发生变化,那么E的这次出现就成为了公共子表达式。对于这种表达式,没有必要花时间再对它进行计算,只需要直接用前面计算过的表达式结果代替E就可以了。如果这种优化仅限于程序的基本块内,便称为局部公共子表达式消除,如果这种优化的范围涵盖了多个基本块,那就称为全局公共子表达式消除。举个简单的例子,假设存在如下代码:

int d = (c * b) * 12 + a + (a + b * c);

  如果这段代码交给Javac编译器则不会进行任何优化。但是当这段代码进入到虚拟机即时编译器后,它将进行如下优化:编译器检测到“c * b”与“b * c”是一样的表达式,而且计算期间b与c的值是不变的。因此,这条表达式就可能被视为:

int d = E * 12 + a + (a + E);

  这时,编译器还可能进行另外一种优化:代数简化,把表达式变为:

int d = E * 13 + a * 2;

  这样,表达式进行变换之后,再计算起来就可以节省一些时间了。

数组边界检查消除

  我们知道Java语言是一门动态安全的语言,对数组的读写访问也不像C、C++那样在本质上是裸指针操作,如果有一个数组foo[],在Java语言中访问数组元素foo[i]的时候将会自动进行上下界的范围检查,即检查i>=0&&i<foo.length这个条件,否则将会抛出一个数组下标越界异常。这对开发者来说是一件好事,即使程序员没有专门编写防御代码,也可以避免大部分的溢出攻击,但是对于虚拟机来说,每次数组元素的读写都带有一次隐含的条件判定操作,对于拥有大量数组访问的程序代码,无疑也是一种性能负担。

  无论如何,为了安全,数组边界检查肯定是必须做的,但数组边界检查是不是必须在运行期间一次不漏地检查则是可以商量的。比如数组下标是一个常量,只要在编译期间根据数据流分析来确定foo.length的值,并判断下标有没有越界,执行的时候就不需要判断了。更加常见的情况是数组访问发生在循环之中,并且使用循环变量来进行数组访问,如果编译器只要通过数据流分析尽可以判定循环变量的取值范围永远在区间[0, foo.length)之间,那整个循环中就可以把数组的上下界检查消除,这可以节省很多次的条件判断操作。

方法内联

  最重要的优化手段之一。它的目的主要有两个:去除方法调用的成本(如建立栈帧等)、为其他优化建立了良好的基础,方法内联膨胀之后可以便于在更大范围上采取后续的优化手段。方法内联举个例子:

public final int getA()
{getA()语句1;getA()语句2;getA()语句3;getA()语句4;getA()语句5
}
public static void main(String[] args)
{main语句1;main语句2;int i = getA();main语句3;main语句4
}

优化之后:

public static void main(String[] args)
{main语句1;main语句2;getA()语句1;getA()语句2;getA()语句3;getA()语句4;getA()语句5;main语句3;main语句4
}

  从效果上来看,无非是把getA()方法中的内容原封不动地拿到main函数中,但是这样却少了保护现场、恢复线程、建立栈帧等一系列的工作,并且代码一膨胀,原来方法A有5行代码,方法B有6行代码,方法C有7行代码,对于三个方法各自运行来说可能没有什么好优化的,但是三个方法合起来放到main函数中,就有了很大的优化空间了。

  讲到这里,是否理解为什么要尽量把方法声明为final?

  因为Java有多态的存在,运行时调用的是哪个方法可以根据实际的子类来确定,极大的增强了灵活性,但是这样的话,编译期间同样也无法确定应该使用的是哪个版本,所以无法被内联。但是声明为final的方法不一样,这些方法无法被重写,所以调用类A的B方法,运行时的调用的必然是类A的B方法,这样的话,这个方法就可以被内联。

逃逸分析

  目前Java虚拟机中比较前沿的优化技术,它并不是直接优化代码的手段,而是为其他优化手段提供了分析技术。

  逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中去,称为方法逃逸。甚至可能被外部线程访问到,比如赋值给类变量或可以在其他线程中访问到的实例变量,称为线程逃逸。如果能证明一个对象不会逃逸到方法外或者线程之外,也就是别的方法或线程无法通过任何途径访问到这个对象,则可能为这个变量进行一些高效的优化:

  (1)栈上分配

    Java虚拟机中,对象在堆上分配这个众所周知。虚拟机的垃圾收集系统可以回收堆中不再使用的对象,但回收动作无论是筛选可回收对象和整理内存都要耗费时间。如果确定一个对象不会逃逸出方法之外,那么让这个对象在栈上分配是一个不错的主意,对象所占用的内存空间就可以随着栈帧出栈而销毁,这样垃圾收集系统的压力将会小很多。

  (2)同步消除

    线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那么这个变量的读写肯定不会有竞争,对这个变量实施的同步措施就可以消除掉。

  (3)标量替换

    标量是指一个数据已经无法再分解成更小的数据来表示了,Java中的基本数据类型及引用类型都不能进一步分解,因此,它们可以称为标量。相对的,一个数据如果还可以继续分解,那么就称为聚合量,Java中的对象就是最典型的聚合量。如果逃逸分析证明一个对象不会被外部访问,并且这个对象可以被拆散的话,那程序真正执行的时候将可能不创建这个对象,而改为直接创建它的若干个被这个方法使用到的成员变量来代替。将对象拆分后,除了可以让对象的成员在栈上分配和读写外,还可以为后续进一步的优化手段创建条件。

逃逸分析技术现状和未来

  关于逃逸分析的论文1999年就已经发表,但直到Sun JDK1.6才实现了逃逸分析而且直到现在这项优化尚未足够成熟,仍有很大改进余地。不成熟的原因主要是不能保证逃逸分析的性能收益必定能高于它的消耗。虽然在实际测试结果中,实施逃逸分析后的程序往往能运行出不错的成绩,但是在实际的应用程序,尤其是大型程序中反而发现实施逃逸分析可能出现效果不稳定的情况,或因分析过程耗时但却无法有效判别出非逃逸对象而导致性能有所下降。

  如果有需要,并且确认对程序运行有益,可以使用参数-XX:+DoEscapeAnalysis来手动开启逃逸分析,开启之后可以通过参数-XX:+PrintEscapeAnalysis来查看分析结果。有了逃逸分析支持之后,就可以使用参数-XX:+EliminateAllocations来开启标量替换,使用参数-XX:+EliminatLocks来开启同步消除,使用参数-XX:+PrintEliminateAllocations查看标量的替换情况。

  尽管目前逃逸分析技术仍不是十分成熟,但是在今后的虚拟机中,逃逸分析技术肯定会支撑起一系列实用有效的优化技术。

参考:《深入理解Java虚拟机》 周志明 编著:

转载于:https://www.cnblogs.com/Joe-Go/p/10004151.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/484699.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第一章 计算机网络 6 OSI参考模型 [计算机网络笔记]

第一章 计算机网络 6 OSI参考模型 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; OSI参考模型的7层次结构及其功能OSI参考模型数据传输的过程 转载请注明文章来源&#xff01; 计算机网络的…

第二章 数据的表示和运算 2.1.3 字符与字符串 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.3 字符与字符串 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; ASCII码/汉字编码字符串在内存中的表示 转载请注明文章来源&…

评阅百篇博士论文后我发现:博士生发SCI越多,通常科研能力越差!

来源&#xff1a;秦四清科学网博客 作者&#xff1a;秦四清多年来&#xff0c;我评阅了上百部博士学位论文&#xff0c;也参加了上百次的博士学位论文答辩会&#xff0c;我和不少老师有一个共同的深刻感受&#xff1a;在攻读博士期间&#xff0c;发表了多篇sci论文的博士生&…

深入分析5nm芯片

来源&#xff1a; 半导体行业观察苹果公司于2020年10月发布了新型智能手机“iPhone 12”系列&#xff0c;搭载的是采用5纳米工艺的全球首个名为“A14 BIONIC”芯片。苹果公司将“A14 BIONIC”芯片应用到了iPhone 12、新款“iPad Air”。2020年11月苹果公司又发布了搭载“Apple …

第二章 数据的表示和运算 2.1.5 汉明(海明)校验码 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.5 汉明(海明)校验码 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; 海明&#xff08;Hamming&#xff09;校验码原理和编码方法 …

vivado下创建基本时序周期约束

创建基本时钟周期约束。&#xff08;验证我们的设计能否在期望的频率上运行&#xff09; &#xff08;学习记录&#xff0c;晚一点会做实验传上来的。&#xff09; 时钟基本概念&#xff1a;https://blog.csdn.net/wordwarwordwar/article/details/78259208 时序约束的基本概念…

我国的人工智能芯片的市场规模及发展前景

来源&#xff1a;人工智能实验室图片来源&#xff1a;网络随着深度学习技术的快速发展&#xff0c;以及互联网和云计算时代海量数据和高效计算能力的支撑&#xff0c;计算机视觉技术、语音技术、自然语言理解技术等人工智能技术取得了突破性进展&#xff0c;并解锁多个行业的人…

TiDB 架构及设计实现

一. TiDB的核心特性 高度兼容 MySQL 大多数情况下&#xff0c;无需修改代码即可从 MySQL 轻松迁移至 TiDB&#xff0c;分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。 水平弹性扩展 通过简单地增加新节点即可实现 TiDB 的水平扩展&#xff0c;按需扩展吞吐或存储&am…

南洋理工75页最新「深度学习对话系统」大综述论文,最全面概述深度学习对话技术进展...

来源&#xff1a;专知 摘要对话系统是一个流行的自然语言处理(NLP)任务&#xff0c;因为它在现实生活中应用前景广阔。这也是一个复杂的任务&#xff0c;因为涉及到许多需要研究的自然语言处理任务。因此&#xff0c;关于深度学习的对话系统研究的大量工作开展了。在这个综述中…

第二章 物理层 2,3 数据通信基础知识 [计算机网络笔记]

第二章 物理层 2,3 数据通信基础知识 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; (了解即可) 通信方式&#xff1a;单工/半双工/全双工传输方式&#xff1a;并行/串行传输同步/异步传输…

《GTA 5》走进现实!AI逼真还原游戏街景,还能“脑补”细节 | 英特尔出品

来源&#xff1a;AI科技评论作者&#xff1a;琰琰编辑&#xff1a;刘冰一在不少玩家眼中&#xff0c;GTA 5&#xff08;GTA V&#xff09;称得上是一款旷世神作&#xff01;GTA 也叫“侠盗猎车手”&#xff0c;是R星旗下一款超高人气动作冒险类游戏&#xff0c;目前已经发售至第…

对公平席位分配问题的探讨:最大余数法、Q值法和D’Hondt方法及其特例|公平分配原则等

公平席位分配问题 本文研究公平的席位分配问题。对席位分配问题中经典的最大余数法、Q值法和D’Hondt方法进行研究和比较&#xff0c;在提出公平性判断原则的基础上&#xff0c;分析其优缺点。本文使用Matlab搭建三种席位分配模型&#xff0c;并对结果展开讨论。给出最大余数法…

电动车产业深度报告:对比苹果,剖析特斯拉产业链投资机会 | 附完整报告下载...

报告出品方&#xff1a;兴业证券作者&#xff1a;戴畅 董晓彬 赵季新本篇报告对苹果产业链和特斯拉产业链进行了深度对比分析&#xff0c;前者引领消费电子黄金十年&#xff0c;后者将开启相关产业链赤金十年。1智能手机 vs 电动汽车&#xff1a;电动车方兴未艾&#xff0c;市场…

七牛云注册创建oss并配置自定义域名

1.登陆官网注册账号 有个人和企业两种,根据自己的情况进行注册 https://portal.qiniu.com/signup/choice 2.注册后要进行认证,不认证是没有免费空间给你使用的 3.创建对象存储,这个当然是选择离自己距离近的咯,更快的响应嘛 4.创建成功后,如果不想绑定到自己的域名的话,七牛云也…

状态转移法求解夫妻过河问题

状态转移法求解夫妻过河问题 摘 要 本文研究夫妻问题。主要运用“状态转移法”解决夫妻过河问题&#xff0c;并用Python编程实现&#xff0c;输出求解过程和结果。分析夫妻对数n和船载人数m和是否有解的关系&#xff0c;给出了该问题的一般提法和解法。 目 录 3.1 约束条件 1…

第二章 数据的表示和运算 2.1.6 循环冗余校验码/CRC码 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.6 循环冗余校验码/CRC码 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; 循环冗余校验码/CRC码 的生成和检错 转载请注明文章来源…

利用基于GPU的AI模拟一个现实宇宙 仅需36分钟

来源&#xff1a;The Next Web编译&#xff1a;科技行者科学家已经习惯于使用超级计算机处理宇宙学领域的海量数据&#xff0c;最近卡耐基梅隆大学的研究团队找到一种新方法&#xff0c;可以使用常规的机器学习技术(与AI绘画或作曲拥有同样的底层设计)&#xff0c;在图形处理单…

第七章:集成学习(利用AdaBoost元算法...)

---恢复内容开始--- 集成学习其实不能算一个算法&#xff0c;应该算是一种框架&#xff0c;集百家之长。集成算法具体有Bagging与Boosting两种大类。两者区别&#xff1a; 1)Bagging是并行的&#xff0c;它就好比找男朋友&#xff0c;美女选择择偶对象的时候&#xff0c;会问几…

GPT-3难以复现,为什么说PyTorch走上了一条“大弯路”?

来源&#xff1a;OneFlow 投稿责编&#xff1a;欧阳姝黎2020 年&#xff0c;最轰动的 AI 新闻莫过于 OpenAI 发布的 GPT-3 了。它的1750亿参数量及其在众多NLP任务上超过人类的出众表现让人们开始坚信&#xff1a;大模型才是未来。但与之带来的问题是&#xff0c;训练超大模型所…

生小兔问题

生小兔问题&#x1f430; 本文研究生小兔问题。使用代数模型&#xff0c;在考虑生育情况变化的情况下&#xff0c;求解兔子/白鼠的数目变化。 第1章 问题重述 生小兔问题 兔子出生后能够存活12个月&#xff0c;从第7月开始生小兔&#xff0c;7、8两月每对兔子生1对小兔/月&am…