Input efficiency

Write here if you have problems with your C++ source code

Moderator: Board moderators

Post Reply
Eric3k
New poster
Posts: 29
Joined: Mon Apr 29, 2002 5:22 pm

Input efficiency

Post by Eric3k »

Hi,
I solved a problem and ran in about .7 seconds. However, I thought the algorithm was pretty fast yet in the statistics, some people solved it in .01 secs. So instead I removed all the code but the input statements and received a WA in .5 secs.
Therefore it must be the input that's slow.
I used std::cin for reading n sets, each set consisting of three strings.
Ex:
cin>>n;
for (int i=0;...){
string a,b,c;
for (int j=0;j<3;j++){
cin>>a>>b>>c;
....
}
}

I also changed it to scanf to check how long it took and it ran in about .4 secs.
So I'm :roll: :-? :o :( . Does anyone know any faster ways to read from the standard input?
Thx
kmhasan
Problemsetter
Posts: 107
Joined: Fri Oct 26, 2001 2:00 am
Location: Canada
Contact:

Post by kmhasan »

Yes, there are faster ways to get input. You can try the fread() function.

Have a look at the following threads:
http://acm.uva.es/board/viewtopic.php?t ... ight=fread
http://acm.uva.es/board/viewtopic.php?t ... ight=fread
Eric3k
New poster
Posts: 29
Joined: Mon Apr 29, 2002 5:22 pm

Post by Eric3k »

Cool thanks! I'll try those. :D
Moni
Experienced poster
Posts: 202
Joined: Fri Mar 22, 2002 2:00 am
Location: Chittagong. CSE - CUET
Contact:

Post by Moni »

kmhasan wrote:Yes, there are faster ways to get input. You can try the fread() function.

Have a look at the following threads:
http://acm.uva.es/board/viewtopic.php?t ... ight=fread
http://acm.uva.es/board/viewtopic.php?t ... ight=fread
Hi! Tomal!
But if one wants to remain in pure C++ or Java code he must sacrifice this type of "fastness"! Isn't it ???
ImageWe are all in a circular way, no advances, only moving and moving!
Eric3k
New poster
Posts: 29
Joined: Mon Apr 29, 2002 5:22 pm

Post by Eric3k »

How about using buffers or sharing input buffers (ie by rdbuf())? Does anyone know about how efficient they are and if there are any ways to convert a streambuffer, like cin.rdbuf() to a string buffer?
I'm guessing that reading the entire buffer and converting it to a string, then processing the string buffer using >> would be faster since it's done in memory. :roll:
Moni
Experienced poster
Posts: 202
Joined: Fri Mar 22, 2002 2:00 am
Location: Chittagong. CSE - CUET
Contact:

Post by Moni »

Are you talking about:

[cpp]

#include <sstream>

[/cpp]

And string to stream and vice versa conversion ???
ImageWe are all in a circular way, no advances, only moving and moving!
Eric3k
New poster
Posts: 29
Joined: Mon Apr 29, 2002 5:22 pm

Post by Eric3k »

Yeah like istringstream (or maybe stringbuf). What am wondering is if maybe reading the entire cin buffer and converting it to a string buffer, then processing it in memory to make it faster.
kmhasan
Problemsetter
Posts: 107
Joined: Fri Oct 26, 2001 2:00 am
Location: Canada
Contact:

Post by kmhasan »

Sorry that I took time to post a reply. My phone line went dead and I'm off the 'Net.

Yes, it is possible to do faster I/O operations with C++ too. But the question is, would we like to do that? First let me show an example of doing fast (block) input handling for reading non-negative integers.
[cpp]
#include <cstdio>
#include <iostream>
using namespace std;

class myclass {
private:
int number;
static const int MAXSIZE = 1000000;
static char inpbuffer[MAXSIZE], *ptr;
static bool read;
public:
int getNumber() {
return number;
}
void setNumber(int number) {
myclass::number = number;
}
friend ostream& operator<<(ostream&, myclass&);
friend bool operator>>(istream&, myclass&);
};
bool myclass::read;
char myclass::inpbuffer[myclass::MAXSIZE];
char* myclass::ptr;

ostream& operator<<(ostream& out, myclass& obj) {
out<<obj.getNumber();
return out;
}
bool operator>>(istream& in, myclass& obj) {
if (myclass::read==false) {
in.read(myclass::inpbuffer,sizeof(myclass::inpbuffer));
// fread(myclass::inpbuffer,sizeof(myclass::inpbuffer),sizeof(char),stdin);
myclass::ptr = myclass::inpbuffer;
myclass::read = true;
}
int num = 0;
while (true) {
while (*myclass::ptr && (*myclass::ptr<'0' || *myclass::ptr>'9'))
myclass::ptr++;

if (*myclass::ptr=='\0') return false;
while (*myclass::ptr && *myclass::ptr>='0' && *myclass::ptr<='9') {
num *= 10;
num += *myclass::ptr-'0';
myclass::ptr++;
}
break;
}
if (*myclass::ptr) {
obj.setNumber(num);
return true;
} else return false;
}

