阿里二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!

大家好,我是老赵

不知道从何时起,传出了这么一句话:Java中使用try catch 会严重影响性能。

然而,事实真的如此么?我们对try catch 应该畏之如猛虎么?

一、JVM 异常处理逻辑

Java 程序中显式抛出异常由athrow指令支持,除了通过 throw 主动抛出异常外,JVM规范中还规定了许多运行时异常会在检测到异常状况时自动抛出(效果等同athrow), 例如除数为0时就会自动抛出异常,以及大名鼎鼎的 NullPointerException 。

还需要注意的是,JVM 中 异常处理的catch语句不再由字节码指令来实现(很早之前通过 jsr和 ret指令来完成,它们在很早之前的版本里就被舍弃了),现在的JVM通过异常表(Exception table 方法体中能找到其内容)来完成 catch 语句;很多人说try catch 影响性能可能就是因为认识还停留于上古时代。

1、 我们编写如下的类,add方法中计算++x;并捕获异常;

public class TestClass {private static int len = 779;public int add(int x){try {// 若运行时检测到 x = 0,那么 jvm会自动抛出异常,(可以理解成由jvm自己负责 athrow 指令调用)x = 100/x;} catch (Exception e) {x = 100;}return x;}
}

2、 使用javap工具查看上述类的编译后的class文件;

编译javac TestClass.java使用javap 查看 add 方法被编译后的机器指令javap -verbose TestClass.class

忽略常量池等其他信息,下边贴出add 方法编译后的 机器指令集:

public int add(int);descriptor: (I)Iflags: ACC_PUBLICCode:stack=2, locals=3, args_size=20: bipush        100   //  加载参数1002: iload_1             //  将一个int型变量推至栈顶3: idiv                //  相除4: istore_1            //  除的结果值压入本地变量5: goto          11    //  跳转到指令:118: astore_2            //  将引用类型值压入本地变量9: bipush        100   //  将单字节常量推送栈顶<这里与数值100有关,可以尝试修改100后的编译结果:iconst、bipush、ldc> 10: istore_1            //  将int类型值压入本地变量11: iload_1             //  int 型变量推栈顶12: ireturn             //  返回// 注意看 from 和 to 以及 targer,然后对照着去看上述指令Exception table:from    to  target type0     5     8   Class java/lang/ExceptionLineNumberTable:line 6: 0line 9: 5line 7: 8line 8: 9line 10: 11StackMapTable: number_of_entries = 2frame_type = 72 /* same_locals_1_stack_item */stack = [ class java/lang/Exception ]frame_type = 2 /* same */

再来看Exception table:

5597ea5b68dd32c831e0608741bc1b37.png

from=0, to=5。指令 0~5 对应的就是 try 语句包含的内容,而targer = 8 正好对应 catch 语句块内部操作。

个人理解,from 和 to 相当于划分区间,只要在这个区间内抛出了type 所对应的,“java/lang/Exception” 异常(主动athrow 或者 由jvm运行时检测到异常自动抛出),那么就跳转到target 所代表的第八行。

若执行过程中,没有异常,直接从第5条指令跳转到第11条指令后返回,由此可见未发生异常时,所谓的性能损耗几乎不存在;

如果硬是要说的话,用了try catch 编译后指令篇幅变长了;goto 语句跳转会耗费性能,当你写个数百行代码的方法的时候,编译出来成百上千条指令,这时候这句goto的带来的影响显得微乎其微。

如图所示为去掉try catch 后的指令篇幅,几乎等同上述指令的前五条。

244c9ba3c7b20413947f723d5a479334.png

综上所述:“Java中使用try catch 会严重影响性能” 是民间说法,它并不成立。如果不信,接着看下面的测试吧。

二、关于JVM的编译优化

其实写出测试用例并不是很难,这里我们需要重点考虑的是编译器的自动优化,是否会因此得到不同的测试结果?

本节会粗略的介绍一些jvm编译器相关的概念,讲它只为更精确的测试结果,通过它我们可以窥探 try catch 是否会影响JVM的编译优化。

前端编译与优化:我们最常见的前端编译器是 javac,它的优化更偏向于代码结构上的优化,它主要是为了提高程序员的编码效率,不怎么关注执行效率优化;例如,数据流和控制流分析、解语法糖等等。

后端编译与优化:后端编译包括 “即时编译[JIT]” 和 “提前编译[AOT]”,区别于前端编译器,它们最终作用体现于运行期,致力于优化从字节码生成本地机器码的过程(它们优化的是代码的执行效率)。

1. 分层编译

PS* JVM 自己根据宿主机决定自己的运行模式, “JVM 运行模式”;[客户端模式-Client、服务端模式-Server],它们代表的是两个不同的即时编译器,C1(Client Compiler) 和 C2 (Server Compiler)。

PS* 分层编译分为:“解释模式”、“编译模式”、“混合模式”;

