为什么std :: cout如此耗时? [英] Why is std::cout so time consuming?

查看:207
本文介绍了为什么std :: cout如此耗时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个程序来计算8个字符串 sharjeel的排列。

I have made a program to compute the permutations of an 8 character string "sharjeel".

#include <iostream>
#include <time.h>

char string[] = "sharjeel";
int len = 8;
int count = 0;

void swap(char& a, char& b){
    char t = a;
    a = b;
    b = t;
}
void permute(int pos) {
    if(pos==len-1){
        std::cout << ++count << "\t" << string << std::endl;
        return;
    }
    else {
        for (int i = pos; i < len;i++)
        {
            swap(string[i], string[pos]);
            permute(pos + 1);
            swap(string[i], string[pos]);
        }
    }
}

int main(){
    clock_t start = clock();
    permute(0);
    std::cout << "Permutations: " << count << std::endl;
    std::cout << "Time taken: " << (double)(clock() - start) / (double)CLOCKS_PER_SEC << std::endl;
    return 1;
}

如果我打印每个排列,执行大约需要9.8秒。

If I print each permutation along it takes about 9.8 seconds for the execution to complete.

40314   lshaerej
40315   lshareej
40316   lshareje
40317   lshareej
40318   lshareje
40319   lsharjee
40320   lsharjee
Permutations: 40320
Time taken: 9.815

现在,如果我替换以下行:

Now if I replace the line:

std::cout << ++count << "\t" << string << std::endl;

其中:

++count;

然后重新编译,输出为:

and then recompile, the output is:

Permutations: 40320
Time taken: 0.001

再次运行:

Permutations: 40320
Time taken: 0.002

使用带-O3的g ++编译

Compiled using g++ with -O3

为什么std :: cout相对比较耗时?有没有一种更快的打印方法?

Why is std::cout so relatively time consuming? Is there a way to print that is faster?

编辑:制作了该程序的C#版本

Made a C# version of the program

/*
 * Permutations
 * in c#
 * much faster than the c++ version 
 */

using System;
using System.Diagnostics;

namespace Permutation_C
{
    class MainClass
    {
        private static uint len;
        private static char[] input;
        private static int count = 0;

        public static void Main (string[] args)
        {
            Console.Write ("Enter a string to permute: ");
            input = Console.ReadLine ().ToCharArray();
            len = Convert.ToUInt32(input.Length);
            Stopwatch clock = Stopwatch.StartNew();
            permute (0u);
            Console.WriteLine("Time Taken: {0} seconds", clock.ElapsedMilliseconds/1000.0);
        }

        static void permute(uint pos)
        {

            if (pos == len - 1u) {
                Console.WriteLine ("{0}.\t{1}",++count, new string(input));
                return;
            } else {
                for (uint i = pos; i < len; i++) {
                    swap (Convert.ToInt32(i),Convert.ToInt32(pos));
                    permute (pos + 1);
                    swap (Convert.ToInt32(i),Convert.ToInt32(pos));
                }
            }

        }
        static void swap(int a, int b) {
            char t = input[a];
            input[a] = input[b];
            input[b] = t;
        }
    }
}

输出:

40313.  lshaerje
40314.  lshaerej
40315.  lshareej
40316.  lshareje
40317.  lshareej
40318.  lshareje
40319.  lsharjee
40320.  lsharjee
Time Taken: 4.628 seconds
Press any key to continue . . .

从这里开始,Console.WriteLine()的速度似乎比std的速度快一倍: :cout。似乎正在减慢std :: cout的速度?

From here, Console.WriteLine() seems almost twice as fast when compared with the results from std::cout. What seems to be slowing std::cout down?

推荐答案

std :: cout 最终会导致操作系统被调用。

std::cout ultimately results in the operating system being invoked.

如果您想快速进行计算,则必须确保计算中不涉及任何外部实体, 尤其是在编写时考虑到多功能性而不是性能的实体,例如操作系统。

If you want something to compute fast, you have to make sure that no external entities are involved in the computation, especially entities that have been written with versatility more than performance in mind, like the operating system.

是否希望它运行得更快?您有几种选择:

Want it to run faster? You have a few options:


  1. 替换<< std :: endl; << ‘n’。这将避免在每一行上将C ++运行时的内部缓冲区刷新到操作系统。

  1. Replace << std::endl; with << '\n'. This will refrain from flushing the internal buffer of the C++ runtime to the operating system on every single line. It should result in a huge performance improvement.

使用 std :: ios :: sync_with_stdio(false); 如用户Galik Mar在评论中建议。

Use std::ios::sync_with_stdio(false); as user Galik Mar suggests in a comment.

在缓冲区中尽可能多地收集外发文本,并使用一次输出整个缓冲区

Collect as much as possible of your outgoing text in a buffer, and output the entire buffer at once with a single call.

将您的输出写入文件而不是控制台,然后由单独的应用程序(例如Notepad ++)显示该文件,该应用程序可以跟踪并继续滚动到底部。

Write your output to a file instead of the console, and then keep that file displayed by a separate application such as Notepad++ which can keep track of changes and keep scrolling to the bottom.

至于为什么它是如此耗时,单词 slow ),这是因为 std :: cout (最终是操作系统的标准输出流)的主要目的是多功能性,而不是性能。考虑一下: std :: cout 是一个C ++库函数,它将调用操作系统。操作系统将确定要写入的文件不是真正的文件,而是控制台,因此它将数据发送到控制台子系统;控制台子系统将接收数据,并且它将开始调用图形子系统以在控制台窗口中呈现文本;图形子系统将在光栅显示器上绘制字体字形,并且在渲染数据时,将滚动控制台窗口,这涉及复制大量视频RAM。即使图形卡在硬件中处理了一部分工作,也需要做很多工作。

As for why it is so "time consuming", (in other words, slow,) that's because the primary purpose of std::cout (and ultimately the operating system's standard output stream) is versatility, not performance. Think about it: std::cout is a C++ library function which will invoke the operating system; the operating system will determine that the file being written to is not really a file, but the console, so it will send the data to the console subsystem; the console subsystem will receive the data and it will start invoking the graphics subsystem to render the text in the console window; the graphics subsystem will be drawing font glyphs on a raster display, and while rendering the data, there will be scrolling of the console window, which involves copying large amounts of video RAM. That's an awful lot of work, even if the graphics card takes care of some of it in hardware.

对于C#版本,我不确定到底要怎么做继续,但是可能发生的事情却大不相同:在C#中,您没有调用 Console.Out.Flush(),因此您的输出被缓存了,并且您没有遭受C ++的 std :: cout<< std :: endl 会导致每行刷新到操作系统。 但是 ,当缓冲区确实变满时,C#必须将其刷新到操作系统,然后不仅受到表示的开销的打击不仅取决于操作系统,还取决于虚拟机工作方式固有的强大的从托管到本地以及从本地到托管的过渡。

As for the C# version, I am not sure exactly what is going on, but what is probably happening is something quite different: In C# you are not invoking Console.Out.Flush(), so your output is cached and you are not suffering the overhead incurred by C++'s std::cout << std::endl which causes each line to be flushed to the operating system. However, when the buffer does become full, C# must flush it to the operating system, and then it is hit not only by the overhead represented by the operating system, but also by the formidable managed-to-native and native-to-managed transition that is inherent in the way it's virtual machine works.

这篇关于为什么std :: cout如此耗时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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