详解三大编译器: gcc、llvm 和 clang (icc/icpc/ifort)

1. 详解三大编译器: gcc、llvm 和 clang (icc/icpc/ifort)

clang+llvm 构成一个完整的编译器。题主大概是这个意思。clang 是前端, llvm 是后端, 它们统称为 LLVM。

1.1. 编译器一般构成

传统的编译器通常分为三个部分, 前端 (frontEnd), 优化器 (Optimizer) 和后端 (backEnd). 在编译过程中, 前端主要负责词法和语法分析, 将源代码转化为抽象语法树; 优化器则是在前端的基础上, 对得到的中间代码进行优化, 使代码更加高效; 后端则是将已经优化的中间代码转化为针对各自平台的机器代码。

1.2. GCC

GCC(GNU Compiler Collection, GNU 编译器套装), 是一套由 GNU 开发的编程语言编译器。GCC 原名为 GNU C 语言编译器, 因为它原本只能处理 C 语言。GCC 快速演进, 变得可处理 C++、Fortran、Pascal、Objective-C、Java 以及 Ada 等他语言。

1.3. LLVM

LLVM (Low Level Virtual Machine, 底层虚拟机)) 提供了与编译器相关的支持, 能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。简而言之, 可以作为多种编译器的后台来使用。

苹果公司一直使用 GCC 作为官方的编译器。GCC 作为一款开源的编译器, 一直做得不错, 但 Apple 对编译工具会提出更高的要求。原因主要有以下两点:

其一, 是 Apple 对 Objective-C 语言(包括后来对 C 语言)新增很多特性, 但 GCC 开发者并不买 Apple 的账——不给实现, 因此索性后来两者分成两条分支分别开发, 这也造成 Apple 的编译器版本远落后于 GCC 的官方版本。

其二, GCC 的代码耦合度太高, 很难独立, 而且越是后期的版本, 代码质量越差, 但 Apple 想做的很多功能(比如更好的 IDE 支持), 需要模块化的方式来调用 GCC, 但 GCC 一直不给做。

1.4. 编译器大神 Chris Lattner 横空出世

2000 年, 本科毕业的 Chris Lattner 像中国多数大学生一样, 按部就班地考了 GRE, 最终前往 UIUC(伊利诺伊大学厄巴纳香槟分校), 开始了艰苦读计算机硕士和博士的生涯。在这阶段, 他不仅周游美国各大景点, 更是翻烂了《Compilers: Principles, Techniques, and Tools》, 成了 GPA 满分 (4.0) 牛人, 并不断地研究探索关于编译器的未知领域, 发表了一篇又一篇的论文。他在硕士毕业论文里提出了一套完整的在编译时、链接时、运行时甚至是在闲置时优化程序的编译思想, 直接奠定了 LLVM 的基础。LLVM 在他念博士时更加成熟, 使用 GCC 作为前端来对用户程序进行语义分析产生 IF(Intermidiate Format), 然后 LLVM 使用分析结果完成代码优化和生成。这项研究让他在 2005 年毕业时就成为了业界小有名气的编译器专家, 他也因此早早地被 Apple 盯上, 最终成为其编译器项目的骨干。

刚进入 Apple, Chris Lattner 就大展身手: 首先在 OpenGL 小组做代码优化, 把 LLVM 运行时的编译架在 OpenGL 栈上, 这样 OpenGL 栈能够产出更高效率的图形代码。如果显卡足够高级, 这些代码会直接扔入 GPU 执行。但对于一些不支持全部 OpenGL 特性的显卡(比如当时的 Intel GMA 卡), LLVM 则能够把这些指令优化成高效的 CPU 指令, 使程序依然能够正常运行。这个强大的 OpenGL 实现被用在了后来发布的 Mac OS X 10.5 上。同时, LLVM 的链接优化被直接加入到 Apple 的代码链接器上, 而 LLVM-GCC 也被同步到使用 GCC4.0 代码。

1.5. LLVM2.0 - Clang

Apple 吸收 Chris Lattner 的目的要比改进 GCC 代码更具野心 – Apple 打算从零开始写 C、C++、Objective-C 语言的前端 Clang, 完全替代掉 GCC。

Clang 是 LLVM 的前端, 可以用来编译 C, C++, ObjectiveC 等语言。Clang 则是以 LLVM 为后端的一款高效易用, 并且与 IDE 结合很好的编译前端。

