walt3433
这个作者很懒,什么都没留下…
展开
-
高性能计算——选择优化
简而言之,它涉及在程序的关注点添加计时器和计数器,编译并在真实数据上运行它,然后再次编译,但这次使用测试运行的额外信息。循环展开编译器默认是禁用的,除非循环需要一个在编译时已知的小的常数迭代次数——在这种情况下,它将被替换为一个完全无跳转的,重复的指令序列。那些没有包含在-O3中的优化要么不是严格兼容语言标准的,要么是高度依赖特殊场景的,并且需要程序员提供一些额外的输入来帮助决定使用它们是否有益。它通常会为大型代码库提高10-20%的性能,因此通常包含在对性能至关重要的项目的构建过程中。原创 2024-03-29 09:48:40 · 212 阅读 · 0 评论 -
高性能计算——编译器标志和目标
从编译器获取高性能的第一步是通过超过一百种不同的编译器选项、属性和指令来请求它。原创 2024-03-27 10:14:06 · 185 阅读 · 0 评论 -
高性能计算——编译
学习汇编语言的主要好处不在于用它编写程序,而便于理解在代码编译执行过程中发生的事情及其对性能的影响。确实有会存在一些比较少见的情况,我们需要切换到手写汇编以获得最大性能,但大多数时候,编译器能够自己生成接近最优的代码。当它们做不到这一点时,通常是因为程序员对问题的了解超出了源代码所能推断的范围,但未能将这些额外信息传达给编译器。在这一部分中,我们将讨论如何让编译器准确执行我们想要的操作,并收集有助于进一步优化的有用信息。原创 2024-03-26 10:48:20 · 545 阅读 · 0 评论 -
高性能计算——指令表
在数字电子学中,执行阶段的交错是一个通用概念,不仅应用于主CPU流水线,还应用于独立指令和内存的层面。大多数执行单元都有自己的小流水线,可以在前一个指令之后一到两个周期内接收另一个指令。你可以从CPU的指令表文档中获得特定架构的延迟和吞吐量数据。原创 2024-03-25 10:02:16 · 387 阅读 · 0 评论 -
高性能计算——无分支编程
正如我们在上一篇文章中讨论的,CPU无法有效预测的分支指令,消耗是较大的,因为它们可能导致长时间的流水线停顿,以便在分支预测错误后获取新指令。今天,我们将讨论如何来有效的消除分支指令。原创 2024-03-21 10:15:45 · 221 阅读 · 0 评论 -
高性能计算——分支处理的成本
这个简单的问题可能会引发我们对现代计算机处理器工作方式的深入思考。在探索CPU如何高效执行指令的过程中,我们不仅会发现答案,还会揭示一系列复杂且引人入胜的概念,包括分支预测、指令级并行性以及编译器优化技巧。在这篇文章中,我们将深入探讨这个问题,并了解为什么在某些情况下,对数据进行预处理(如排序)可以显著提高程序的执行速度。这不仅是关于数据组织的问题,更是关于现代处理器如何利用其架构来优化指令执行的故事。原创 2024-03-18 17:21:36 · 527 阅读 · 0 评论 -
高性能计算——流水线的危害
解决危害的唯一方法是进行流水线停顿:在拥塞的原因消失之前停止所有之前步骤的进展。这在流水线中创造了气泡——类似于流体管道中的气泡——一种时间传播的状态,当执行单元空闲且没有有效工作完成时。流水线允许你通过并发执行指令来隐藏指令的延迟,但也创造了一些自身的潜在障碍——特征性地称为流水线危害,即下一条指令不能在下一个时钟周期执行的情况。由于它们对性能有非常不同的影响,我们将以相反的顺序开始,从更严重的问题开始讨论。原创 2024-03-17 21:49:00 · 164 阅读 · 0 评论 -
高性能计算——指令级并行
而又因为指令并不总是以最方便的顺序到达,所以,当可能时,现代CPU可以乱序的执行指令来提高总体利用率并最大化的减少流水线停顿。但现在,我们可以假设CPU维护了一个未来一段距离的待处理指令缓冲区,当指令操作数的值计算出来并且有空闲的执行单元可用时,会立即执行它们。整个操作序列是很长的。即使对于很简单的操作,比如将两个存储在寄存器中的值相加,也需要长达15-20个CPU周期。理想的流水线处理器的CPI应该趋向于一,但如果我们通过复制每个流水线阶段来使每个阶段“更宽”,以便同时处理多于一条指令,实际上可以更低。原创 2024-03-16 10:12:03 · 417 阅读 · 0 评论 -
高性能计算——汇编语言(终章)
这可能由许多原因造成,所有这些原因最终都与机器码在内存中的布局有关,这些原因会以奇怪的方式影响性能,例如移除未使用的代码、交换“if”分支,甚至改变函数声明的顺序都有可能会导致性能的提高或恶化。当其他条件相同时,编译器通常更喜欢较短机器码的指令,因为这样可以在单个32B的获取块中放入更多的指令,同时也会减少二进制文件的大小。指令的存储和获取的内存系统,和数据内存系统大致相同,除了用单独的指令缓存替换掉较低层的缓存(因为我们不希望随机的数据读取将处理它的指令代码挤掉)。),更像是几乎从不发生的异常。原创 2024-03-15 11:13:28 · 271 阅读 · 0 评论 -
高性能计算——汇编语言(四)
与其创建n个条件控制分支,不如创建一个包含所有可能的跳转位置的指针或偏移量的分支表,然后用状态变量索引它,该变量取值在[0,n)范围内。基于switch的代码对编译器来说不总是直接优化的,因此在状态机的上下文中,goto语句通常直接使用。使用虚函数调用时,会从结构体实例中获取该偏移字段,并使用它进行普通的函数调用,利用所有派生类的所有方法和其他字段具有完全相同的偏移这一事实。对于Animal的所有具体实现,编译器填充它们的所有方法(即它们的指令序列),使它们对于所有类都具有完全相同的长度(在。原创 2024-03-14 17:19:41 · 276 阅读 · 0 评论 -
高性能计算——汇编语言(三)
因为现代操作系统实际上不会给你内存页面,直到你读取或写入它们的地址空间,你可以自由指定一个非常大的栈大小,它更像是对可以使用的栈内存的限制,而不是每个程序必须使用的固定数量。如果函数是递归的,通常仍然可以通过重构它使其“无调用”,这在函数是尾递归的情况下是可行的,也就是说,它在进行递归调用后立即返回。这在函数式编程中是非常重要的概念,在函数式编程中没有循环,你只能使用函数。解决这两个问题,可以通过在内存中设置一个专门的区域来解决,在调用函数之前,我们可以在这个位置写下所有我们需要从函数返回时的信息。原创 2024-03-13 18:27:49 · 174 阅读 · 0 评论 -
高性能计算——汇编语言(二)
我们再看一个稍微复杂赢一点的例子这段代码计算一个32位整数数组的总和,就像一个简单的for循环一样。循环的“主体”是 add edx, DWORD PTR [rax]:这条指令是从迭代器rax中加载数据并将其添加到累加器edx中。接下来,我们通过 add rax, 4将迭代器向前移动4字节。然后,发生了一个件稍微复杂的事情。原创 2024-03-12 10:14:30 · 387 阅读 · 0 评论 -
高性能计算——汇编语言(一)
汇编语言,是一种更加人性化的机器语言表示形式,使用了一些助记符代码来表示机器码指令,并使用符号名称来引用寄存器和一些其他的存储位置。汇编语言的结构非常简单,与高级编程语言相比,没有太多的语法构造。[reg];汇编语言是非常简洁的语言,它尽可能的直接反映机器码,几乎达到了1:1的对应关系。事实上,可以使用反汇编将任何编译过的程序转换为其汇编语言形式。需要注意的是,上面两段代码不仅在语法上略有不同。同样都是编译器产生的优化代码,但Arm版本使用了4条指令,而X86版本仅使用了3条。原创 2024-03-08 10:03:37 · 289 阅读 · 0 评论 -
高性能计算——计算机架构
当我自己开始学习如何自己优化程序时,其实犯了一个较大的错误,那就是主要依赖于经验方法。因为不了解计算机的真正工作原理,我会经常靠着经验半随机地交换嵌套循环、重排算法操作、组合分支条件、手动内联函数,以及遵循我从论坛或其他人那里听说的各种性能建议,盲目地希望能有所改进。不幸的是,目前大多数程序员处理性能优化的方式都是这样。太多关于性能优化的文章并不会教你如何定性定量的地计算软件性能。相反,它们只给你一些关于特定实现方法的通用建议。原创 2024-03-07 13:39:18 · 191 阅读 · 0 评论 -
高性能计算——编程语言
如果你正在阅读这篇文章,那么在你的编码经历中,一定有那么一刻,你会开始关心代码的效率。我的这一刻发生在高中时,当时我意识到仅仅制作网站和进行实用编程是无法让你进入大学的,于是我开始踏入计算机奥赛的世界。作为一个天赋还不错的程序员,尤其是当时仅仅是高中生的我,之前竟然从未思考过我写的代码执行起来究竟需要多少时间。意识到这个问题很重要后,我开始计算我代码的操作数量。一秒钟到底完成多杀操作?当时的我对计算机架构知之甚少,完全无法回答这个问题。但是我也不需要详细的答案——我需要的是一个经验法则。原创 2024-03-04 14:32:14 · 713 阅读 · 0 评论 -
高性能计算——现代硬件系统
上世纪60年代的超级计算机们,主要缺点并不是它们运行缓慢——相对而言,它们其实并不慢——而是因为它们体积巨大,使用复杂,并且运行维护费用非常昂贵,只有世界超级大国才能负担得起。它们的规模是导致价格如此昂贵的主要原因:需要非常多的定制化组件,这些组件必须在宏观世界中非常小心地由拥有电气工程高级学位的工程师组装使用,而这个过程无法扩展到大规模生产。事情的转折点是因为微型芯片的发展。它彻底的改变了整个行业,并可能是20世纪最重要的发明。原创 2024-03-03 21:40:18 · 650 阅读 · 0 评论 -
高性能计算——复杂度模型
如果你曾经翻阅过计算机科学的教科书,就会看到通常在开头部分介绍算法复杂度。简单来说,计算复杂度就是计算机在计算过程中执行的基本操作(加法、乘法、读取、写入等)的总次数,有时也会根据操作不同消耗,进行加权。复杂度是一个很早期的概念,在上世纪60年代初被系统的提出,并从那时起就被普遍用来当做设计算法的消耗。这个模型之所以能被迅速采纳,是因为它很好的模拟了当时计算机的工作方式。原创 2024-03-01 15:44:56 · 1087 阅读 · 0 评论 -
高性能计算——概览
这是一系列关于高性能计算的介绍,名为《现代硬件的算法》(原著作者是谢尔盖·斯洛廷(Sergey Slotin)。我会结合自己从业多年的经历将其翻译转述。文章的目标读者群体不仅涵盖高性能计算工程师,算法研究人员,甚至包括刚刚完成算法课程并且希望学习到更多实用方法来让提高程序运行效率的学生们。《计算机程序设计艺术》(The Art of Computer Programming)和《算法导论》()这两本书,毫无疑问都是杰作,对计算机科学课程产生了巨大影响。原创 2024-03-01 15:41:52 · 383 阅读 · 0 评论