HNU 编译系统 作业1

题目1

请从编译功能的角度简要说明 JDK  JRE 的主要区别

· 如果我们只有一个.java 源文件,要运行该程序,最少需要安装的是 JDK 还是 JRE?请说明理由;

· 如果我们只有一个已经编译好的 .class 字节码文件,最少需要安装的是 JDK 还是 JRE?请说明理由。

· 结合上述问题与前置课程知识,思考C++/Golang/Java三种语言在编译开销与运行性能上的取舍。

(1)从编译功能的角度来看,JDK与JRE的主要区别在于:

JDK包含 JRE + 编译器 javac + 调试工具等,既能编译源代码,也能运行字节码。

JRE只包含运行环境(JVM + 核心类库),只能运行字节码,不能编译源代码。

(2)如果我们只有一个.java 源文件,则需要先编译为 .class字节码文件才能运行。编译在JDK中才有,JRE没有,因此最少需要安装JDK。

(3)如果我们只有一个已经编译好的 .class 字节码文件,则无需编译可直接运行,而JRE可以运行字节码,因此最少需要安装JRE。

(4)C++/Golang/Java三种语言在编译开销与运行性能上的取舍

C++编译为本地机器码,编译时间较长,生成的可执行文件大且依赖平台。

优点:启动快,运行性能极高。

缺点:跨平台性差,开发周期中频繁修改→重新编译→耗时大。

Golang编译为本地可执行文件,但编译器设计追求快速。

优点:编译快、部署方便(单一可执行文件),运行性能接近 C++。

缺点:相比 Java 缺少成熟的虚拟机级优化(如 JIT),长时间运行性能优化略逊。

Java先编译为 .class 字节码,再由 JVM 解释/即时编译(JIT) 运行。

优点:跨平台性强(一次编译,到处运行),JIT 能在运行期优化热点代码,长期性能可接近 C++。

缺点:首次运行时需要类加载 + JIT,启动速度较慢,编译开销分布在运行期。

综合取舍:

C++:编译慢、运行快 → 适合性能极限要求(如游戏引擎、系统软件)。

Go:编译快、运行快 → 适合服务端开发,快速迭代和部署。

Java:编译适中、运行性能动态优化 → 适合跨平台、大型系统、长期运行的服务。

题目2

简要描述深度学习框架(以PyTorch为例)的编译流程,并思考其与传统程序的编译结果优化目标相比,有哪些相同点与不同点?

编译结果

相同点

①都会生成可执行的目标代码(或库),供运行时调用。

②都需要经过中间表示(IR)和优化步骤。

不同点

传统程序:结果是固定的二进制文件/可执行程序,逻辑确定。

深度学习框架:结果可能是动态库 + JIT/AOT 生成的特定算子代码,运行时仍可变化和优化。

优化目标

相同点

①都追求高效执行和资源利用。

②都会使用常见的优化手段(如常量折叠、循环展开、内联)。

不同点

传统程序:优化重点在于指令执行效率、寄存器分配、分支预测、整体运行时间与代码体积。

深度学习框架:优化重点在于并行计算效率、算子融合、内存/显存带宽利用率、硬件特化(CPU/GPU/TPU)。

题目3

给定表达式a = 3 + 4 * 2,仿照教材图1.4画出此表达式的语法树。

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
### 编译原理课程作业示例 #### 表达式求值解析树遍历实现 为了展示编译原理中的表达式求值过程,可以构建一个简单的语法分析器来处理算术表达式的计算。此部分展示了如何通过访问者模式完成对抽象语法树(AST)节点的遍历以及最终的结果计算。 ```cpp // 定义用于表示不同类型的表达式节点类结构体 struct ExprNode { virtual ~ExprNode() {} }; class BinaryOp : public ExprNode { /* ... */ }; class UnaryOp : public ExprNode { /* ... */ }; class NumberLiteral : public ExprNode { /* ... */ }; // 访问者接口定义 class ITreeVisitor { public: virtual void visit(BinaryOp* node) = 0; virtual void visit(UnaryOp* node) = 0; virtual void visit(NumberLiteral* node) = 0; }; // 实现具体的访问者逻辑 class TreeVisitorCalculator final : public ITreeVisitor { private: int evaluateResult; public: explicit TreeVisitorCalculator() : evaluateResult(0) {} // 对于不同的操作符执行相应的运算 void visit(BinaryOp* node) override {/*...*/} void visit(UnaryOp* node) override {/*...*/} void visit(NumberLiteral* node) override { this->evaluateResult += static_cast<NumberLiteral*>(node)->value(); } [[nodiscard]] int getResult() const noexcept { return this->evaluateResult; } }; ``` 在上述代码片段中,`TreeVisitorCalculator` 类实现了 `ITreeVisitor` 接口,并提供了具体的方法去处理每种可能遇到的操作数或操作符类型。当整个 AST 被成功遍历之后,就可以得到表达式的计算结果[^2]。 对于给定的例子 `"4 * 2 - 2 / 4 + 5"` 的评估: ```cpp int main(){ // 构建表达式的根节点 exprRoot (此处省略了实际创建的过程) TreeVisitorCalculator treeVisitor; // 遍历这棵树并计算其值 int result = treeVisitor.visit(exprRoot); std::cout << "Expression evaluation: " << result << std::endl; } ``` 这段程序会输出表达式 `4 * 2 - 2 / 4 + 5` 经过解释后的数值结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值