Clang 只支持 C, C++ 和 Objective-C 三种语言。2007 年开始开发, C 编译器最早完成, 而由于 Objective-C 只是 C 语言的一个简单扩展, 相对简单, 很多情况下甚至可以等价地改写为 C 语言对 Objective-C 运行库的函数调用, 因此在 2009 年时, 已经完全可以用于生产环境。C++ 在后来也得到了支持。

1.6. GCC 和 Clang 对比

1.6.1. Clang 特性

速度快: 通过编译 OS X 上几乎包含了所有 C 头文件的 carbon.h 的测试, 包括预处理 (Preprocess), 语法 (lex), 解析 (parse), 语义分析 (Semantic Analysis), 抽象语法树生成 (Abstract Syntax Tree) 的时间, Clang 比 GCC 快 2 倍多。

内存占用小: Clang 内存占用是源码的 130%, Apple GCC 则超过 10 倍。

诊断信息可读性强: 其中错误的语法不但有源码提示, 还会在错误的调用和相关上下文的下方有~~~~~和^的提示, 相比之下 GCC 的提示很天书。

兼容性好: Clang 从一开始就被设计为一个 API, 允许它被源代码分析工具和 IDE 集成。GCC 被构建成一个单一的静态编译器, 这使得它非常难以被作为 API 并集成到其他工具中。

Clang 有静态分析, GCC 没有。

Clang 使用 BSD 许可证, GCC 使用 GPL 许可证。

1.6.2. GCC 优势

支持 JAVA/ADA/FORTRAN

GCC 支持更多平台

GCC 更流行, 广泛使用, 支持完备

GCC 基于 C, 不需要 C++ 编译器即可编译

1.7. llvm 与 gcc

  1. llvm 是一个编译器, 也是一个编译器架构, 是一系列编译工具, 也是一个编译器工具链, 开源 C++11 实现。
  2. gcc 相对于 clang 的优势:
  • gcc 支持更过语言前端, 如 Java, Ada, FORTRAN, Go 等
  • gcc 支持更多地 CPU 目标架构
  • gcc 支持更多语言扩展, 比如 gcc 可以完美地支持 Linux Kernel 的编译, 而 clang 会遇到一些扩展的问题
  1. clang 相对于 gcc 的优势:
  • clang 的 AST 和整个设计是人类可以阅读的
  • clang 的模块化和复用性更好, clang 从初衷上就是以 API 的形式设计, 可以被源码分析工具, 重构, IDE 等复用。而 gcc 在设计时就没有这个考量, gcc 被设计为"一大团"静态编译器, 总之就是可以实现功能, 并且功能很强大(上面优点), 但其中内容基本不可知, gcc 的设计就没有考虑复用性
  • clang 可以序列化其生成的 AST 到硬盘上并且被其他程序读入, 这对整个程序的分析很有用, gcc 不支持这项功能
  • llvm 的优化在全程都会进行, 包括编译时优化, 链接时优化, 装载时优化, 运行时优化, 以及闲时优化。可参考: LLVM 全时优化。
  • clang 更快且用更少内存
  • clang 在设计时就考虑提供更加清晰准确地诊断信息(error 和 warning 信息)
  • gcc 的许可证是 GPL, clang 是 BSD

gcc 就像橡皮泥, 能够塑造出任何优秀的作品, 但基本没有复用性可言; llvm 就像乐高积木, 虽然更加粗犷, 但是模块化和复用性极佳。

那么, llvm 框架模块化的优势究竟是怎样在其他领域为其他应用带来巨大的便利的呢? 以下整理自 知乎@蓝色 大佬的一个回答(LLVM 相比于 GCC, 有哪些技术上的优势? ):

  • 统一的 IR 与模块化。你可以很轻易的抽取 LLVM 的组件(以库的形式)出来用于其它领域, 如抽取 LLVM JIT 用于 MapD 这样的 GPU 数据库, 或者抽取 LLVM 的整个后端(优化与 CodeGen)用于 TVM 这样的深度学习推理框架。这样带来的好处就是 LLVM 不再仅仅是用于给 Clang 等编译器前端提供服务的编译器后端, 而是可以为需要 JIT / CodeGen 功能的所有领域服务, 比如提到的 GPU 数据库、深度学习推理框架, 还包括安全、区块链等应用领域。而这一切 LLVM 所需要的仅仅是一个统一的中间表示格式: LLVM IR。所以, 现在比较常见的开发模式变为:

各种各样的应用(DSL、GPU 数据库、TVM、安全、区块链等)----> 生成 LLVM IR ----> LLVM 的优化 ----> LLVM Code Gen ----> 目标代码(ARM、x86、Hexagon、NVPTX、AMDGPU、WebAssembly…)。 这在 LLVM 出现之前, 基本上是做不到的事情, 不仅 GCC, 包括其它编译器都可以理解为"一坨", 根本抽不出来。

  • 快速的可定制化。这一点架设在第一点的基础上, 由于在 LLVM 中编写优化 Pass 非常方便, 所以针对各种各样的应用, 可以变为:

    • 各种各样的应用(DSL、GPU 数据库、TVM、安全、区块链等)----> 生成 LLVM IR ----> 编写针对自己特定应用的优化 Pass ----> LLVM 的优化 ----> LLVM Code Gen ----> 目标代码(ARM、x86、Hexagon、NVPTX、AMDGPU、WebAssembly…)
    • 也包括: 各种各样的应用(DSL、GPU 数据库、TVM、安全、区块链等)----> 生成 LLVM IR ----> 编写针对自己特定应用的优化 Pass ----> LLVM 的优化 ----> LLVM Code Gen ----> 目标代码(ARM、x86、Hexagon、NVPTX、AMDGPU、WebAssembly, 自己的后端(如 AI 芯片)…)
  • 使用现代 C++代码编写并有良好的代码组织。LLVM 使用 C++11 编写, 代码十分清晰与规范, 对于阅读并且改写非常的方便。同时, 其代码组织非常的好, 每一个地方放什么东西, 一目了然。而我也与一些同僚聊过, 大家也都觉得 LLVM 是更好读、更好改的代码。

  • License 优势。这一点是优势, 但是是否是技术优势, 看如何理解, 但是这一点确实帮助了 LLVM 很多, 让其快速被各大公司采用并不断回馈它。

1.8. GCC、LLVM 和 Clang 如何选择?

目前不推荐使用老的 GCC 4.2, 因为苹果不会维持它了, 而且 LLVM-GCC 看起来会更好。在项目中途改编译选项可是一个大变动, 需要慎重。

对新的项目而言, LLVM-GCC 看起來应该是个安全的选择, 苹果公司认为它够稳定够成熟, 所以才把它当做 Xcode 4 的预设选项。而且, 既然选项使用的是 GCC parser, 向后兼容性应该没问题。

LLVM-GCC 是个安全的选项, 但并不是指 Clang/LLVM 比较不安全, 只是成熟度还沒那么高效了。

1.9. 总结 - 再探 LLVM

回顾 GCC 的历史, 虽然它取得了巨大的成功, 但开发 GCC 的初衷是提供一款免费的开源编译器, 仅此而已。可后来随着 GCC 支持了越来越多的语言, GCC 架构的问题也逐渐暴露出来。但 GCC 到底有什么问题呢?

LLVM 的优点也正是 GCC 的缺点。传统编译器工作的时候前端负责解析源代码, 检查语法错误, 并将其翻译为抽象的语法树 (Abstract Syntax Tree)。优化器对这一中间代码进行优化, 试图使代码更高效。后端则负责将优化器优化后的中间代码转换为目标机器的代码, 这一过程后端会最大化的利用目标机器的特殊指令, 以提高代码的性能。事实上, 不光静态语言如此, 动态语言也符合上面这个模型, 例如 Java。JVM 也利用上面这个模型, 将 Java 代码翻译为 Java bytecode。这一模型的好处是, 当我们要支持多种语言时, 只需要添加多个前端就可以了。当需要支持多种目标机器时, 只需要添加多个后端就可以了。对于中间的优化器, 我们可以使用通用的中间代码。这种三段式的结构还有一个好处, 开发前端的人只需要知道如何将源代码转换为优化器能够理解的中间代码就可以了, 他不需要知道优化器的工作原理, 也不需要了解目标机器的知识。这大大降低了编译器的开发难度, 使更多的开发人员可以参与进来。虽然这种三段式的编译器有很多优点, 并且被写到了教科书上, 但是在实际中这一结构却从来没有被完美实现过。做的比较好的应该属 Java 和 .NET 虚拟机。虚拟机可以将目标语言翻译为 bytecode, 所以理论上讲我们可以将任何语言翻译为 bytecode, 然后输入虚拟机中运行。但是这一动态语言的模型并不太适合 C 语言, 所以硬将 C 语言翻译为 bytecode 并实现垃圾回收机制的效率是非常低的。GCC 也将三段式做的比较好, 并且实现了很多前端, 支持了很多语言。但是上述这些编译器的致命缺陷是, 他们是一个完整的可执行文件, 没有给其它语言的开发者提供代码重用的接口。即使 GCC 是开源的, 但是源代码重用的难度也比较大。

