jjzjj

关于性能:C代码执行慢

codeneng 2023-03-28 原文

C++ code executes slow

我上周移植了一个递归分支

  • 这不是一个真正的问题。没有看到代码就无法说出发生了什么。但一般来说,新手 C 程序员经常写慢程序,因为他们不理解 C 的值语义和复制构造函数语义。您需要尽可能使用引用或移动语义以避免不必要的向量/字符串复制,以及 vector::reserve 以减少重新分配的数量。
  • 我对 C 语言还是有点陌生??,但我认为在堆栈上分配临时空间会有很大帮助。
  • 您是否正在分析调试版本?您应该对所有优化进行分析。
  • 这是一个发布版本,Visual Studio 设置为"完全优化",所以恐怕是我的代码的问题。但是感谢您的评论,我看到我在正确的Rails上!
  • 您如何在函数之间传递向量(尤其是大向量)?按值:void function(vector a),按引用:void function(vector &a) 或按指针:void function(vector *a) 分别。 void function(shared_ptr<vector> a) ?
  • 通过参考,对我来说似乎是最简单的。通过引用传递和通过指针传递之间有很大的区别吗?
  • 不,我猜你是按价值传递的。按参考应该没问题。您是否检查过您的代码是否正确,即使它很慢?即,您的代码是否完成并就小整数 LP 问题给出正确答案?
  • @Christoph 是的,引用不能为空。
  • 1)尝试随机暂停方法。 2)在调试器下执行并使用调试版本。某处的一些助理教授告诉人们你应该只在打开优化的情况下进行分析,那是学术玩具程序的废话。 3)看起来你的第一个大问题是太多新的和自由的。前几个暂停示例将准确告诉您哪些语句负责,您可以将它们移出内部循环或池使用的对象。


是的,如果使用不当,std::vector 可能会很昂贵。最大的性能损失可能是重新分配 - 因为大小需要动态调整,并且元素必须在连续内存中,所以每当您添加超出已分配内容的新元素时,就会发生重新分配。

这就是为什么您应该事先声明尺寸。如果你知道你必须持有 n 元素,请将其声明为

 std::vector<MyClass> x(n);

 std::vector<MyClass> x;
 x.reserve(n);

而不仅仅是

 std::vector<MyClass> x;

后跟 n push_backs.

如果在这之后它仍然很慢,您可以为 std::vector 提供自定义分配器。我希望你不要达到那个地步。

  • 我事先声明了尺寸,所以这是我避免的一些陷阱:)
  • 如果自动调整大小总是使容量翻倍,则在向量大小 M 处,最多执行了 2M 个副本(以及最多 log2(M) 次重新分配),在任何合理的初始容量下要少得多。在任何乘数 B 处,任何向量大小的副本/元素最多为 B/{B-1},因此在 1.5 倍时最多为 3,在 1.25 倍时最多为 5。除非副本非常昂贵,否则这是在喧嚣中,不值得担心。


在 Matlab 中,一切都是对对象的引用。因此,当您传递它们时,您相当于复制了一个指针(大小约为 int,具体取决于几个因素),而不是复制整个矩阵,这可能更大。

没有看到任何代码,我不能肯定地说,但我怀疑您正在复制大量对象而不是复制对它们的引用。我建议您查看智能指针,例如 std::shared_ptr.

你没有说清楚,但你应该优化编译。 (g++ -O3。) 一些昂贵的副本和其他操作可以优化出来,但不是全部。

此外,如果您是 C 新手,您不应该使用 new。它是为专家准备的,只有在与同事讨论并喝了一杯浓咖啡后才能使用。 (当然,new 可能会被某些容器代表您使用,例如 std::vector。)

  • 他可能没有直接使用 new,但 std::vector 在内部调用 new
  • 您断言 new 只能由专家使用,这有点戏剧化。稍加思考,您就可以轻松地以安全且高效的方式使用 new。
  • 幸运的是,我自己没有使用新的。我还通过引用函数来传递向量,这是我已经发现的一件事:)
  • @ChaosPandion 我实际上非常不同意你的观点。新用户现在可以使用 std::make_shared 来实例化堆上的对象,并且设计良好的 API 可以完全消除该要求。初学者无需使用它。
  • @Charles Salvia - 您不仅在猜测您看不到的代码,而且还在猜测背后隐藏的内容(分析器提到了新的和免费的,但您猜想使用的是 std::vector 代替)。
  • @SChepurin,OP 明确表示他正在使用 std::vector。但是,是的,没有代码,这一切都是猜测。
  • 好吧,只是为了确定:如果我写 std::vector<int> test(10),则会调用新的地方来创建这个向量 - 如果我这样做,例如在循环中很多次,这将花费大量时间并像现在一样显示在分析器中。
  • @Christoph 是的。把它贴在循环外面......
  • @Christoph - 这个魔法(10)从何而来?如果您知道大小,那么也许您不需要动态分配并且数组就足够了?而且速度更快。
  • @Christoph - 但是,如果您更喜欢 std::vector 的安全性,那么"如果您要进行大量插入并且您非常了解要存储的内容的大小,那么使用 Reserve 是一个好主意. 它的速度要快得多。"(请参阅?? stackoverflow.com/questions/2761570/...)
  • @Christoph 或者使用 std::array
  • 我的例子中的 10 很神奇,在我的代码中,不幸的是大小来自一个变量。但是我会看看是否可以对其进行一些更改,并且可能会在某些时候引入数组,谢谢您的建议。不幸的是,我现在必须离开,但我会尝试改进我的代码并在有变化时报告!


n


避免调用 new

有关关于性能:C代码执行慢的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  7. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  8. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