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 元素,请将其声明为
1
| std::vector<MyClass> x(n); |
或
1 2
| std::vector<MyClass> x;
x.reserve(n); |
而不仅仅是
1
| 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