LLVM 最初的定位是比较底层的虚拟机。它的出现正是为了解决编译器代码重用的问题, LLVM 一上来就站在比较高的角度, 制定了 LLVM IR 这一中间代码表示语言。LLVM IR 充分考虑了各种应用场景, 例如在 IDE 中调用 LLVM 进行实时的代码语法检查, 对静态语言、动态语言的编译、优化等。从上面这个图中我们发现 LLVM 与 GCC 在三段式架构上并没有本质区别。LLVM 与其它编译器最大的差别是, 它不仅仅是 Compiler Collection, 也是 Libraries Collection。举个例子, 假如说我要写一个 X 语言的优化器, 我自己实现了 PassX 算法, 用以处理 X 语言与其它语言差别最大的地方。而 LLVM 优化器提供的 PassA 和 PassB 算法则提供了 X 语言与其它语言共性的优化算法。那么我可以选择 X 优化器在链接的时候把 LLVM 提供的算法链接进来。LLVM 不仅仅是编译器, 也是一个 SDK。Apple LLVM compiler 4.2 是一个真正的 LLVM 编译器, 前端使用的是 Clang, 基于最新的 LLVM 3.2 编译的。LLVM GCC 4.2 编译器的核心仍然是 LLVM, 但是前端使用的是 GCC 4.2 编译器。从 LLVM 的下载页面可以看出, LLVM 从 1.0 到 2.5 使用的都是 GCC 作为前端, 直到 2.6 开始才提供了 Clang 前端。

如果你下载 LLVM 的代码, 那么它就是一个 IR 到 ARM/机器码的编译器。比如 bin/opt 就是对 IR 的优化器, bin/llc 就是 IR->ASM 的翻译, bin/llvm-mc 就是汇编器。如果你再从 http://llvm.org 下载 Clang, 那么就有了 C->IR 的翻译以及完整的编译器 Driver。GDB 是 GNU 的调试器。只要编译器支持 DWARF 格式, 就可以用 GDB 调试。

1.10. icc icpc ifort

  • Intel 编译器编译 C 和 C++源程序的编译命令分别为 iccicpc;
  • 编译 Fortran 源程序的命令为 ifort

icpc 命令使用与 icc 命令相同的编译器选项, 利用 icpc 编译时将后缀为 .c.i 的文件看作为 C++文件; 而利用 icc 编译时将后缀为 .c.i 的文件则看作为 C 文件。用 icpc 编译时, 总会链接 C++ 库; 而用 icc 编译时, 只有在编译命令行中包含 C++源文件时才链接 C++ 库。

在 Intel 数学库 (Intelmath) 中的许多函数针对 Intel 微处理器相比针对非 Intel 微处理器做了非常大的优化处理。

1.10.1. 什么是 ICC/GCC?

CPU 这东西, 大家除了关注工艺、主频、核心数量等规格信息之外, 更在意的应该就是性能表现了。反应 CPU 性能的测试可谓是相当多样, 但要说起最权威的, 那就不得不提 SPEC CPU 测试了。

SPEC 的全称是 Standard Performance Evaluation Corporation, 翻译过来是标准性能评估组织, 它是一个全球性的第三方非营利性组织, 由计算机厂商、系统集成商、大学、研究机构、咨询等多家公司组成, 目标是建立、维护一套用于评估计算机系统的标准。

在 CPU 性能测试上, SPEC CPU 2006 是 SPEC 组织推出的最新版的软件(上一个版本 SPEC CPU 2000 已经基本没有人用了), 同时也是最受行业认可的测试软件。SPEC CPU 2006 包括了 CINT2006 和 CFP2006 两个子项目, 前者用于测量和对比整数性能, 而后者则用于测量和对比浮点性能。在各种处理器的 SPEC CPU 2006 测试结果上, 我们往往会看到 ICC 或是 GCC 的字样, 那么 ICC 和 GCC 又分别代表什么呢?

