草庐IT

c++ - 现代 C++ 编译器的有效优化策略

coder 2023-05-01 原文

我正在编写对性能非常关键的科学代码。代码的初始版本已经编写和测试,现在,有了分析器,是时候从热点开始剃须周期了。

众所周知,一些优化,例如循环展开,如今由编译器比由程序员手动干预更有效地处理。哪些技术仍然值得?显然,我会通过探查器运行我尝试的所有操作,但如果有关于哪些方法有效哪些方法无效的传统智慧,这将为我节省大量时间。

我知道优化非常依赖于编译器和架构。我正在使用面向 Core 2 Duo 的英特尔 C++ 编译器,但我也对哪些适用于 gcc 或“任何现代编译器”感兴趣。

以下是我正在考虑的一些具体想法:

  • 将 STL 容器/算法替换为手动容器/算法有什么好处?特别是,我的程序包含一个非常大的优先级队列(当前是 std::priority_queue),其操作占用了很多总时间。这是否值得研究,或者 STL 实现可能已经是最快的了?
  • 类似地,对于所需大小未知但上限相当小的 std::vector,用静态分配的数组替换它们是否有利可图?
  • 我发现动态内存分配通常是一个严重的瓶颈,消除它可以显着提高速度。因此,我对按值返回大型临时数据结构与按指针返回与按引用传递结果的性能权衡很感兴趣。有没有办法可靠地确定编译器是否会对给定方法使用 RVO(当然,假设调用者不需要修改结果)?
  • 编译器的缓存感知能力如何?例如,是否值得研究重新排序嵌套循环?
  • 鉴于程序的科学性, float 无处不在。我的代码中的一个重要瓶颈曾经是从浮点到整数的转换:编译器会发出代码来保存当前的舍入模式,更改它,执行转换,然后恢复旧的舍入模式 --- 即使程序中没有任何内容改变了舍入模式!禁用此行为显着加快了我的代码速度。是否有任何我应该注意的与浮点相关的类似问题?
  • 单独编译和链接 C++ 的一个后果是编译器无法执行看似非常简单的优化,例如将 strlen() 等方法调用移出循环的终止条件。是否有任何像这样的优化我应该注意,因为它们不能由编译器完成,必须手动完成?
  • 另一方面,有哪些我应该避免的技术,因为它们可能会干扰编译器自动优化代码的能力?

最后,将某些类型的答案扼杀在萌芽状态:

  • 我了解优化在复杂性、可靠性和可维护性方面是有代价的。对于这个特定的应用程序,提高性能是值得的。
  • 我知道最好的优化通常是改进高级算法,这已经完成了。

最佳答案

Is there any benefit to replacing STL containers/algorithms with hand-rolled ones? In particular, my program includes a very large priority queue (currently a std::priority_queue) whose manipulation is taking a lot of total time. Is this something worth looking into, or is the STL implementation already likely the fastest possible?

我假设您知道 STL 容器依赖于复制元素。在某些情况下,这可能是一个重大损失。存储指针,如果您进行大量容器操作,您可能会看到性能有所提高。另一方面,它可能会降低缓存局部性并伤害您。另一种选择是使用专门的分配器。

某些容器(例如 mapsetlist)依赖于大量指针操作。尽管有悖常理,但用 vector 替换它们通常会导致更快的代码。生成的算法可能从 O(1)O(log n)O(n),但由于缓存局部性,它可以在实践中要快得多。配置文件是肯定的。

您提到您正在使用 priority_queue ,我想这会为重新排列元素付出很多代价,尤其是在它们很大的情况下。您可以尝试切换底层容器(可能是 deque 或专门的)。我几乎肯定会存储指针 - 再次确认,配置文件。

Along similar lines, for a std::vectors whose needed sizes are unknown but have a reasonably small upper bound, is it profitable to replace them with statically-allocated arrays?

同样,这可能会有所帮助,具体取决于用例。您可以避免堆分配,但前提是您不需要数组超过堆栈...或者您可以 reserve() 中的大小 vector 所以重新分配的复制更少。

I've found that dynamic memory allocation is often a severe bottleneck, and that eliminating it can lead to significant speedups. As a consequence I'm interesting in the performance tradeoffs of returning large temporary data structures by value vs. returning by pointer vs. passing the result in by reference. Is there a way to reliably determine whether or not the compiler will use RVO for a given method (assuming the caller doesn't need to modify the result, of course)?

您可以查看生成的程序集以查看是否应用了 RVO,但如果您返回指针或引用,则可以确定没有拷贝。这是否会有所帮助取决于您在做什么 - 例如。不能返回对临时对象的引用。你可以使用 arenas 来分配 并重用对象,因此不会支付大量的堆惩罚。

How cache-aware do compilers tend to be? For example, is it worth looking into reordering nested loops?

我在这个领域看到了戏剧性的(非常戏剧性的)加速。我从中看到的改进比我后来从多线程代码中看到的要多。从那以后的五年里,情况可能发生了变化——只有一种方法可以确定——个人资料。

On the flip side, are there any techniques I should avoid because they are likely to interfere with the compiler's ability to automatically optimize code?

  • 在单参数构造函数上使用 explicit。临时对象的构造和销毁可能隐藏在您的代码中。

  • 注意对大对象的隐藏复制构造函数调用。在某些情况下,可以考虑用指针替换。

  • 简介,简介,简介。调整瓶颈区域。

关于c++ - 现代 C++ 编译器的有效优化策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2932515/

有关c++ - 现代 C++ 编译器的有效优化策略的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  3. ruby - Sinatra set cache_control to static files in public folder编译错误 - 2

    我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. python - 是否可以使用 Ruby 或 Python 禁用 anchor /引用来发出有效的 YAML? - 2

    是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. .net - 是否有 Ruby .NET 编译器? - 2

    是否有适用于Ruby语言的.NETFramework编译器?我听说过DLR(动态语言运行时),这是否将使Ruby能够用于.NET开发? 最佳答案 IronRuby是Microsoft支持的项目,建立在动态语言运行时之上。 关于.net-是否有Ruby.NET编译器?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/199638/

随机推荐