使用返回值优化get和函数调用周围的循环

Optimize loop around a get and function call using returned value?

本文关键字:函数调用 周围 循环 get 返回值 优化      更新时间:2023-10-16

这是一个从缓冲源获取数据并将其发送到处理的片段。如果队列为空,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()都使用了大量的代码,那么这样做可能意味着所有的代码都可以留在即时缓存中,而不是每次调用函数时都从另一个缓存中取出。

编译器不能做这个优化,因为它可能不知道重新排序函数调用是安全的。