Which is the fastest method of input in C++

I am coding for various programming olympiads and thus to improve time efficiency i am looking for the fastest method for getting input without need of adding extra library , ie , within the standard available directory as per gcc compilers as during the competitions we obviously cant add libraries to compiler . Till now in C++ , i used cin and cout , but found that scanf and printf are much faster than it , so can anybody tell me a more faster way , it maybe a custom function , for i don't mind space complexity much , but i prefer time more . Thankyou in advanced .


That streams are always slower than the C-API functions is a pretty common misconception because by default, they synchronize with the C-layer. So yeah, that's a feature, not a bug.

Without sacrificing type safety (and readability, depending on your taste), you possibly gain performance with streams by using:

std::ios_base::sync_with_stdio (false);

A little indicator:

#include <cstdio>
#include <iostream>

template <typename Test> 
void test (Test t)
{
    const clock_t begin = clock();
    t();
    const clock_t end = clock();
    std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}

void std_io() {
    std::string line;
    unsigned dependency_var = 0;

    while (!feof (stdin)) {
        int c;
        line.clear();
        while (EOF != (c = fgetc(stdin)) && c!='n')
            line.push_back (c);
        dependency_var += line.size();
    }

    std::cout << dependency_var << 'n';
}

void synced() {
    std::ios_base::sync_with_stdio (true);
    std::string line;
    unsigned dependency_var = 0;
    while (getline (std::cin, line)) {
        dependency_var += line.size();
    }
    std::cout << dependency_var << 'n';
}

void unsynced() {
    std::ios_base::sync_with_stdio (false);
    std::string line;
    unsigned dependency_var = 0;
    while (getline (std::cin, line)) {
        dependency_var += line.size();
    }
    std::cout << dependency_var << 'n';
}

void usage() { std::cout << "one of (synced|unsynced|stdio), plsn"; }

int main (int argc, char *argv[]) {
    if (argc < 2) { usage(); return 1; }

    if (std::string(argv[1]) == "synced") test (synced);
    else if (std::string(argv[1]) == "unsynced") test (unsynced);
    else if (std::string(argv[1]) == "stdio") test (std_io);
    else { usage(); return 1; }

    return 0;
}

With g++ -O3, and a big text file:

cat testfile | ./a.out stdio
...
0.34 sec

cat testfile | ./a.out synced
...
1.31 sec

cat testfile | ./a.out unsynced
...
0.08 sec

How this applies to your case depends. Modify this toy-benchmark, add more tests, and compare eg something like std::cin >> a >> b >> c with scanf ("%d %d %d", &a, &b, &c); . I guarantee, with optimizations (ie without being in debug mode), performance differences will be subtle.

If that does not saturate your needs, you might try other approaches, eg reading the whole file first (may or may not bring more performance) or memory maps (which is a non-portable solution, but the big desktops have them).


Update

Formatted input: scanf vs. streams

#include <cstdio>
#include <iostream>

template <typename Test> 
void test (Test t)
{
    const clock_t begin = clock();
    t();
    const clock_t end = clock();
    std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}

void scanf_() {
    char x,y,c;
    unsigned dependency_var = 0;

    while (!feof (stdin)) {
        scanf ("%c%c%c", &x, &y, &c);
        dependency_var += x + y + c;
    }

    std::cout << dependency_var << 'n';
}

void unsynced() {
    std::ios_base::sync_with_stdio (false);
    char x,y,c;
    unsigned dependency_var = 0;
    while (std::cin) {
        std::cin >> x >> y >> c;
        dependency_var += x + y + c; 
    }
    std::cout << dependency_var << 'n';
}

void usage() { std::cout << "one of (scanf|unsynced), plsn"; }

int main (int argc, char *argv[]) {
    if (argc < 2) { usage(); return 1; }

    if (std::string(argv[1]) == "scanf") test (scanf_);
    else if (std::string(argv[1]) == "unsynced") test (unsynced);
    else { usage(); return 1; }

    return 0;
}

Results:

scanf: 0.63 sec
unsynced stream: 0.41 

Generally, buffered input will be the fastest. The less frequently you have to flush your input buffer, the faster the input will be. For a full and very informative discussion, see this question. In short, read() with large buffer sizes is as fast as you can get since it's almost directly on top of the corresponding system call in your OS.


Probably scanf is somewhat faster than using streams. Although streams provide a lot of type safety, and do not have to parse format strings at runtime, it usually has an advantage of not requiring excessive memory allocations (this depends on your compiler and runtime). That said, unless performance is your only end goal and you are in the critical path then you should really favour the safer (slower) methods.

There is a very delicious article written here by Herb Sutter

http://www.gotw.ca/publications/mill19.htm

who goes into a lot of detail of the performance of string formatters like sscanf and lexical_cast and what kind of things were making them run slowly or quickly. This is kind of analogous, probably to the kind of things that would affect performance between C style IO and C++ style. The main difference with the formatters tended to be the type safety and the number of memory allocations.

链接地址: http://www.djcxy.com/p/31526.html

上一篇: Python与Numpy / Scipy与纯C ++的大数据分析

下一篇: 这是C ++中最快的输入方法