int main() {
myclass myobj;
while (cin>>myobj) {
cout<<myobj<<endl;
// printf("%d\n",myobj.getNumber());
}
return 0;
}
[/cpp]
The same thing can be done in C, using:
[c]
#include <stdio.h>
#define MAXSIZE 1000000

char inpbuffer[MAXSIZE], *ptr;
int read;

int getNumber() {
if (!read) {
fread(inpbuffer,sizeof(inpbuffer),sizeof(char),stdin);
ptr = inpbuffer;
read = 1;
}
int num = 0;
while (1) {
while (*ptr && (*ptr<'0' || *ptr>'9'))
ptr++;

if (*ptr=='\0') return -1;
while (*ptr && *ptr>='0' && *ptr<='9') {
num *= 10;
num += *ptr-'0';
ptr++;
}
break;
}
if (*ptr) {
return num;
} else return -1;
return num;
}

int main() {
int num;
while ((num=getNumber())!=-1)
printf("%d\n",num);
return 0;
}
[/c]
The C++ code runs a bit slower compared to the C code. But it remains higly comparable. I verified the codes in Visual C++ .Net and GCC 3.2.2 from DJGPP on Windows XP and GCC 3.2 on RedHat linux 8.0.

If you'd notice, you'd see that in the C++ code I've tried to go with the OOP paradigm. Thanks to the nifty feature of operator overloading of C++, looking at the main method you'd see that life had been made a lot easier. But, if you'd have a look at the class definition, you'd clearly see how many stupid things I had to do for this simple task. The task was simply to read non-negative integers (reading by block of course), why on earth should I instantiate objects with an integer data member only?

OOP is good. In my undergraduate program my introduction to programming was with JAVA, for that reason I tried my level best to be an OO purist. But as I moved on to programming contests, I realized that given the limited time to solve a problem, it's better to give up those ideal thoughts. OO features are quite useful for solving problems, even in real time programming contests, however it's not really wise to follow OOP strictly everywhere in a contest. For application programming given the freedom, I'd definitely go for OOP. But for real-time contests (not for online contests ;) ) I'd suggest to think if it's necessary at all.

I prefer not to say anything about doing faster I/O with JAVA. UVA OJ doesn't provide reasonable support for JAVA. The way it is now, doing simple I/O seems quite painful. I hope UVA would provide the required support as they promised to do it "soon".
Moni
Experienced poster
Posts: 202
Joined: Fri Mar 22, 2002 2:00 am
Location: Chittagong. CSE - CUET
Contact:

Post by Moni »

Yes! :D Brother Tomal! You are also supporting me :wink: (Though Stefan didn't :cry: ) :

http://acm.uva.es/board/viewtopic.php?t=370&start=30
ImageWe are all in a circular way, no advances, only moving and moving!
kmhasan
Problemsetter
Posts: 107
Joined: Fri Oct 26, 2001 2:00 am
Location: Canada
Contact:

Post by kmhasan »

Moni: I am sorry to say that I don't support you. When I posted my previous reply I haven't read the latest posts under the thread for which you posted a link to. After reading those posts I see that there are many things that people agree on, and I feel the same way about those. But there are differences, too. For example you said:
Moni wrote:And another important thing, don't make it habit to use the advanced routines provided by the complier ...
I'd say it'd be blunder if you follow such strategy when you get prepared for real time contests. You must code the advanced routine yourself before you use the ones provided by the compiler. That's for your knowledge and experience. When you're done with that part, you have every right to use the advanced routines provided by the compiler and be proud about that.
You also said that JAVA is not suitable for contests. I'd strongly disagree to that. We used JAVA in real time contests, and it really gave us an edge over other teams, at least for about 2 and a half hours.
So, you see there are reasons for my not supporting you.
I must say I was shocked to see you write:
Moni wrote:I always use my junior students to make the code for me. I make the algorithm clear to them and they do the rest for me.
Now I realize why George Bernard Shaw said:
He who can, does
He who cannot, teaches.
bugzpodder
Experienced poster
Posts: 147
Joined: Fri Jun 13, 2003 10:46 pm

Post by bugzpodder »

okay, i was using cin/cout then i switched to scanf/printf. memory usage has gone down by 50 or so, but my execution time went up 0.030!!
i read that cin is faster than scanf so i tried cin/prinf, but the execution time went up even more (another 0.010). i went back to cin/cout and the time went down again. is it suppose to happen? i always thought cin/cout is slower than scanf/printf. I am trying this on 116 Unidirectional TSP. here are the times.

0:00.748 448 28684 C++ 116 - Unidirectional TSP
0:00.799 452 28684 C++ 116 - Unidirectional TSP
0:00.779 400 28684 C++ 116 - Unidirectional TSP
0:00.803 404 28684 C++ 116 - Unidirectional TSP
0:00.777 400 28684 C++ 116 - Unidirectional TSP
0:00.754 456 28684 C++ 116 - Unidirectional TSP
0:00.754 456 28684 C++ 116 - Unidirectional TSP
0:00.754 452 28684 C++ 116 - Unidirectional TSP

the .754 ish is cin/cout
.799 is the cin/printf
the 3 in the middle is scanf/printf
havnt tried scanf/cout

maybe it makes a difference if i compile in C and C++?
Post Reply

Return to “C++”