混合cout和printf以加快输出速度 [英] mixing cout and printf for faster output

查看:350
本文介绍了混合cout和printf以加快输出速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行一些测试后,我注意到 printf cout 要快得多。我知道它的实现依赖,但在我的Linux框 printf 是8倍更快。所以我的想法是混合两种打印方法:我想使用 cout 进行简单打印,我计划使用 printf 用于产生巨大的输出(通常在循环中)。我认为只要在切换到其他方法之前不要忘记刷新,就可以安全地进行:

  cout< < Hello<< endl; 
cout.flush();

for(int i = 0; i <1000000; ++ i){
printf(World!\\\
);
}
fflush(stdout);

cout<< 最后一行<< endl;
cout<<冲洗;

是这样吗?



更新:感谢所有宝贵的反馈。答案总结:如果你想避免棘手的解决方案,只是简单地不使用 endl cout 隐式刷新缓冲区。请改用\\\

解决方案

直接回答是,是的,这是好的。



很多人已经提出了如何提高速度的各种想法,但似乎有很多分歧,最有效的。我决定写一个快速测试程序,以至少了解哪些技术做了什么。

  #include< iostream> 
#include< string>
#include< sstream>
#include< time.h>
#include< iomanip>
#include< algorithm>
#include< iterator>
#include< stdio.h>

char fmt [] =%s\\\
;
static const int count = 3000000;
static char const * const string =这是一个字符串。
static std :: string s = std :: string(string)+\\\
;

void show_time(void(* f)(),char const * caption){
clock_t start = clock();
f();
clock_t ticks = clock() - start;
std :: cerr<< std :: setw(30)<< caption
<< :
<< (double)ticks / CLOCKS_PER_SEC<< \\\
;
}

