これが本当かどうかはわかりませんが、サイトを提供している問題の1つでFAQを読んでいると、何かを見つけました。
入出力方法を確認してください。 C++では、cinとcoutの使用は遅すぎます。これらを使用すると、適切な量の入力または出力の問題を解決できないことが保証されます。代わりにprintfとscanfを使用してください。
誰かがこれを明確にできますか? C++プログラムではcin >> somethingを使用するよりも速くscanf()を実際に使用していますか?はいの場合、それはC++プログラムで使用することをお勧めしますか?私はただC++を学んでいますが、それはC特有だと思いました...
簡単なケースの簡単なテストを次に示します。標準入力とXORすべての数字から数字のリストを読み取るプログラム。
iostreamバージョン:
_#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バージョン:
_#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;
}
_
結果
3番目のプログラムを使用して、33,280,276個の乱数を含むテキストファイルを生成しました。実行時間は次のとおりです。
_iostream version: 24.3 seconds
scanf version: 6.4 seconds
_
コンパイラの最適化設定を変更しても、結果はまったく変わらないようでした。
したがって、実際には速度の違いがあります。
EDIT:User clyfish 以下に指摘 速度の違いは、主にiostream I/O関数がC I/O関数との同期を維持しているためです。 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;
}
_
新しい結果:
_iostream version: 21.9 seconds
scanf version: 6.8 seconds
iostream with sync_with_stdio(false): 5.5 seconds
_
C++ iostreamが勝ちます!この内部同期/フラッシュは、通常iostream i/oを遅くするものであることがわかります。 stdioとiostreamを混在させていない場合は、オフにすることができ、iostreamが最速になります。
http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma
cin
/cout
のパフォーマンスは、基盤となるCライブラリとの同期を維持する必要があるため、遅くなる可能性があります。これは、C IOとC++ IOを使用する場合に必要です。
ただし、C++ IOのみを使用する場合は、IO操作の前に次の行を使用します。
std::ios::sync_with_stdio(false);
詳細については、対応する libstdc ++ docs をご覧ください。
おそらくscanfはストリームを使用するよりもいくらか高速です。ストリームは多くのタイプセーフティを提供し、実行時にフォーマット文字列を解析する必要はありませんが、通常、過剰なメモリ割り当てを必要としないという利点があります(これはコンパイラとランタイムに依存します)。そうは言っても、パフォーマンスが唯一の最終目標であり、クリティカルパスにいる場合を除き、より安全な(より遅い)メソッドを優先する必要があります。
ハーブサッターによる非常においしい記事がここにあります。「 マナーファームのストリングフォーマッター 」は、sscanf
やlexical_cast
およびどのようなものがそれらをゆっくりまたは迅速に実行させていたのか。これは、CスタイルIOとC++スタイルの間のパフォーマンスに影響を与えるようなものにおそらく似ています。フォーマッタとの主な違いは、タイプセーフティとメモリ数です。割り当て。
私は夜、UVa Onlineの問題(Factovisors、非常に興味深い問題、チェックしてみてください)に取り組んでいます。
送信時にTLE(制限時間を超過)を取得していました。これらの問題解決オンラインジャッジサイトでは、ソリューションの評価に使用される可能性のある数千のテストケースを処理するために、約2〜3秒の時間制限があります。このような計算量の多い問題では、マイクロ秒ごとにカウントされます。
提案されたアルゴリズムを使用していました(サイトのディスカッションフォーラムで読みました)が、まだTLEを取得していました。
「cin >> n >> m」を「scanf( "%d%d"、&n、&m)」に変更し、いくつかの小さな「couts」を「printfs」に変更すると、TLEが「Accepted」に変わりました。
それで、はい、特に制限時間が短い場合、それは大きな違いを生むことができます。
パフォーマンスと文字列フォーマットの両方に関心がある場合は、 Matthew WilsonのFastFormat ライブラリをご覧ください。
編集-そのライブラリのaccu出版物へのリンク: http://accu.org/index.php/journals/1539
はい、iostreamはcstdioよりも低速です。
はい、C++で開発している場合は、おそらくcstdioを使用しないでください。
とはいえ、フォーマット、タイプセーフティ、何とか、何とか、何とかを気にしない場合は、scanfよりも高速なI/O取得方法があります...
たとえば、これはSTDINから数値を取得するカスタムルーチンです。
inline int get_number()
{
int c;
int n = 0;
while ((c = getchar_unlocked()) >= '0' && c <= '9')
{
// n = 10 * n + (c - '0');
n = (n << 3) + ( n << 1 ) + c - '0';
}
return n;
}
FILE *をC++ streambufとして実装し、fprintfをランタイム形式パーサーとして実装するstdio実装( libio )があります。 IOstreamはランタイム形式の解析を必要としません。それはすべてコンパイル時に行われます。そのため、バックエンドが共有されているため、実行時にiostreamが高速になると期待するのは合理的です。
問題は、cin
がscanf()
呼び出しの上に抽象化レイヤーを提供するため、多くのオーバーヘッドが伴うことです。 cin
が必要なため、C++ソフトウェアを作成している場合は、cin
よりもscanf()
を使用しないでください。パフォーマンスが必要な場合、おそらくC++でI/Oを記述することはないでしょう。
一般的に使用されるステートメントcin
およびcout
は、C++のscanf
およびprintf
よりも遅いように見えますが、実際にはより高速です!
問題は、C++では、cin
とcout
を使用するときは常に、scanf
とcin
をプログラムで使用すると、両者は互いに同期して動作します。この同期プロセスには時間がかかります。したがって、cin
およびcout
は遅くなるように見えます。
ただし、同期プロセスが発生しないように設定されている場合、cin
はscanf
よりも高速です。
同期プロセスをスキップするには、プログラムのmain()
の先頭に次のコードスニペットを含めます。
std::ios::sync_with_stdio(false);
詳細については、 このサイト をご覧ください。
#include <stdio.h>
#include <unistd.h>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
static int scanuint(unsigned int* x)
{
char c;
*x = 0;
do
{
c = getchar_unlocked();
if (unlikely(c==EOF)) return 1;
} while(c<'0' || c>'9');
do
{
//*x = (*x<<3)+(*x<<1) + c - '0';
*x = 10 * (*x) + c - '0';
c = getchar_unlocked();
if (unlikely(c==EOF)) return 1;
} while ((c>='0' && c<='9'));
return 0;
}
int main(int argc, char **argv) {
int parity = 0;
unsigned int x;
while (1 != (scanuint(&x))) {
parity ^= x;
}
parity ^=x;
printf("%d\n", parity);
return 0;
}
ファイルの最後にバグがありますが、このCコードは高速のC++バージョンよりも劇的に高速です。
paradox@scorpion 3845568-78602a3f95902f3f3ac63b6beecaa9719e28a6d6 ▶ make test
time ./xor-c < Rand.txt
360589110
real 0m11,336s
user 0m11,157s
sys 0m0,179s
time ./xor2-c < Rand.txt
360589110
real 0m2,104s
user 0m1,959s
sys 0m0,144s
time ./xor-cpp < Rand.txt
360589110
real 0m29,948s
user 0m29,809s
sys 0m0,140s
time ./xor-cpp-noflush < Rand.txt
360589110
real 0m7,604s
user 0m7,480s
sys 0m0,123s
元のC++は30秒かかり、Cコードは2秒かかりました。