我主要来自Python背景,现在我正在学习C和x86-64程序集。以前我通过Cython间接地使用了C,但是现在除了程序集之外,我还在学习C本身。
我的基本问题是,当涉及到优化编译器时,我应该把自己放在一种什么样的心态中。我应该让编译器完成它的工作,但是,一旦我足够精通组装,就开始检查和确认程序集输出?这就是负责任的C程序员想要编写高性能代码的原因吗?
引发这个问题的原因是我想检查gcc 7.5.0将下面的代码优化为什么。特别是,我运行了objdump,以了解如何在不同级别上对同一索引下的数组进行两次访问。
movaps XMMWORD PTR [rsp+0x10],xmm0
-O3还有一些指令我还没有学到,例如-O2和-O1比较清晰,但我仍然不完全理解-O0级别上的messages[idx]确实被访问了两次< code >H 214f 215我的问题不是何时使用这些级别。我只是问更有经验的程序员,如果这是您所做的,运行具有高度优化的代码,并检查程序集输出以确保一切都如预期的那样?对于那些想真正知道编译器生成的机器代码的人来说,这是一个自然的工作流吗?
我知道下面的例子是一个很小的优化机会,但你是否刚刚了解到某些优化确实发生了,而你不再考虑它们了?关于什么类型的转换和优化可以发生的信息不多,更不用说编译器不会给程序员留下任何便条或消息来理解优化的内容和原因,所以除了在实践中学习之外,我想不出任何其他的方法。谢谢。
#include <stddef.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
size_t len_messages = 9;
int messages[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for(size_t idx=0; idx < len_messages; idx++) {
printf("Accessing here %d and there %d\n", messages[idx], messages[idx]);
}
return 0;
}发布于 2020-09-18 19:55:01
我很少单独看拆卸。大多数情况下,我使用Ghidra对函数进行反编译,以查看优化器的运行情况。你会得到一个更大更好的画面。在更熟悉的语言中,仍然可以看到生成的程序集。
发布于 2020-09-18 16:14:17
,我的基本问题是,当涉及到优化编译器时,我应该把自己放在一种什么样的心态中。我应该让编译器完成它的工作,但是,一旦我足够精通组装,就开始检查和确认程序集输出?
基本上没有。
不同的代码块会以不同的数量影响性能--一段在初始化期间只使用一次的代码不会对性能产生多大影响,而在循环中间频繁执行的一段代码可能会对性能产生极大的影响。优化装配成本、开发人员的时间和可移植性;而这些额外的成本通常不能通过疏忽的代码性能改进来证明,而这些改进并不经常执行。
因此,主要的策略是使用分析器来确定最重要(对于性能而言)代码片段的位置;并且只对这些代码块进行性能改进研究。
然而,“调查性能改进”仍然不一定意味着直接进行组装。您可以考虑改进算法、改进数据结构和缓存局部性、改进并行性(“更多线程!”)等等。
在所有这些之后,您可以查看编译器生成的程序集,看看是否能够找到手动改进/优化程序集的方法。你也可能不会。
您可能仍然不使用汇编语言的原因是不同的CPU是不同的。您可以为一个CPU (无论您的计算机有什么)进行优化,并使软件在其他CPU上显着地慢下来(不管运行您的软件的最终用户有什么);或者您可以依赖可能不存在的特性(例如AVX512)。当然,这也意味着您从分析中得到的结果并不像您想象的那样有用(对于粗略的估计来说已经足够好了,并且永远不能作为适用于所有CPU的精确表示)。
为了解决以下问题,您可能需要多种不同版本的汇编语言,用于不同的CPUs -一个用于“64位Intel with AVX-512",一个用于”64位Intel with AVX2",一个用于“64位英特尔没有任何AVX",另外两个版本用于AMD,因为您发现在AMD上需要更长的一些指令,而其他一些指令在AMD上更快;然后,另一个64位ARM的不同版本集合,然后是PowerPC,然后.
基本上,在装配中进行优化是很少见的。对于“重击”库(例如MPEG解码器、大数库、.)这可能很有意义,对于大型程序中的一些性能关键部分来说,这可能是合理的;但除此之外,您的时间可能还有更重要的事情要做。
https://stackoverflow.com/questions/63956256
复制相似问题