什么是 ICC/GCC?

ICC: 全称 Intel C++ Compiler, 是 Intel 开发的 C/C++/Fortran 编译器套装, 适用于 Linux、Microsoft 和 Mac OS X 操作系统, 没有非 IA 指令集版本(就是说仅供 x86 架构 CPU 使用)。ICC 广泛应用于高性能计算、分布式计算等商业计算领域, 其向量化和并行化性能是业界的标杆, 能够充分发挥现代处理器的特性。

Parallel Studio XE 和 System Studio

▲ICC 编译器套装提供两个版本, 针对高性能计算机测试采用前者, 而后者面向嵌入式及移动设备。

GCC: 全称 GNU Compiler Collection, GNU 编译器套装, 是广泛应用的 Linux 系统的默认编译器(特别是用于编译 Linux 内核)。GCC 能够支持多种架构的处理器, 跨平台特性相对出色。不过, GNU 组织要求全部的代码由自己完成(防止版权问题), 所以 GCC 虽然有广泛的硬件支持, 但是在各硬件平台上却并不是性能最优的编译器。

▲GCC 官方 LOGO

到底啥是编译器?

所谓编译器, 就是将"一种语言(通常为高级语言)"翻译为"另一种语言(通常为低级语言→汇编语言)"的程序。它的主要工作流程:
高级语言源代码→预处理器→编译器→汇编语言, 汇编语言再经过汇编器→目标文件→链接器生成可执行程序。
在这个流程中, 高级语言指的就是源代码, 如 Pascal、C、C++、fortran、Java 等, 而目标文件指的是包含 CPU 可以执行的二进制指令的集合。也就是说, 编译器起到的作用就是将程序源代码"翻译"成汇编语言, 既然是"翻译"工作, 往往就有 Good 和 Better 的区别, 而从上面的介绍我们能够看出, 不同的操作系统, 能够使用的编译器是不同的, 那这个编译效率自然也就存在差异。
同时, CPU 也是区分不同架构的, 比如 x86、MIPS、ARM、Power 等等, 不同架构的 CPU 往往运行不同的操作系统, 如 x86 架构 CPU 可以运行 Windows、Linux(Android) 和 Mac OS X, 而 MIPS 等其他架构 CPU 往往只能运行基于 Linux 开发的操作系统。
所以, 不同架构的 CPU, 根据适合的操作系统, 在 SPEC CPU 测试过程中编译器的选择上是不一定是唯一的, 而选择哪一种编译器, 站在 CPU 研发者的角度上, 无疑会选择能让 CPU 性能发挥到最大的编译器。

