使用返回值优化get和函数调用周围的循环
Optimize loop around a get and function call using returned value?
这是一个从缓冲源获取数据并将其发送到处理的片段。如果队列为空,get()返回一个null,进程方法很乐意接受一个null,什么也不做。编写这种代码的最佳方式是什么?
something a; // any legal C++ return type...
aQueueOfSomethings g;
while (true) {
a=g.get();
process(a);
}
没有办法预测通过get()到达的值,它们就是它们,它们需要尽快从队列中取出并传递给process()。
我没有看到这里浪费了很多精力-如果我跳过名为'a'的显式局部变量并使循环变成一行:
process(g.get());
g.g eget()的隐式返回值仍将分配空间,可能涉及构造函数调用,等等。
如果返回的对象有一定的大小或复杂度,最好有一个指向它的指针,而不是它的副本,并传递该指针,而不是按值复制…所以我更喜欢
something *a;
g.get(a);
process(a);
而不是
something a;
a=g.get();
process(a);
我用c++写了一个测试用例,尝试两行和一行版本,循环100,000,000次。
如果a是一个包含4个整数和2个浮点数的对象,并且process()方法涉及到它们,那么两行解决方案实际上更快!如果a对象是单个int类型,则单行版本更快。如果对象很复杂,但是process()方法只涉及一个值,那么一行代码会更快。
对我来说最有趣的是,使用g++编译器,Mac OS X 10.5.8, -O第一级优化开关在1行和2行版本中产生相同的,更快的操作。
除了让编译器优化,单行的方法和没有显式的中间变量,并通过引用传递,以避免复制,有没有什么通常会使它运行得更快?我觉得我错过了一些明显的东西。
我认为这是一个无用的优化的最高案例
(您正在使用缓冲区和想要对其进行位优化的东西?)
同样,编译器将两种方式编译成完全相同的代码,并且(在大多数情况下)完全有权进行返回值优化和尾部调用优化。
结合可能的queue_class::get()内联,您的问题似乎完全没有意义
我相信你是想在编译器的工作上打败他。
你遇到过性能问题吗?如果没有,您可能会专注于生成可读的代码(您似乎有),您可以维护,而不是诉诸于可能是过早的优化和混乱的代码与奇怪的优化。
这段代码的问题不在于你做了什么,而在于它必须旋转- 浪费CPU周期,即使在没有工作要做的情况下,计算机执行的其他任务可能已经使用了。
如果有很多程序采取这种态度(它们是计算机之王,会占用整个cpu),那么一切都会变慢到绝对爬行。让你的代码像这样工作是一个非常极端的决定。
如果可能的话,更改整个模型,以便在有更多可用数据时获得某种回调/信号/事件。
你是对的,你应该让编译器优化,但如果你知道这样做是安全的:
while (true) {
a=g.get();
b=g.get();
c=g.get();
d=g.get();
process(a);
process(b);
process(c);
process(d);
}
那么它可能会使事情更快。
或者,更极端的是,准备好返回类型的整个数组(或指向该类型的指针),然后循环处理它们。如果process()和get()都使用了大量的代码,那么这样做可能意味着所有的代码都可以留在即时缓存中,而不是每次调用函数时都从另一个缓存中取出。
编译器不能做这个优化,因为它可能不知道重新排序函数调用是安全的。
- 函数调用中参数的顺序重要吗
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 变量没有改变?通过向量的函数调用
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 模板函数调用
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 析构函数调用
- 成员函数调用和C++对象模型
- 使用共享指针的函数调用,其对象应为 const
- C++:编译时检查匹配的函数调用对?
- 函数调用C++中的参数太少
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 返回指向对象的指针的函数调用是否为 prvalue?
- C++ 如何重载 [] 运算符并进行函数调用
- 代码的效率. 转到和函数调用
- 是同一作用域的函数部分中的函数调用
- 函数调用周围的圆括号
- 使用返回值优化get和函数调用周围的循环