草庐IT

c++ - C++中进行良好性能优化的想法

coder 2024-02-06 原文

好的,在过去三天里,我一直处于分析器结果的前面,该结果是通过自动化套件运行相当多的测试用例而产生的。这样做的目的是查看是否存在可以总体上提高性能的良好优化。在这种情况下,我将取得良好的成绩,具体如下:

  • 具有表现的潜力
    两者都是非常好的改进
    最后重要且可观察
    用户级别,例如> 100%改善
    在表现不佳的地区。
  • 具有潜在的核心空间
    减少使用量减少50%以上
    在数据繁重的区域中。
  • 易于实现,且最少
    对代码的混淆和最小化
    副作用。即...的好处
    极大地实现优化
    超过成本。

  • 该应用程序是一个3d映射和建模程序包,在界面中具有大量图形,并在后端进行了几何处理。我已经在确保为大多数处理选择最佳算法方面做了很多工作,并且在此阶段,我正在寻找任何普遍适用的简便方法来处理大型和复杂数据集。到目前为止,我已经提出了以下建议:
  • 搜索时,请保留最近找到的项目的缓冲区并首先进行检查。重复搜索的大量处理似乎是围绕同一区域进行的。从到目前为止的答案来看,这似乎是memoization
  • 的一种特定形式
  • 排序时,检查数据是否尚未按照排序顺序(特别是在使用qsort的地方)
  • 将GUI和处理保持在单独的线程中(无法实现易于实现的良好标准,但IMO仍然值得)
  • 在频繁使用的成员函数中,具有局部类变量且具有显着的构造/销毁时间的地方,请将它们设为私有(private)类成员。动态数组和字符串,尤其是MFC CArrays和CStrings尤其如此。
  • 使用动态数组时,将初始大小设置为略微超过典型用法,并采用指数增长策略。
  • 处理要存储在数组中的非常大的数据集时,请首先调整数据大小,以避免任何重新分配。
  • 避免函数返回会在堆栈上创建临时对象拷贝,请改用引用参数,例如

    CString MyFunc(double x,double y)

  • 效率不如
    void  MyFunc(double x, double y, CString &Result)
    

    实际上,在代码的任何性能关键区域都应避免使用CStrings和大多数MFC。 (编辑:RVO可能更普遍地否定了它,尽管我的应用程序中的CString却不是)

    这些项目似乎在我的上下文中运行良好,但是是否有我遗漏的明显项目,或者是否还有其他良好的优化资源?

    编辑:根据提供的许多评论,显然需要一些进一步的解释。虽然我完全意识到建议针对特定代码段进行特定优化需要先看一下该代码,但过去两天用于分析探查器输出的结果显示了针对优化候选者的某些模式。我也意识到自己对别人在该领域取得良好成就所做的无知,并且(至少对我而言)看到列举的此类技术的值(value)(无论它们是否适用于我的情况)。这个问题不是关于优化的危险,但是对于那里的任何初学者,我建议您首先考虑对优化的强烈要求,然后再考虑。我自己的喜好是在将来根据性能要求在设计阶段进行大多数优化,但是我还是强烈建议进行性能分析,以验证实现中是否满足设计假设。我想请人们将答案仅限于他们自己的积极优化经验,而不是基于他们的信念。
    我们是否应该首先考虑优化。

    FWIW,在我的自动化套件中,让编译器优化代码与不优化代码之间的差异为12%,这在最终用户级别上是可以观察到的。

    第二个编辑:我发现一些相关的帖子非常有益,尤其是Mike Dunlavey关于过于依赖探查器输出的评论。

    Performance optimization strategies of last resort?

    What can I use to profile C++ code in Linux?

    最佳答案

    CString MyFunc(double x, double y)

    is less efficient than

    void MyFunc(double x, double y, CString &Result)



    如果MyFunc书写干净,它们应该大致相同。编译器应该能够利用NRVO。听起来您好像已经进行了概要分析,但发现它不是-我只是说它可能更适合您的条件,例如“对代码的最小混淆”,以稍微重新排列功能本身以使NRVO发生。

    还有更多尝试的方法:
  • 内存(类似于您的缓存
    重复搜索,但更多
    专注于树/图的分辨率,
    如果你有任何)。
  • 如果不需要多余的字符,请使用浮点数而不是 double 数
    精度(如果您愿意,甚至可以是整数
    能够)。
  • 使用类型标记假设(您提到了排序数组-
    另一种常见的是小写字母
    字符串)。创建派生或
    包装类型(例如Sorted<T>)
    使这样的假设明确。那
    如果你有一个方法需要
    例如,Sorted<vector<T> >
    然后给它一个排序的 vector
    直接通过-但是如果您
    给它一个vector<T>,它必须
    在构造了一个Sorted<vector<T> >它将对它进行排序。你可以
    手动断言它已排序
    使用替代构造函数,
    但它使携带更容易
    你的假设,也许
    catch 你可能有的地方
    否则错过。
  • 不要放弃内联等。请确保您完全了解何时
    他们应该提供帮助,何时他们
    应该阻碍。在某些情况下,他们
    确实可以有所作为-但是
    如果您只处理可能不会
    他们任意。
  • 您可能会受益于flyweightpooled object allocators
  • 进行线程处理时,
    尽量减少任何互动,因此
    您可以减少代码量
    需要锁定。经常服用
    甚至相当昂贵的拷贝
    对象可以减少开销
    而不是互斥。明显利用
    可以的原子类型。
  • 关于c++ - C++中进行良好性能优化的想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2190654/

    有关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 - 使用 `+=` 和 `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.你能做的最好的事情是:

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

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

    4. 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”]、[“苹果”、“

    5. Ruby 的数字方法性能 - 2

      我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

    6. ruby - Ruby 性能中的计时器 - 2

      我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

    7. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

      如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

    8. += 的 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=

    9. ruby-on-rails - 在 Rails 3 中进行身份验证最常用的方法是什么? - 2

      我需要在rail3中使用标准注册/登录/忘记密码功能进行身份验证。是否有大多数人为此使用的插件或其他东西? 最佳答案 我不确定最常用的方法是什么-但可以肯定的是,Plataformatec的“Devise”是一个非常流行的方法:http://github.com/plataformatec/devise我已经尝试了一些authgem,对我来说,它是最简单的设置和修改以满足我的需要。它内置了密码恢复、帐户确认(如果需要)和其他一些非常方便的功能。 关于ruby-on-rails-在Rail

    10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

      出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

    随机推荐