void use_printf(){
for(int i = 0; i printf(fmt,string);
}

void use_puts(){
for(int i = 0; i puts(string);
}

void use_cout(){
for(int i = 0; i std :: cout< string<< \\\
;
}

void use_cout_unsync(){
std :: cout.sync_with_stdio(false);
for(int i = 0; i< count; i ++)
std :: cout< string<< \\\
;
std :: cout.sync_with_stdio(true);
}

void use_stringstream(){
std :: stringstream temp;
for(int i = 0; i< count; i ++)
temp< string<< \\\
;
std :: cout<< temp.str();
}

void use_endl(){
for(int i = 0; i std :: cout< string<< std :: endl;
}

void use_fill_n(){
std :: fill_n(std :: ostream_iterator< char const *>(std :: cout,\\\
), count,string);
}

void use_write(){
for(int i = 0; i std :: cout.write(s.data (),s.size());
}

int main(){
show_time(use_printf,Time using printf);
show_time(use_puts,Time using puts);
show_time(use_cout,Time using cout(synced));
show_time(use_cout_unsync,Time using cout(un-synced));
show_time(use_stringstream,Time using stringstream);
show_time(use_endl,time using endl);
show_time(use_fill_n,Time using fill_n);
show_time(use_write,Time using write);
return 0;
}



我在VC ++ 2013(x86和x64版本) )。一次运行(输出重定向到磁盘文件)的输出如下所示:

  printf:0.953 
使用puts的时间:0.567
使用cout(已同步)的时间:0.736
使用cout(未同步)的时间:0.714
使用stringstream的时间:0.725
使用endl的时间:20.097
使用fill_n的时间:0.749
使用写入的时间:0.499

正如预期,结果不尽相同,但有几点我发现有趣:

  1. printf / puts比写入NUL
    • 但是cout在写入真实文件时保持非常好。

  2. b $ b
    • 在我的测试中,fill_n大约与其他任何一样快

  3. 到目前为止最大的优化是避免endl

  4. cout.write给出了最快的时间(尽管可能不是很大的时间)

强制调用 printf 。 Anders Kaseorg很好地指出 - g ++ 可以识别特定的序列 printf(%s\\\
,foo); 等效于 puts(foo); ,并相应地生成代码(即,生成调用 puts 而不是 printf )。将格式字符串移动到全局数组,并传递作为格式字符串产生相同的输出,但强制它通过 printf 而不是 puts 。当然,他们可能还会在这一天进行优化,但至少现在(g ++ 5.1)使用 g ++ -O3 -S 的测试确认它实际上是调用 printf (其中上一个代码编译为调用 puts )。


After performing some tests I noticed that printf is much faster than cout. I know that it's implementation dependent, but on my Linux box printf is 8x faster. So my idea is to mix the two printing methods: I want to use cout for simple prints, and I plan to use printf for producing huge outputs (typically in a loop). I think it's safe to do as long as I don't forget to flush before switching to the other method:

cout << "Hello" << endl;
cout.flush();

for (int i=0; i<1000000; ++i) {
    printf("World!\n");
}
fflush(stdout);

cout << "last line" << endl;
cout << flush;

Is it OK like that?

Update: Thanks for all the precious feedbacks. Summary of the answers: if you want to avoid tricky solutions, just simply don't use endl with cout since it flushes the buffer implicitly. Use "\n" instead. It can be interesting if you produce large outputs.

解决方案

The direct answer is that yes, that's okay.

A lot of people have thrown around various ideas of how to improve speed, but there seems to be quite a bit of disagreement over which is most effective. I decided to write a quick test program to get at least some idea of which techniques did what.

#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>

char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";

void show_time(void (*f)(), char const *caption) { 
    clock_t start = clock();
    f();
    clock_t ticks = clock()-start;
    std::cerr << std::setw(30) << caption 
        << ": " 
        << (double)ticks/CLOCKS_PER_SEC << "\n";
}

void use_printf() {
    for (int i=0; i<count; i++)
        printf(fmt, string);
}

void use_puts() {
    for (int i=0; i<count; i++) 
        puts(string);        
}

void use_cout() { 
    for (int i=0; i<count; i++)
        std::cout << string << "\n";
}

void use_cout_unsync() { 
    std::cout.sync_with_stdio(false);
    for (int i=0; i<count; i++)
        std::cout << string << "\n";
    std::cout.sync_with_stdio(true);
}

void use_stringstream() { 
    std::stringstream temp;
    for (int i=0; i<count; i++)
        temp << string << "\n";
    std::cout << temp.str();
}

void use_endl() { 
    for (int i=0; i<count; i++)
        std::cout << string << std::endl;
}

void use_fill_n() { 
    std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}

void use_write() {
    for (int i = 0; i < count; i++)
        std::cout.write(s.data(), s.size());
}

int main() { 
    show_time(use_printf, "Time using printf");
    show_time(use_puts, "Time using puts");
    show_time(use_cout, "Time using cout (synced)");
    show_time(use_cout_unsync, "Time using cout (un-synced)");
    show_time(use_stringstream, "Time using stringstream");
    show_time(use_endl, "Time using endl");
    show_time(use_fill_n, "Time using fill_n");
    show_time(use_write, "Time using write");
    return 0;
}

I ran this on Windows after compiling with VC++ 2013 (both x86 and x64 versions). Output from one run (with output redirected to a disk file) looked like this:

          Time using printf: 0.953
            Time using puts: 0.567
   Time using cout (synced): 0.736
Time using cout (un-synced): 0.714
    Time using stringstream: 0.725
            Time using endl: 20.097
          Time using fill_n: 0.749
           Time using write: 0.499

As expected, results vary, but there are a few points I found interesting:

  1. printf/puts are much faster than cout when writing to the NUL device
    • but cout keeps up quite nicely when writing to a real file
  2. Quite a few proposed optimizations accomplish little
    • In my testing, fill_n is about as fast as anything else
  3. By far the biggest optimization is avoiding endl
  4. cout.write gave the fastest time (though probably not by a significant margin

I've recently edited the code to force a call to printf. Anders Kaseorg was kind enough to point out--that g++ recognizes the specific sequence printf("%s\n", foo); is equivalent to puts(foo);, and generates code accordingly (i.e., generates code to call puts instead of printf). Moving the format string to a global array, and passing that as the format string produces identical output, but forces it to be produced via printf instead of puts. Of course, it's possible they might optimize around this some day as well, but at least for now (g++ 5.1) a test with g++ -O3 -S confirms that it's actually calling printf (where the previous code compiled to a call to puts).

这篇关于混合cout和printf以加快输出速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