  • 解释模式下运行时,编译器不介入工作;

  • 编译模式模式下运行,会使用即时编译器优化热点代码,有可选的即时编译器[C1 或 C2];

  • 混合模式为:解释模式和编译模式搭配使用。

d42eec12e536f0bfe221ea16c8a16e78.png

如图,我的环境里JVM 运行于 Server 模式,如果使用即时编译,那么就是使用的:C2 即时编译器。

2. 即时编译器

了解如下的几个 概念:

1. 解释模式

它不使用即时编译器进行后端优化

  • 强制虚拟机运行于 “解释模式” -Xint

  • 禁用后台编译 -XX:-BackgroundCompilation

2. 编译模式

即时编译器会在运行时,对生成的本地机器码进行优化,其中重点关照热点代码。

强制虚拟机运行于 "编译模式"
-Xcomp
方法调用次数计数器阈值,它是基于计数器热点代码探测依据[Client模式=1500,Server模式=10000]
-XX:CompileThreshold=10
关闭方法调用次数热度衰减,使用方法调用计数的绝对值,它搭配上一配置项使用
-XX:-UseCounterDecay
除了热点方法,还有热点回边代码[循环],热点回边代码的阈值计算参考如下:
-XX:BackEdgeThreshold  = 方法计数器阈值[-XX:CompileThreshold] * OSR比率[-XX:OnStackReplacePercentage]
OSR比率默认值:Client模式=933,Server模式=140
-XX:OnStackReplacePercentag=100

所谓 “即时”,它是在运行过程中发生的,所以它的缺点也也明显:在运行期间需要耗费资源去做性能分析,也不太适合在运行期间去大刀阔斧的去做一些耗费资源的重负载优化操作。

3. 提前编译器:jaotc

它是后端编译的另一个主角,它有两个发展路线,基于Graal [新时代的主角] 编译器开发,因为本文用的是 C2 编译器,所以只对它做一个了解;

第一条路线:与传统的C、C++编译做的事情类似,在程序运行之前就把程序代码编译成机器码;好处是够快,不占用运行时系统资源,缺点是"启动过程" 会很缓慢;

第二条路线:已知即时编译运行时做性能统计分析占用资源,那么,我们可以把其中一些耗费资源的编译工作,放到提前编译阶段来完成啊,最后在运行时即时编译器再去使用,那么可以大大节省即时编译的开销;这个分支可以把它看作是即时编译缓存;

遗憾的是它只支持 G1 或者 Parallel 垃圾收集器,且只存在JDK 9 以后的版本,暂不需要去关注它;JDK 9 以后的版本可以使用这个参数打印相关信息:[-XX:PrintAOT]。

三、关于测试的约束

执行用时统计

System.naoTime() 输出的是过了多少时间[微秒:10的负9次方秒],并不是完全精确的方法执行用时的合计,为了保证结果准确性,测试的运算次数将拉长到百万甚至千万次。

编译器优化的因素

上一节花了一定的篇幅介绍编译器优化,这里我要做的是:对比完全不使用任何编译优化,与使用即时编译时,try catch 对的性能影响。

1、 通过指令禁用JVM的编译优化,让它以最原始的状态运行,然后看有无trycatch的影响;
2、 通过指令使用即时编译,尽量做到把后端优化拉满,看看trycatch十有会影响到jvm的编译优化;

关于指令重排序

目前尚未可知 try catch 的使用影响指令重排序;

我们这里的讨论有一个前提,当 try catch 的使用无法避免时,我们应该如何使用 try catch 以应对它可能存在的对指令重排序的影响。

指令重排序发生在多线程并发场景,这么做是为了更好的利用CPU资源,在单线程测试时不需要考虑。不论如何指令重排序,都会保证最终执行结果,与单线程下的执行结果相同;

虽然我们不去测试它,但是也可以进行一些推断,参考 volatile 关键字禁止指令重排序的做法:插入内存屏障;

假定 try catch 存在屏障,导致前后的代码分割;那么最少的try catch代表最少的分割。

所以,是不是会有这样的结论呢:我们把方法体内的 多个 try catch 合并为一个 try catch 是不是反而能减少屏障呢?这么做势必造成 try catch 的范围变大。

当然,上述关于指令重排序讨论内容都是基于个人的猜想,犹未可知 try catch 是否影响指令重排序;本文重点讨论的也只是单线程环境下的 try catch 使用影响性能。

四、测试代码

