输入速度测试

· · 个人记录

上次测试用的学校的旧电脑,硬盘成瓶颈了,今天重新测一次。

基本信息

测试环境

懒得搞 Linux,直接用的 Windows。

Windows 11 22H2 22621.2428
AMD Ryzen 7 4800H with Radeon Graphics   2.90 GHz
Dual Channel DDR4-3200 SDRAM (22-22-22-52 CR1)

硬盘跑分在下面(Ram Disk,随机有点寄,但是应该问题不大),几乎可以避免硬盘读写速度成为瓶颈。

运行的程序的时候,CPU 有负载的核心都把频率控制在 4.1 \text{GHz} 以上。

缓存全部开的 128 \text{MiB},经过测试,减小缓存会降低速度。

读取一般按行读取。

测试结果

参考数据:某些毒瘤题一个输入文件大小在 32 \text{MiB} 及以上,因此请避免在此类题目使用速度低于 64 \text{MiB/s} 的输入方式,下面划了及格线。

随机字母

文件包含随机生成的字母和换行符,每 128 \text{MiB} 的末位为 \n,其余位置为随机产生的小写英文字母,文件大小 4096 \text{MiB}

测试结果(按速度从快到慢排序):

  1. fread:用时 5.683 \text{s},平均速度 720.746 \text{MiB/s}
  2. ifstream:用时 15.995 \text{s},平均速度 256.08 \text{MiB/s}
  3. cin+ios::sync_with_stdio(false):用时 16.124 \text{s},平均速度 254.031 \text{MiB/s}
  4. fgets:用时 16.985 \text{s},平均速度 241.154 \text{MiB/s}
  1. getchar:用时 68.351 \text{s},平均速度 59.926 \text{MiB/s}
  2. scanf:用时 88.052 \text{s},平均速度 46.518 \text{MiB/s}
  3. cin:用时 216.278 \text{s},平均速度 18.9386 \text{MiB/s}

随机数字

文件包含随机生成但是长度固定的正整数,每 128 \text{MiB} 为一行,末位为 \n,包含 13421772[10^8,10^9) 的正整数和一个 [10^6,10^7) 的正整数,中间用空格隔开,为公平,要求完成对负数的处理。,文件大小 4096 \text{MiB}

测试结果(按速度从快到慢排序):

  1. fread:用时 6.647 \text{s},平均速度 616.218 \text{MiB/s}
  2. ifstream:用时 37.23 \text{s},平均速度 110.019 \text{MiB/s}
  3. cin+ios::sync_with_stdio(false):用时 39.26 \text{s},平均速度 104.33 \text{MiB/s}
  1. getchar:用时 73.058 \text{s},平均速度 56.065 \text{MiB/s}
  2. scanf:用时 223.737 \text{s},平均速度 18.3072 \text{MiB/s}
  3. cin:用时 414.642 \text{s},平均速度 9.8784 \text{MiB/s}

字符串采用类似以下的方式读入,求和用于检验结果:

    FILE *f=fopen("rand_letter.txt","r");
    while(true) {
        memset(buf,0,sizeof(buf));
        int res=fread(buf,1,SIZE,f);
        if(!buf[0]) break;
        for(int i=0;i<res;++i) if(buf[i]>='a'&&buf[i]<='z') sum+=buf[i];
    }
    clock_t end=clock();
    double dt=double(end)/double(CLOCKS_PER_SEC);
    cout<<sum<<endl;
    cout<<"time:"<<dt<<"s"<<"  speed:"<<4096./dt<<"MiB/s"<<endl;

快读采用以下实现,其中测试 getchar 时直接注释掉新定义的 getchar 函数。

namespace Read {
char *cur=buf+SIZE,*ed=buf+SIZE;
inline char getchar() {
    if(cur==ed) fread(buf,1,SIZE,f),cur=buf;
    return *(cur++);
}

template<typename T> inline void read(T &x) {
    char ch=getchar(); bool flag=false;
    while(ch<'0'||ch>'9') {
        if(ch=='-') flag=true;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    x=flag?-x:x;
}
}

整数读取采用类似以下的实现,求和用于检验结果:

    int T=13421773*32,tmp;
    while(T--) {
        cin>>tmp; sum+=tmp;
    }
    clock_t end=clock();
    double dt=double(end)/double(CLOCKS_PER_SEC);
    cout<<sum<<endl;
    cout<<"time:"<<dt<<"s"<<"  speed:"<<4096./dt<<"MiB/s"<<endl;