通过前面对 ICC 和 GCC 的解读, 不难看出两者的区别。ICC 和 GCC 都可以运行在 Windows 和 Linux 下, Intel 是 x86 架构 CPU 的老大, 配合 x86 架构 CPU 开发了 ICC, 能够最大程度的发挥出 x86 架构 CPU 的真实性能。GCC 能够配合更多种类架构的 CPU 加以使用, 适用平台更广, 但从 CPU 性能发挥的角度上看, 大而广很难和专而精比拼。
但是, 综合 x86 CPU 和 Windows 系统的市场占有率这两个因素来看, 在 CPU 测试过程中, ICC 和 GCC 的采用率又是怎样呢?
第三方商业机构更多采用 ICC, GCC 寥寥无几
SPEC 官网 (http://spec.org/) 上公布着大量的专业机构测试结果供大家研究分析, 笔者选定了全部的整数单笔者选定了全部的整数单任务测试结果进行分析, 通过爬虫抓取了约 8600 个测试结果, 并对测试中使用的编译器进行了数据统计:

结果是使用 ICC 编译器的测试结果高达 95%, 而 GCC 不足 0.1%。这些测试结果基本都是独立的第三方商业机构的测试结果, 具有很高的参考价值。数据显示, ICC 编译器的使用在 SPEC CPU 2006 测试中具有压倒性的优势, 而 GCC 则几乎没有商业机构使用。
上述统计还反映了一个事实, 就是 Intel 和 AMD 的 x86 架构处理器在桌面及服务器领域的垄断性优势。而从其中非 x86 架构 CPU 的测试结果来看, 仅剩的数个测试成绩, Power、Sparc 全部使用的是针对自家指令集优化过的编译器, 而非 GCC, 这也侧面反映了 GCC"大而广"的一些问题。
产生这个现象的原因要从 SPEC CPU 测试成绩产生方法来说起: SPEC 组织使用一台 1997 年的 Ultra Enterprise 2 主机(处理器为 296MHz UltraSPARC II Processor) 作为参考对象, 在其上运行了全部的 SPEC CPU 2006 子测试, 并把每一项的测试结果的用时(中间数)定位系数 1。
实际测试中, 假定被测试的 CPU 运行某项子测试的用时为 A, 而 Ultra Enterprise 2 主机同一项子测试用时为 B, 则用 B/A, 即可得到被测试 CPU 该项子测试的成绩, 而各子测试成绩的几何平均值记为总成绩。
即 SPEC 各子项成绩是相对于 Ultra Enterprise 2 计算出来的 (Ultra Enterprise 2 各项成绩计为 1, 总分也是 1)。
参考机器 (Ultra Enterprise 2 主机)的测试结果也公布在 spec.org 网站上面:
https://www.spec.org/cpu2006/results/res2006q3/cpu2006-20060513-00001.html

从中可以看出的是, 作为参考成绩的测试结果也并没有使用 GCC, 而是 Sparc 自家的编译器。

ICC GCC 哪个更好?

实际上, SPEC CPU 测试的是应用程序的运行时间, 这个是被测机器处理器、缓存、内存、编译器、操作系统等等部分性能的综合体现, 并不是某个编译器或者某个 CPU 的单独测试结果, 而且软硬件平台综合体现的结果, 即按照官方规则正确跑出来的分都是可比的。SPEC CPU 测试结果追求的是程序运行用时越短越好, 测试成绩的优劣固然重要, 但是编译器的真正的用途是"翻译语言", 在同样的硬件平台 (CPU) 下, "翻译"的越快就可以理解为应用启动或进行某种运算的用时更少, 这就是选择编译器的重要性, 也是现代应用优化的方向。

拿 ICC 和 GCC 相比, ICC 是针对 x86 架构 CPU 使用的编译器, ICC 在现代高性能计算领域广泛使用的向量化、并行化能力较强, 而 GCC 作为跨平台性的编译器, 在这方面性能较差, 但是针对某些偏门的 CPU 指令集而言, GCC 是唯一的选择。
ICC、GCC 两者广泛应用于商业环境中、都会被应用于处理器、OS 及编译器开发、测试之中。有些爱好者担心 ICC 过度优化, 结果不准确, 其实这大可不必。SPEC CPU 是有严格的测试标准的, 每一项测试都要求严格和参考结果一致, 任何过度优化导致的程序计算错误都不会被计算在结果之中。实际上, ICC 在多年的高性能计算领域已经证明了自己的可靠性, 而 GCC 在过往版本中, 也会有编译出错、计算结果不正确等现象。

Closed Source 和 Open Source.
▲ICC GCC 区别好比如此, 懂得人自然懂

最后笔者想要强调的是, 硬件平台性能发挥需要合适的编译器来加以配合, 合适的才是最好的, 如果编译器不能合理使用, 那又有何意义呢?

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在构建和编译程序时,为了避免依赖性,通常会使用来自STL(标准模板库)的算法和数据结构。这些算法和数据结构可以包括具有不同分布(如正态分布和均匀分布)的C++11随机数生成器。同时,在构建编译程序时,需要一个编译器,例如GCCClangICC或MSVC的较新版本。这些编译器可以用来将源代码编译成可执行文件。 关于ICC(Intel C++ Compiler),ICC是英特尔公司开发的一款优化编译器。它支持各种优化选项,可以提高程序的性能。其中包括一些与布局和拥塞相关的选项,如create_fp_placement -congestion_driven-timing_driven。 对于数据结构和算法的相关问题,没有提及ICC的具体功能和支持。如果想要了解ICC在数据结构和算法方面的应用,建议查阅相关文档或资料,以获取更详细的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [HarmOsc:使用HMC算法模拟的晶格上的谐振子](https://download.csdn.net/download/weixin_42128270/19728020)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ICC布局规划](https://blog.csdn.net/weixin_39942351/article/details/112039528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云满笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值