gpt4 book ai didi

c - GCC循环展开标志真的有效吗?

转载 作者:太空狗 更新时间:2023-10-29 16:29:20 24 4
gpt4 key购买 nike

在 C 语言中,我有一个任务,我必须对分配为二维数组(数组的数组)的巨大矩阵进行乘法、求逆、转置、加法等操作。

我找到了 gcc 标志 -funroll-all-loops。如果我理解正确的话,这将自动展开所有循环,而无需程序员的任何努力。

我的问题:

a) gcc 是否包括这种带有各种优化标志的优化,如 -O1-O2 等?

b) 我是否必须在我的代码中使用任何 pragma 才能利用循环展开或自动识别循环?

c)如果展开可以提高性能,为什么默认情况下不启用此选项?

d) 以最佳方式编译程序的推荐 gcc 优化标志是什么? (我必须运行针对单个 CPU 系列优化的程序,这与我编译代码的机器相同,实际上我使用 march=native-O2 标志)

编辑

似乎对 unroll 的使用存在争议,在某些情况下可能会降低性能。在我的情况下,有多种方法可以在 2 个嵌套 for 循环中简单地执行数学运算,以迭代对大量元素完成的矩阵元素。在这种情况下,展开如何降低或提高性能?

最佳答案

为什么展开循环?

现代处理器流水线指令。他们喜欢知道接下来会发生什么,并根据指令执行顺序的假设进行各种奇特的优化。

虽然在循环结束时,有两种可能性!要么回到顶部,要么继续。处理器对将要发生的事情做出有根据的猜测。如果它做对了,一切都很好。如果没有,它必须刷新管道并在准备采用另一个分支时暂停一下。

正如您想象的那样,展开一个循环可以消除分支和这些停顿的可能性,尤其是在赔率与猜测不符的情况下。

想象一个代码循环,执行 3 次,然后继续。如果您假设(处理器可能会这样做)最后您将重复循环。 2/3 的时间,你会是正确的!不过有 1/3 的时间,您会停滞不前。

另一方面,想象同样的情况,但是代码循环了 3000 次。在这里,展开的时间可能只有 1/3000 的 yield 。

为什么展开循环?

上面提到的部分处理器功能涉及将指令从内存中的可执行文件加载到处理器的板载指令缓存(缩写为 I-cache)中。这包含有限数量的指令,可以快速访问,但当需要从内存加载新指令时可能会停止。

让我们回到前面的例子。假设循环内相当少量的代码占用了 I-cache 的 n 字节。如果我们展开循环,它现在占用 n * 3 字节。多一点,但它可能适合单个缓存行,因此您的缓存将以最佳方式工作,而不需要停止从主内存读取。

然而,3000 循环展开后会使用高达 n * 3000 字节的 I 缓存。这将需要多次从内存中读取,并且可能将程序中其他地方的一些其他有用的东西从 I-cache 中推出。

那我该怎么办?

如您所见,展开为较短的循环提供了更多好处,但如果您打算循环很多次,最终会降低性能。

通常,聪明的编译器会合理猜测要展开哪些循环,但如果您确定知道得更多,则可以强制执行。你如何更好地了解?唯一的方法是两种方式都尝试并比较时间!

过早的优化是万恶之源 -- Donald Knuth

先分析,再优化。

关于c - GCC循环展开标志真的有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24196076/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com