  • 循环次数为100W ,循环内10次预算[给编译器优化预留优化的可能,这些指令可能被合并];

  • 每个方法都会到达千万次浮点计算。

  • 同样每个方法外层再循环跑多次,最后取其中的众数更有说服力。

public class ExecuteTryCatch {// 100W private static final int TIMES = 1000000;private static final float STEP_NUM = 1f;private static final float START_NUM = Float.MIN_VALUE;public static void main(String[] args){int times = 50;ExecuteTryCatch executeTryCatch = new ExecuteTryCatch();// 每个方法执行 50 次while (--times >= 0){System.out.println("times=".concat(String.valueOf(times)));executeTryCatch.executeMillionsEveryTryWithFinally();executeTryCatch.executeMillionsEveryTry();executeTryCatch.executeMillionsOneTry();executeTryCatch.executeMillionsNoneTry();executeTryCatch.executeMillionsTestReOrder();}}/*** 千万次浮点运算不使用 try catch* */public void executeMillionsNoneTry(){float num = START_NUM;long start = System.nanoTime();for (int i = 0; i < TIMES; ++i){num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;}long nao = System.nanoTime() - start;long million = nao / 1000000;System.out.println("noneTry   sum:" + num + "  million:" + million + "  nao: " + nao);}/*** 千万次浮点运算最外层使用 try catch* */public void executeMillionsOneTry(){float num = START_NUM;long start = System.nanoTime();try {for (int i = 0; i < TIMES; ++i){num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;}} catch (Exception e){}long nao = System.nanoTime() - start;long million = nao / 1000000;System.out.println("oneTry    sum:" + num + "  million:" + million + "  nao: " + nao);}/*** 千万次浮点运算循环内使用 try catch* */public void executeMillionsEveryTry(){float num = START_NUM;long start = System.nanoTime();for (int i = 0; i < TIMES; ++i){try {num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;} catch (Exception e) {}}long nao = System.nanoTime() - start;long million = nao / 1000000;System.out.println("evertTry  sum:" + num + "  million:" + million + "  nao: " + nao);}/*** 千万次浮点运算循环内使用 try catch,并使用 finally* */public void executeMillionsEveryTryWithFinally(){float num = START_NUM;long start = System.nanoTime();for (int i = 0; i < TIMES; ++i){try {num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;} catch (Exception e) {} finally {num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;}}long nao = System.nanoTime() - start;long million = nao / 1000000;System.out.println("finalTry  sum:" + num + "  million:" + million + "  nao: " + nao);}/*** 千万次浮点运算,循环内使用多个 try catch* */public void executeMillionsTestReOrder(){float num = START_NUM;long start = System.nanoTime();for (int i = 0; i < TIMES; ++i){try {num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;} catch (Exception e) { }try {num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;} catch (Exception e){}try {num = num + STEP_NUM + 1f;num = num + STEP_NUM + 2f;} catch (Exception e) { }try {num = num + STEP_NUM + 3f;num = num + STEP_NUM + 4f;num = num + STEP_NUM + 5f;} catch (Exception e) {}}long nao = System.nanoTime() - start;long million = nao / 1000000;System.out.println("orderTry  sum:" + num + "  million:" + million + "  nao: " + nao);}}

五、解释模式下执行测试

设置如下JVM参数,禁用编译优化

-Xint
-XX:-BackgroundCompilation

95abf8cc612b2f680ec083fe5f4bb59b.png 

结合测试代码发现,即使百万次循环计算,每个循环内都使用了 try catch 也并没用对造成很大的影响。

唯一发现了一个问题,每个循环内都是使用 try catch 且使用多次。发现性能下降,千万次计算差值为:5~7 毫秒;4个 try 那么执行的指令最少4条goto ,前边阐述过,这里造成这个差异的主要原因是 goto 指令占比过大,放大了问题;当我们在几百行代码里使用少量try catch 时,goto所占比重就会很低,测试结果会更趋于合理。

六、编译模式测试

设置如下测试参数,执行10 次即为热点代码

-Xcomp
-XX:CompileThreshold=10
-XX:-UseCounterDecay
-XX:OnStackReplacePercentage=100
-XX:InterpreterProfilePercentage=33

执行结果如下图,难分胜负,波动只在微秒级别,执行速度也快了很多,编译效果拔群啊,甚至连 “解释模式” 运行时多个try catch 导致的,多个goto跳转带来的问题都给顺带优化了;由此也可以得到 try catch 并不会影响即时编译的结论。

cbf4e30cf1705b53bdc64f3f76044581.png 

我们可以再上升到亿级计算,依旧难分胜负,波动在毫秒级。

ab24b3f6c932b08aa35b1cf7d9ffc469.png 

七、结论

trycatch 不会造成巨大的性能影响,换句话说,我们平时写代码最优先考虑的是程序的健壮性,当然大佬们肯定都知道了怎么合理使用try catch了,但是对萌新来说,你如果不确定,那么你可以使用 try catch;

在未发生异常时,给代码外部包上 try catch,并不会造成影响。

举个栗子吧,我的代码中使用了:URLDecoder.decode,所以必须得捕获异常。

private int getThenAddNoJudge(JSONObject json, String key){if (Objects.isNull(json))throw new IllegalArgumentException("参数异常");int num;try {// 不校验 key 是否未空值,直接调用 toString 每次触发空指针异常并被捕获num = 100 + Integer.parseInt(URLDecoder.decode(json.get(key).toString(), "UTF-8"));} catch (Exception e){num = 100;}return num;}private int getThenAddWithJudge(JSONObject json, String key){if (Objects.isNull(json))throw new IllegalArgumentException("参数异常");int num;try {// 校验 key 是否未空值num = 100 + Integer.parseInt(URLDecoder.decode(Objects.toString(json.get(key), "0"), "UTF-8"));} catch (Exception e){num = 100;}return num;}public static void main(String[] args){int times = 1000000;// 百万次long nao1 = System.nanoTime();ExecuteTryCatch executeTryCatch = new ExecuteTryCatch();for (int i = 0; i < times; i++){executeTryCatch.getThenAddWithJudge(new JSONObject(), "anyKey");}long end1 = System.nanoTime();System.out.println("未抛出异常耗时:millions=" + (end1 - nao1) / 1000000 + "毫秒  nao=" + (end1 - nao1) + "微秒");long nao2 = System.nanoTime();for (int i = 0; i < times; i++){executeTryCatch.getThenAddNoJudge(new JSONObject(), "anyKey");}long end2 = System.nanoTime();System.out.println("每次必抛出异常:millions=" + (end2 - nao2) / 1000000 + "毫秒  nao=" + (end2 - nao2) + "微秒");}

调用方法百万次,执行结果如下:

c70b02752d6c700c5cf67863edbb45b7.png 

经过这个例子,我想你知道你该如何 编写你的代码了吧?可怕的不是 try catch 而是 搬砖业务不熟练啊。

原文:
blog.csdn.net/bokerr/article/details/122655795

 

精彩推荐

1.直接拿去赚钱的 ChatGPT 开源项目...
2.写了个工具,CRUD 开发效率直接提升100倍!生产力拉满...
3.公司入职一个阿里大佬,把SpringBoot项目启动从420秒优化到了40秒!
4.撸了一个SpringBoot+Vue 实现网页版人脸登录、人脸识别,逼格很高!!!
5.Spring Security 保姆级教程!40000字!
6.阿里版ChatGPT已进入测试,中文聊天截图曝光!
7.HTTPS 终于搞懂了 !
8.ES+Redis+MySQL,这个高可用架构设计太顶了!

87fdf61265389fa5cdd0fd26c2f4ae2d.png

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

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

相关文章

chatgpt赋能python:Python处理照片-提高照片处理效率的神器

Python 处理照片 - 提高照片处理效率的神器 对于任何一个专业摄影师或是业余爱好者而言&#xff0c;照片的拍摄技巧虽然至关重要&#xff0c;但是照片的后期处理过程也是不能忽略的&#xff0c;尤其是对于大量照片的处理来说&#xff0c;这中间会花费大量的时间和精力。在这个…

FusionAI - 好用的 AI 写作伴侣 | 生成增强的 ChatGPT 提示,仅需几秒钟即可提升写作水平

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 Your Al writing companion. Generate enhanced GPT prompts and elevate your writing in seconds. FusionAI 地址&#xff1a;http://www.fusionai.…

OpenGL渲染视频步骤--面试用

一 创建一个显卡可执行程序 有两种着色器Shader&#xff1a;顶点着色器、片元着色器。用的是GLSL语言&#xff0c;运行在显卡上的语言。 创建着色器&#xff0c;编译着色器。CreateShader、CompileShader。 创建程序&#xff0c;附加着色器&#xff0c;连接程序&#xff0c;…

解決Unity中使用AVPro Video切换视频时闪现插件Logo

最近在使用unity 3D 插件AVProVideo播放视频&#xff0c;切换视频的时候会在切换间隔闪现一下插件的Logo&#xff0c;摸索之后找到了解决方法&#xff0c;因此发文介绍一下怎么解决。 代码中使用的是以下方法进行切换 m_MediaPlay.OpenMedia(MediaPathType.RelativeToStreaming…

Axure制作播放器原型图-OpenGL FFmpeg QT Rtmp H264 视频监控 mp4播放

要做一个集成了&#xff1a; 1.视频监控 视频播放云台控制 2.图片浏览yuv jpg bmp 图片处理 锐化 模糊 二值化 3.音频播放 pcm aac 音频分析 处理 4.视频文件播放 视频文件格式分析h264-annexb avi flv mp4 5.流媒体播放 hls webrtc rtsp rtmp 6.视频分析 处理--人脸识别…

【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv

通过Qt opengl不是为了3D绘制&#xff0c;而是为了将视频绘制起来 使用opengl 可以极大降低yuv转rgb的转换开销 使用Opengl需要考虑三大问题&#xff1a; 1、QOpenGLWidget&#xff08;与界面如何交互&#xff09; 1、为什么用QT的opengl 简单&#xff0c;界面可以自动叠加 v…

【OpenGL】读取视频并渲染

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍读取视频并渲染。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#…

unity rtsp 视频渲染(一)

unity unity 可以说是一个不错的工具&#xff0c;建立三维的场景非常方便&#xff0c;下面我们建立一个三维的场景&#xff0c;并且在三维的场景中和场景外分别建立系统去播放视频。所谓场景内就是在三维中播放视频&#xff0c;场景外就是在三维场景前表面的二维平面中播放视频…

Unity 视频渲染插件AVPro Movie Capture 简易教程

随着Unity 的 功能日益强大&#xff0c;Unity5的发布使的Unity的图形渲染能力达到了一个新的层次&#xff0c;全局光照的加入&#xff0c;各种新特性的加入&#xff0c;使视频的实时渲染不再是天方夜谈&#xff0c;Unity5发布时的演示视频《Adam》&#xff0c;画质惊人。Unity在…

最新 |《未来简史》作者赫拉利 演讲:AI不需要意识就可以毁灭人类文明 (全文+视频)...

作者&#xff1a;城主 | 编辑&#xff1a;腾讯新闻 郝博阳 编者导语&#xff1a; 最近两个月&#xff0c;自从《暂停AI声明书》发布后&#xff0c;我们看到了诸多AI行业内的专家大佬隔空辩论AI的潜在威胁和治理方法&#xff0c;场面一时无两&#xff0c;基本上把技术路径上AI可…

大模型基础知识 - 语言模型及其演进 公开版

本文为作者内部分享文档&#xff0c;由于不涉敏可以公开&#xff0c;分享本身是课程形式&#xff0c;有什么疑问欢迎在评论区留言。 开场白 人工智能发展到现在&#xff0c;在2个重要领域取得了重大突破&#xff0c;有望达到人类水平&#xff1a; 计算机视觉 &#xff08;Com…

使用ChatGPT帮助快速读书:《Rise of the Robots: Technology and the Threat of a Jobless Future》

有了ChatGPT的帮助&#xff0c;读书也快了&#xff0c;英文版的书也可以快速了解其主要内容&#xff0c;不知道这样囫囵吞枣的阅读有没有其它副作用&#xff0c;先读了几本再说。 《Rise of the Robots: Technology and the Threat of a Jobless Future》这本书我没找到中文版翻…

揭秘ChatGPT爆火的背后真相:学编程已经成为必选项!

这一阵最热门的话题&#xff0c;莫过于人工智能新选手—— ChatGPT&#xff0c;在推出后只用了两个月就积累了1亿用户&#xff01;它的出现在科技圈掀起了一阵“惊涛骇浪”&#xff0c;有人称ChatGPT的意义&#xff0c;堪比当年蒸汽机的出现&#xff0c;它足以爆发新一轮的“工…

【ChatGPT】AI 2.0 时代:拥抱先进的生产力

AI 2.0 时代:拥抱先进的生产力 目录 AI 2.0 时代:拥抱先进的生产力 康波周期是什么? 人类工业革命以来的近现代史 先进生产力的变成了信息与数据 AI科技改变世界

GraphPad Prism 科研绘图(一)

打开GraphPad软件&#xff0c;可以在左侧选择要绘制的图表类型&#xff0c;也可以在左下方直接打开现有的文件 graphpad的工作流程是&#xff0c;首先你需要输入你的数据&#xff0c;也就是你的实验原始数据&#xff0c;叫做Data Table 然后你可以对你的原始数据进行分析&…

科研绘图软件大全

作为材料&#xff0c;化学&#xff0c;环境&#xff0c;物理领域的科研工作者&#xff0c;你是否常为如何表达自己的思想而苦恼? 作为学术论文创造者&#xff0c;你是否为论文中图文单一而叹气? 在这里&#xff0c;推荐给你几款常用科研绘图软件&#xff0c;让你论文从此成为…

【知识图谱】知识图谱的本质是什么?

持续总结更新中 一句话总结知识图谱人工智能从感知到认知什么是知识&#xff1f;什么是先验知识&#xff1f;什么是知识表示&#xff1f;知识图谱的基本组成要素&#xff1f;什么是概念&#xff1f;什么是实体&#xff1f;什么是本体&#xff1f;谈谈本体构建什么是知识图谱的s…

【毕业季】毕业设计避坑指南

文章目录 前言&#x1f34a;缘由毕业季&#xff0c;毕业设计分手季 &#x1f3af;主要目标实现4大重点 &#x1f348;猜你想问如何与狗哥联系进行探讨1.关注公众号【JavaDog程序狗】2.踩踩狗哥博客 &#x1f36f;猜你喜欢文章推荐 正文1.毕业设计如何选题2.毕业设计如何去写3.网…

文心一言“插刀”百度?

在ChatGPT出世半年&#xff0c;爆火将近2月后&#xff0c;中国版AI大模型终于崭露头角。 3月16日&#xff0c;百度于北京总部召开新闻发布会&#xff0c;主题围绕基于文心大模型技术生成式对话产品——文心一言&#xff0c;这也预示着中国首个类ChatGPT产品面世。在其正式推出前…

MSRA王晋东:大模型时代,普通人的科研何去何从

王晋东 投稿量子位 | 公众号 QbitAI 最近&#xff0c;电子工业出版社送了我一本《一本书读懂AIGC&#xff1a;ChatGPT、AI绘画、智能文明与生产力变革》&#xff0c;不禁感叹&#xff1a;现在连写书都这么卷了&#xff01; 要知道&#xff0c;ChatGPT 于去年11月30日刚刚发布、…