Using scanf() in C++ programs is faster than using cin?
Solution 1
Here's a quick test of a simple case: a program to read a list of numbers from standard input and XOR all of the numbers.
iostream version:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
scanf version:
#include <stdio.h>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (1 == scanf("%d", &x))
parity ^= x;
printf("%d\n", parity);
return 0;
}
Results
Using a third program, I generated a text file containing 33,280,276 random numbers. The execution times are:
iostream version: 24.3 seconds
scanf version: 6.4 seconds
Changing the compiler's optimization settings didn't seem to change the results much at all.
Thus: there really is a speed difference.
EDIT: User clyfish points out below that the speed difference is largely due to the iostream I/O functions maintaining synchronization with the C I/O functions. We can turn this off with a call to std::ios::sync_with_stdio(false);
:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
std::ios::sync_with_stdio(false);
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
New results:
iostream version: 21.9 seconds
scanf version: 6.8 seconds
iostream with sync_with_stdio(false): 5.5 seconds
C++ iostream wins! It turns out that this internal syncing / flushing is what normally slows down iostream i/o. If we're not mixing stdio and iostream, we can turn it off, and then iostream is fastest.
The code: https://gist.github.com/3845568
Solution 2
http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma
Performance of cin
/cout
can be slow because they need to keep themselves in sync with the underlying C library. This is essential if both C IO and C++ IO is going to be used.
However, if you only going to use C++ IO, then simply use the below line before any IO operations.
std::ios::sync_with_stdio(false);
For more info on this, look at the corresponding libstdc++ docs.
Solution 3
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 "The String Formatters of Manor Farm" 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.
Solution 4
I just spent an evening working on a problem on UVa Online (Factovisors, a very interesting problem, check it out):
I was getting TLE (time limit exceeded) on my submissions. On these problem solving online judge sites, you have about a 2-3 second time limit to handle potentially thousands of test cases used to evaluate your solution. For computationally intensive problems like this one, every microsecond counts.
I was using the suggested algorithm (read about in the discussion forums for the site), but was still getting TLEs.
I changed just "cin >> n >> m" to "scanf( "%d %d", &n, &m )" and the few tiny "couts" to "printfs", and my TLE turned into "Accepted"!
So, yes, it can make a big difference, especially when time limits are short.
Solution 5
If you care about both performance and string formatting, do take a look at Matthew Wilson's FastFormat library.
edit -- link to accu publication on that library: http://accu.org/index.php/journals/1539
zeroDivisible
Updated on July 08, 2022Comments
-
zeroDivisible almost 2 years
I don't know if this is true, but when I was reading FAQ on one of the problem providing sites, I found something, that poke my attention:
Check your input/output methods. In C++, using cin and cout is too slow. Use these, and you will guarantee not being able to solve any problem with a decent amount of input or output. Use printf and scanf instead.
Can someone please clarify this? Is really using scanf() in C++ programs faster than using cin >> something ? If yes, that is it a good practice to use it in C++ programs? I thought that it was C specific, though I am just learning C++...
-
mekanik almost 15 yearsI'm curious what kind of problems they have where they think this will be an issue. Do you have a link to that site?
-
zeroDivisible almost 15 years@Eclipse: here is the link to the site: spoj.pl , the above citation was found somewhere on the forums.
-
John Kugelman almost 15 yearsMy guess: bad programmer blames standard libraries for poor performance. Kind of like the always humorous "I think I found a bug in GCC" cry.
-
mpen almost 15 years@eclipse: the ACM problems I've worked on for competitions have a substantial amount of input/output and your program has to solve the questions in under something like 60 seconds... it becomes a real issue here.
-
mpen almost 15 years--- that said, if you need to rely on scanf() for that extra performance boost, you're going about the problem the wrong way :)
-
Johannes Schaub - litb almost 15 yearsthis is some amusing thing about cin (scroll to where talks about its slowdown in his impl): unthought.net/c++/c_vs_c++.html
-
mekanik almost 15 yearsJust as an observation - I played around with it, and on the 2nd problems (PRIME1) - using the same algorithm, both times, once using cin/cout and once with scanf/printf and the first version was faster than the second (but close enough that it's statistically irrelevant). This is one of the problems that is marked as being input/output intensive, and the method of input/output made no statistical difference whatsoever.
-
zeroDivisible almost 15 years@Eclipse - thanks for the information about testing both methods. I'm sad though - I tried to blame cin and cout, but now I know that my algorithm sucks:)
-
-
TOMKA almost 15 yearsWhat about IPC through pipes? Do you think there might be a noticeable performance hit there?
-
Jay Conrod almost 15 yearsEven with IPC through pipes, much more time is spent going in and out of the kernel than just parsing it with scanf/cin.
-
Johannes Schaub - litb almost 15 yearsI did tests in this area, and certainly cout & cin suck performance. While for user input it's negligible, it's certainly not so for things where performance matters. Other c++ framework exist that are faster, though.
-
visual_learner almost 15 yearsI don't think so. I think GNU's libc is pure C and assembly.
-
Shaunak Patel almost 15 yearsAgree completely. But you need to be aware that FastFormat is only for output. It has no input/read facilities. (Not yet, anyway)
-
nibot over 11 yearsUnfortunately that link seems to be dead. Here's a Wayback Machine copy: web.archive.org/web/20081222164527/http://fastformat.org
-
gabrielhidasy about 11 yearsJust checked the line above (std::ios::sync_with_stdio(false);) And it really make iostream almost as fast as cstdio
-
MuhammadAnnaqeeb about 10 yearsAgree. Same happened to me in UVA Online Judge problem: Army Buddies uva.onlinejudge.org/…
-
MuhammadAnnaqeeb about 10 yearsalso use cin.tie(static_cast<ostream*>(0)); for better performance
-
MuhammadAnnaqeeb about 10 yearsgetchar_unlocked() is non-standard , and available for gcc not visual studio
-
nibot about 10 yearsIs
cin
really more "abstract" (at runtime) thanscanf
? I don't think so...scanf
must interpret the format string at runtime, whereas theiostream
knows the format at compile-time. -
TOMKA almost 8 years@nibot: The type is known at compile-time but not the format. Whether the input is expected to be hexadecimal or not for example is entirely dependent on how the
std::istream
is configured at runtime (via I/O manipulators or by setting flags on theistream
object itself). AFILE*
object on the other hand has no such state, so a call toscanf
in this regard is much more stable. -
Krishna Mohan almost 8 yearsI think the use of 'endl' may slowdown the execution.
-
nibot almost 8 yearsThe use of std::endl is not in the loop.
-
polkovnikov.ph over 7 yearsThe problem is that
iostream
is slower than hdd. Yes, it sucks that much. -
iBug about 6 yearsMakes no difference with sync on or off. Blame libc++ for that. It only boosts libstdc++
-
Chandrahas Aroori almost 6 yearsDo you think there is would be any difference between <cstdio> and <stdio.h>??
-
Maxim Egorushkin about 5 years
iostream
loses when you parse more than one integer in onescanf
call. -
Blair Houghton almost 5 yearsAnd then after you turn off syncing, what happens if someone adds a putchar() to your program?
-
Dariush Mazlumi about 4 years+1 for your explanation about synchronization. I had just turned sync off and used both scanf and cin in some code. now I know what was wrong with it. thank you!
-
Luka Govedič over 2 yearsThat doesn't make it better.