学习如何通过Assembly进行优化[关闭]


21

我是计算机游戏技术专业的二年级学生。我最近完成了我自己的“探路者”的第一个原型(它不使用A *而是几何方法/模式识别,探路者只需要他认为有关的地形知识即可做出决定,因为我想要一个可以实际探索的AI(如果已经知道地形),那么它将很容易以最短的方式行走,因为探路者具有节点的内存。

无论如何,我的问题更笼统:如何开始优化算法/循环/ for_each / etc。使用汇编语言,但欢迎使用一般技巧。我特别在寻找好书,因为要找到与此主题相关的好书真的很困难。有一些像这样的小文章,但仍然不足以优化算法/游戏...

我希望那里有一本现代的好书,我只是找不到...


1
这并不能直接回答您的问题,但是探索性(所谓的自适应)A *已被研究并且具有非常好的性能(这意味着您无需使用ASM对其进行优化)。看看D * Lite
乔纳森·迪金森

Answers:


21

在这里,我将是一个反对的人,他说,学习优化,尤其是装配优化,更重要的是装配调试,永远不会太早。我相信,如果您是一名学生,您会从中获得最大的好处(因为这样您就不会有什么损失(即节省时间/金钱)),而且一切都会有所收获。

如果您从事该行业,但不擅长组装,那就不要。否则,如果您是学生或有时间,我会抽出时间学习反汇编程序,看看是否能找到比编译器更好的解决方案。如果我做不到,谁在乎!我刚刚学习了如何编写以及编译器,当您遇到发行代码中的错误(没有调试符号)并盯着反汇编时,这是一个巨大的好处,因为这是您唯一可以看的东西。

答案

这是我发现的关于优化的最佳资源之一。

http://www.agner.org/optimize/

在咆哮

如果您阅读了主要开发人员的一些文章(例如,进行EASTL的推理和对代码的仔细检查将导致您做出类似的评论,因为GCC很难插入此if语句,它将告诉您大多数人们告诉您,相信编译器并不总是正确的,尤其是在游戏开发中),然后涉足该行业,您会发现优化是日常工作,并且知道汇编输出意味着什么是一大优势。而且,人们似乎并没有意识到(尤其是在stackoverflow上)分析游戏非常困难并且并不总是准确的。

有一个警告。您可以花时间优化某些内容,然后再意识到那是浪费时间。但是你学到了什么?您学会了在类似情况下不要重复相同的错误。

在我看来,SO现在所采取的态度是该声明的一种宗教立场,除非您进行概要分析并且不要担心,否则编译器不会比您更了解。它阻碍了学习。我知道业内专家的薪水非常好(我的意思是非常好的钱),他们在组装过程中四处游玩以优化游戏和调试游戏,因为编译器不擅长或根本无法为您提供帮助,因为不能(与GPU相关的崩溃,无法在调试器中读取所涉及数据的崩溃等)。

如果某个喜欢这样做的人还没有完全意识到这一点,在这里提出问题,却被编译器比你更了解的许多答案而拒绝/关闭该怎么办从来没有成为那些高薪程序员之一?

最后一个想法。如果您尽早开始这样做,您会发现很快您将开始编写性能最差的代码,因为编译器以相同的方式或以最佳方式对其进行了优化,因此性能没有任何改善,因为现在编译器可以对其进行优化。 。无论哪种情况,它都已成为习惯,并且您以这种方式编写代码的速度不会比以前慢。有两个示例(还有更多示例):

  1. 除非您确实想要后增量,否则请先增量
  2. 使用恒定的局部大小变量而不是在循环内的容器上调用size()来为容器编写循环。

编辑:在行业中又8年后更新。学习组装。了解优化器如何工作以及它们生成的程序集(CompilerExplorer是实现此目的的出色工具)。我在Test版本(用于内部测试的优化版本)中遇到了无数次崩溃,即使使用调试符号也无法依赖调试器。编译器已经优化了太多东西,而程序集是您从崩溃转储中查找错误的宝贵信息的唯一来源。如果幸运的话,每个构建都需要30到40分钟,并且在构建队列中排在首位-因此,您不能依靠某些传统技术来隔离错误。多人游戏会使情况变得更糟。了解程序集以及如何阅读优化的程序集将使您变得更好,最终对团队更有价值。


1
关于优化编译器的好处。它们很棒,但是远非完美,而且与某些人所认为的不同,通常不难找到编译器没有进行的简单优化。
aaaaaaaaaaaaaa

3
应该注意的是,“学习阅读程序集”和“学习优化程序集” 之间是有区别的。两者不是一回事,您的答案与使用汇编实现优化并没有真正的联系。读取汇编是一项有用的技能,因为它可以帮助调试和发现编译器未正确执行操作的地方。但这与实际使用汇编来编写优化的例程非常不同,后者需要对特定CPU的指令调度有深入的了解。这也是您未涵盖的内容。
Nicol Bolas

1
另外,“我刚刚学习了如何编写以及编译器”不,您没有。您了解了如何为一个特定的CPU编译一个特定的例程。学习如何实现优化的汇编例程不仅仅需要查看编译器如何编译一个例程。您必须了解为什么编译器为了重现特定的C ++代码而选择了这些操作码。这需要对CPU的深入了解,指令调度等。概括地说,这需要多年的经验。您仅通过解码几个例程就不会得到它。
Nicol Bolas

7
因此,-1表示A:实际上并未回答有关如何编写程序集优化例程的问题。B:错误地表达了学习如何在编写汇编优化的例程时击败编译器是多么容易。C:鼓励程序员算法级优化之前先考虑汇编级优化。即使是那些高薪的“行业专家”也会告诉您,那是把车推到了前面。
Nicol Bolas

2
@Samaursa:没有人说过人们不应该“了解反汇编以及如何优化代码”。这不是宗教辩论;这是一个简单的事实。人们花了几个世纪的时间来手动优化某些例程,才发现这对整体性能没有任何意义。学习如何优化算法是一项非常有价值的技能。学习如何阅读汇编是半有价值的技能。学习如何编写汇编例程是一种很少使用的技能。如今,最佳的优化来自更好的缓存利用率,而不是手工组装。
Nicol Bolas

22

您会得到的第一个提示是-不要。

现代编译器实际上确实非常擅长优化代码,并且比起您可能编写的任何自卷式汇编语言,它更有可能做得更好。

例外是在您确定编译器在优化方面做得不好的任何特定情况,因此这是第二个技巧。这里没有通用的准则,您需要了解自己的代码,了解代码的作用,能够直接对其进行反汇编,并能够绝对确定编译器是否做得不好。

即使在这种情况下,您仍然可能不想这样做。您需要确定不会为您带来任何持续的维护开销。您可能希望在6个月的时间内重新使用此代码并对其进行部分修改,或者您可能会发现一个极其细微的错误,而该错误将很难在汇编语言版本中修复。即使您认为自己已经解决了所有错误,但一旦您的程序发布到公共错误中,您甚至都不会想到会发生的错误对您来说将成为现实。这真是令人大开眼界(和谦卑的经历)。

即使您乐于接受,您仍可能会发现绝对没有可衡量的性能改进,因为您的主要瓶颈可能在程序中完全不同。这样我又回到了第一位。别。


15

通常,实体优化不依赖于使用Assembly或对高级语言中的代码进行微优化。如果您阅读了很多研究论文(如我所做的那样-或尝试这样做!),您会发现通常对算法所做的改进是在更宽泛的概念,“定性”水平上进行的,而不是在更“定量”的水平上进行的微优化水平。我要强调的是,从这种角度看算法或对现有解决方案进行矢量化/并行化,更有可能发现数量级增益。

话虽如此,我最近还是碰巧遇到了这个问题,这可能是学习x86 ASM专门针对游戏开发人员的好方法。


附录

我有两个消息来源:

此外,阅读研究论文是跟随智者的思想过程的绝妙方式,因为他们优化了算法以提高性能。最常见的收获是:

  • 减少使用最昂贵的操作(主要是div,SQRT,trig ops和有条件的操作);
  • 通过使用更有效的数据结构,内存对齐和减少条件来提高缓存性能;
  • 在可接受的范围内降低输出质量以提高性能;
  • 向量化(SIMD);
  • 并行化(线程,包括将任务移交给GPU);
  • 当然(越来越少)是手工编码的程序集。当然,首先要检查C / C ++程序集,以查看编译器在何处做出非最佳选择。您可以在80年代和90年代的IME的较早论文中找到更多此类内容。

阅读研究还可以使您处于行业的最前沿,而不必等待这些知识渗透到整个行业。


您在谈论算法优化,但没有提供任何信息,如果我们按照您的建议进行研究,那么您能否给出一些指导?
Skeith

实际上,我确实提到过;您需要研究算法,了解计算机科学家在质量上提高性能的目的。沉浸在足够的时间中,随着时间的流逝,您开始以类似的方式思考。相对于花费数年的时间(我最近在ASM论坛上看到了这一点),掌握渐进式的努力可以节省大量的时间,例如,x86体系结构。追逐大游戏:学会将问题缩小到根本,然后决定什么是多余的以便进行优化。请参阅上面的参考书。
工程师

@NickWiggill您通常的研究论文来源是什么?
kizzx2 2014年

3

我认为可能为时过早。

无论如何,重要的是要了解编译器本身不会产生比汇编程序慢的代码,而仅仅通过编写与编译器相同的汇编代码就不会获得任何性能。

首先,至少要专注于无装配优化。伊戈尔·奥斯特洛夫斯基(Igor Ostrovsky)的一些好文章展示了一些基本知识:http : //igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/

请注意,分支错误预测和高速缓存未命中是您主要要优化的目标,即使您必须通过执行一些额外的算术运算来付出代价,通常也值得避免不可预测的分支或从过多的内存中随机读取。

当然,最重要的是,首先要优化算法。快速算法的慢速执行几乎总是比慢速算法的快速执行更快。


2

这本书非常适合教科书。但是它并不专门针对优化。 x86处理器的汇编语言,第六版

它更多地是关于使用MASM教授组装的基础知识。然后,在本书结尾处,介绍了如何使用c ++内联汇编并将其集成到更大的程序中。

我将其放在此处是因为在学习如何使用汇编优化程序之前先了解汇编的基础知识是有意义的。

我喜欢这本书,因为Irvine教您如何使用编写masm程序所需的工具。他专门研究如何使用IDE(Visual Studio C ++)和调试器。每章都有一些专门解决问题的视频。其中一些信息可在列出的网站上免费获得。


1
“在学习如何使用汇编优化程序之前,有必要先学习汇编的基础知识”-很好的建议。
Maximus Minimus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.