OI各整数读入方式速度比较

Coast23

某天, 我突然对OI常用的整数读入方式的速度感到好奇, 于是决定写个程序测试一下.

测试的读入方式有:

1. scanf
2. 快读(read)
3. 快读(fread)
4. cin
5. cin.tie(0)后的cin
6. 取消流同步后的cin

测试程序

char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#include <bits/stdc++.h>
using namespace std;
using namespace chrono;

int x;
int N = 20000000; // 测试数据量, 这里是2e7

int read() {
int x = 0, f = 1; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) f ^= (ch == '-');
for(; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch xor 48);
return f ? x : -x;
}

void gen(int n){
srand(time(0));
FILE *fp = fopen("test.in", "w");
for(int i = 0; i < n; ++i){
int opt = rand() % 2;
if(opt) fprintf(fp, "%d ", rand());
else fprintf(fp, "%d ", -rand());
}
fclose(fp);
}

void test_read(int n){while(n--) x = read();}
void test_scanf(int n){while(n--) scanf("%d", &x);}
void test_cin(int n){while(n--) cin >> x;}

int main(){
#pragma region 预生成随机数
gen(N);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试scanf
freopen("test.in", "r", stdin);
auto start = high_resolution_clock::now();
test_scanf(N);
auto end = high_resolution_clock::now();
printf("scanf: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试read
#undef getchar
freopen("test.in", "r", stdin);
start = high_resolution_clock::now();
test_read(N);
end = high_resolution_clock::now();
printf("read function: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试fread
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
freopen("test.in", "r", stdin);
start = high_resolution_clock::now();
test_read(N);
end = high_resolution_clock::now();
printf("fread function: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#undef getchar
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试cin
freopen("test.in", "r", stdin);
start = high_resolution_clock::now();
test_cin(N);
end = high_resolution_clock::now();
printf("cin: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试untied cin
freopen("test.in", "r", stdin);
ios::sync_with_stdio(true);
cin.tie(nullptr);
start = high_resolution_clock::now();
test_cin(N);
end = high_resolution_clock::now();
printf("untied cin: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试unsync cin
freopen("test.in", "r", stdin);
ios::sync_with_stdio(false);
start = high_resolution_clock::now();
test_cin(N);
end = high_resolution_clock::now();
printf("unsync cin: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
////////////////////////////////////////////////////////////////////////
#pragma region 测试fastest cin
freopen("test.in", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(nullptr);
start = high_resolution_clock::now();
test_cin(N);
end = high_resolution_clock::now();
printf("fastest cin: %d ms\n", duration_cast<milliseconds>(end - start).count());
fclose(stdin);
#pragma endregion
return 0;
}

Windows11 MinGW-W64测试结果

测试环境

CPU: Intel(R) Core(TM) i9-14900HX 2.20 GHz

RAM: 32 GB

编译器信息:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=C:/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-win32-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=win32 --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-win32-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-win32-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-win32-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-win32-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-win32-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: win32
gcc version 8.1.0 (x86_64-win32-seh-rev0, Built by MinGW-W64 project)
排名读入方式用时
1fastest cin1707ms
2unsync cin1763ms
3fread1909ms
4read1985ms
5scanf5214ms
6cin11080ms
7untied cin11425ms

ArchLinux GCC测试结果

测试环境

CPU: Intel(R) Core(TM) i5-7300U 3.50 GHz
RAM: 8 GB

编译器信息:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.1 20240910 (GCC)
排名读入方式用时
1read1516ms
2fread1592ms
3fastest cin2480ms
4unsync cin2485ms
5scanf2800ms
6untied cin8662ms
7cin9098ms

总结

Windows MinGW-W64下, 读入速度 关闭流同步cin > fread ≈ read > scanf > cin.

ArchLinux GCC下, 读入速度 read ≈ fread > 关闭流同步cin > scanf > cin.

  • 标题: OI各整数读入方式速度比较
  • 作者: Coast23
  • 创建于 : 2025-01-24 23:28:33
  • 更新于 : 2025-03-31 17:38:37
  • 链接: https://coast23.github.io/2025/01/24/OI各整数读入方式速度比较/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论