How to accelerate the input and output of c ++ In the ACM competition? How can we make the cin speed equal to the scanf speed? What is the fastest input/output method ?, Cinscanf
During the competition, when encountering big data, reading files often becomes the bottleneck of program running speed and requires faster reading. I believe that almost all C ++ learners are stuck at the slow speed of the cin machine, so I vowed not to use the cin to read data. It is also said that the speed of Pascal's read statement is not comparable to that of scanf in C/C ++, and C ++ players can only be anxious. Is C ++ really inferior to Pascal? The answer is self-evident. An advanced method is to read the data and then convert the string. This method is a good method, but I have never tried it, so today, we simply tested all the methods we could think of to read data, and the results were amazing.
In the competition, the most recent data reading experience could not be reached. I wrote a program to generate 10 million random numbers to data.txt, a total of 55 MB. Then I wrote a program trunk to calculate the running time. The Code is as follows:
#include <ctime>int main(){ int start = clock(); //DO SOMETHING printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);}
The simplest method is to write a circular scanf. The Code is as follows:
const int MAXN = 10000000;int numbers[MAXN];void scanf_read(){ freopen("data.txt","r",stdin); for (int i=0;i<MAXN;i++) scanf("%d",&numbers[i]);}
But how efficient? The test result on my computer Linux platform is 2.01 seconds. The following is the cin code:
const int MAXN = 10000000;int numbers[MAXN];void cin_read(){ freopen("data.txt","r",stdin); for (int i=0;i<MAXN;i++) std::cin >> numbers[i];}
Unexpectedly, cin took only 6.38 seconds, faster than I thought. There is a reason for the slow cin. By default, cin and stdin are always synchronized. That is to say, these two methods can be mixed without worrying about file pointer confusion, the same is true for cout and stdout. This compatibility feature causes many additional overhead for cin. How can I disable this feature? You only need one statement std: ios: sync_with_stdio (false); To cancel synchronization of cin to stdin. The procedure is as follows:
const int MAXN = 10000000;int numbers[MAXN];void cin_read_nosync(){ freopen("data.txt","r",stdin); std::ios::sync_with_stdio(false); for (int i=0;i<MAXN;i++) std::cin >> numbers[i];}
What is the efficiency after canceling synchronization? The test run time dropped to 2.05 seconds,The efficiency is almost the same as that of scanf.! With this, you can safely use cin and cout.
Next, let's test the method of reading the entire file and then processing it. First, we need to write a function that converts a string to an array. The Code is as follows:
const int MAXS = 60*1024*1024;char buf[MAXS];void analyse(char *buf,int len = MAXS){ int i; numbers[i=0]=0; for (char *p=buf;*p && p-buf<len;p++) if (*p == ' ') numbers[++i]=0; else numbers[i] = numbers[i] * 10 + *p - '0';}
The most common method to read the entire file into a string is to use fread. The Code is as follows:
const int MAXN = 10000000;const int MAXS = 60*1024*1024;int numbers[MAXN];char buf[MAXS];void fread_analyse(){ freopen("data.txt","rb",stdin); int len = fread(buf,1,MAXS,stdin); buf[len] = '\0'; analyse(buf,len);}
The above code has an amazing efficiency. It took only 10000000 seconds to read the 0.29 data records, which has improved the efficiency by almost 10 times! It is absolutely invincible to master these methods. However, I remember that fread is encapsulated with read. Is it faster to directly use read? The Code is as follows:
const int MAXN = 10000000;const int MAXS = 60*1024*1024;int numbers[MAXN];char buf[MAXS];void read_analyse(){ int fd = open("data.txt",O_RDONLY); int len = read(fd,buf,MAXS); buf[len] = '\0'; analyse(buf,len);}
The test shows that the running time is still 0.29 seconds. Therefore, read does not have any special advantages. Is it over now? No, I can call the underlying function mmap in Linux. The function maps files to the memory, which is the basic method to encapsulate all file reading methods, what if I directly use mmap? The Code is as follows:
const int MAXN = 10000000;const int MAXS = 60*1024*1024;int numbers[MAXN];char buf[MAXS];void mmap_analyse(){ int fd = open("data.txt",O_RDONLY); int len = lseek(fd,0,SEEK_END); char *mbuf = (char *) mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); analyse(mbuf,len);}
After testing, the running time was shortened to 0.25 seconds, and the efficiency was improved by 14%. So far, I have no better way to continue improving the speed of reading files. How is Pascal's speed? ResultAstonishingIt runs for as many as 2.16 seconds. The procedure is as follows:
const MAXN = 10000000;var numbers :array[0..MAXN] of longint; i :longint;begin assign(input,'data.txt'); reset(input); for i:=0 to MAXN do read(numbers[i]);end.
To ensure accuracy, I switched to the Windows platform for a test. The results are as follows:
Method/platform/time (seconds) |
Linux gcc |
Windows mingw |
Windows VC2008 |
Scanf |
2.010 |
3.704 |
3.425 |
Cin |
6.380 |
64.003 |
19.208 |
Cin cancel synchronization |
2.050 |
6.004 |
19.616 |
Fread |
0.290 |
0.241 |
0.304 |
Read |
0.290 |
0.398 |
Not Supported |
Mmap |
0.250 |
Not Supported |
Not Supported |
Pascal read |
2.160 |
4.668 |
|
Several problems can be seen from the above
- Programs running on Linux platforms are generally faster than those running on Windows.
- In Windows, VC-compiled programs generally run faster than MINGW (MINimal Gcc for Windows.
- Whether VC cancels synchronization of cinInsensitive, With the same efficiency. In turn, MINGWVery sensitive, The efficiency is 8 times different.
- Read is a linux system function, and MINGW may adopt some analog method. read is slower than fread.
- The speed at which Pascal programs run is not flattering.
I hope this article will inspire you and welcome to continue with the discussion.
BYVoid original reprinted please note
Using cin. tie and sync_with_stdio to speed up input and output, the speed of cin can be close to that of scanf, but the compiler should be more specific.
Tie
Tie is a function that binds two streams. If it is null, the current output stream pointer is returned.
12345678910111213141516171819202122 |
#include <iostream> #include <fstream> ///////////////////////////SubMain////////////////////////////////// int main( int argc, char *argv[]) { std::ostream *prevstr; std::ofstream ofs; ofs.open( "test.txt" ); std::cout << "tie example:\n" ; // Output directly to the screen *std::cin.tie() << "This is inserted into cout\n" ; // The default output stream, that is, cout, is returned when a null parameter is called. prevstr = std::cin.tie(&ofs); // Cinbinds ofs and returns the original output stream. *std::cin.tie() << "This is inserted into the file\n" ; // Ofs, output to file std::cin.tie(prevstr); // Restore ofs.close(); system ( "pause" ); return 0; } ///////////////////////////End Sub////////////////////////////////// |
Output:
123 |
tie example: This is inserted into cout Press any key to continue... |
Test.txt output in the current directory at the same time:
1 |
This is inserted into the file |
Sync_with_stdio
This function is a "stdio compatible" switch. C ++ ensures that the program is not confused when using std: printf and std: cout to be compatible with C, binds the output stream together.
Application
In ACM, a large dataset often causes cin TLE. At this time, most people (including me as well) think that this is the fault that the efficiency of cin is less than that of scanf, and even rise to the boring debate on the execution efficiency of C and C ++ languages. As mentioned above, this is only a conservative measure that C ++ has taken to ensure compatibility. We can unbind stdio before I/O, so do not mix cout and printf at the same time.
By default, cin is bound to cout. flush is called every time the <operator is executed, which increases the IO burden. You can use tie (0) (0 indicates NULL) to unbind cin from cout to accelerate execution efficiency.
As follows:
1234567 |
#include <iostream> int main() { std::ios::sync_with_stdio( false ); std::cin.tie(0); // IO } |
Reference:
Http://meme.biology.tohoku.ac.jp/students/iwasaki/cxx/speed.html
Http://www.hankcs.com/program/cpp/cin-tie-with-sync_with_stdio-acceleration-input-and-output.html
The following describes the fastest way to read data. It directly converts the read data to a string, but the general question is rarely caught in this case. Unless the subject deliberately stops reading the data, you need to turn it on at this time ....
void scan_d(int &ret){ char c; ret = 0; while((c=getchar())<'0' || c>'9'); while(c>='0'&&c<='9') ret = ret*10 +(c-'0'),c=getchar();}
The question has 1099 AC code on acdream's oj.
/** this code is made by ACXZZ* Problem: 1099* Verdict: Accepted* Submission Date: 2014-06-14 21:57:31* Time: 936MS* Memory: 45084KB*/#include<iostream>#include <algorithm>#include<cstring>#include<cstdlib>#include<queue>#include<cstdio>using namespace std;const int N = 11111111; void scan_d(int &ret){ char c; ret = 0; while((c=getchar())<'0' || c>'9'); while(c>='0'&&c<='9') ret = ret*10 +(c-'0'),c=getchar();}int a[N];int main(){ int n,k; cin>>n>>k; for(int i = 0 ; i<n;i++) { scan_d(a[i]); } nth_element(a,a+n-k,a+n); cout<<a[n-k]<<endl;}
If the output is accelerated, it will be similar. If the number is converted to characters, puthcar can output the data.