【问题标题】:Is there a way not to use cache in c++有没有办法不在 C++ 中使用缓存
【发布时间】:2014-11-12 00:50:18
【问题描述】:

这个问题可能有点奇怪,但我想知道是否有办法在 c++ 中使用缓存。

我正在做一些测试,在这个测试中,我将2 GB (512*4 MB matrices) 加载到内存中,然后在它们之间做一些相关性并计算性能。

当我为第一次运行运行代码时,运行时间为t1+x second,在第二次运行中,总时间为t2+x seconds,其中t1t2 是2 GB 矩阵和t1 > t2 的加载时间。 (approx. t1=20, t2=5 sec)。我的假设是因为在第二次运行中使用了缓存。 (我不知道是否还有其他原因会减少这样的加载时间。)

我的问题是由于加载时间没有标准,因此在某些情况下结果具有欺骗性。所以我想要一个 IO 时间的标准。如果有办法,我唯一想到的就是不要使用缓存。

有没有办法标准化我的 IO 时间

我使用的是 Windows 7 x64 并在 Visual Studio 2010 上工作,我的 RAM 为 32 GB。

测试结果:我在 5 个选项中比较了 4MB 二进制文件的平均加载时间。 选项是第一次运行我的原始代码,第二次运行原始代码,使用 FILE_FLAG_NO_BUFFER,第一次运行使用缓存,第二次运行Roy Longbottom 建议。

1st run         : 39.1 ms  
2nd run         : 10.4 ms
no_buffer       : 127.8 ms
cache_1st run   : 27.4 ms
cache_2nd run   : 19.2 ms

我原来的阅读代码如下:

void readNoise(string fpath,Mat& data){
    FILE* fp = fopen(fpath.c_str(),"rb");
    if (!fp)perror("fopen");

    float* buffer= new float[size];
    for(int i=0;i<size;++i)   {
        fread(buffer,sizeof(float),size,fp);
        for(int j=0;j<size;++j){
            data.at<float>(i,j)=buffer[j];
        }
    }
    fclose(fp);
    free(buffer);
}

我注意到我的代码中有一个错误是进行动态分配,当我将动态分配更改为静态分配时,readNoise 方法的运行时间与Roy Longbottom 的缓存使用版本相同。

两次运行的差异减小了,但问题仍然存在:“如何标准化第一次和第二次运行的运行时间”?

【问题讨论】:

  • 当您说“缓存”时,您的意思是“文件系统缓存”吗?既然你提到了 I/O。
  • 假设你的意思是文件系统缓存,是的,可能有一种方法——但我知道的所有方法都是不可移植的,所以你需要告诉我们你是什么操作系统'在我们可以(可能)提供很多帮助之前重新合作。
  • 我想是的,我不知道缓存的细节。
  • 有时在性能检查时我会忽略第一次运行。
  • 既然如此,您可以使用CreateFile 打开文件,并指定FILE_FLAG_NO_BUFFERING,看看这是否至少有助于获得更一致的结果。您可以使用_open_osfhandle_fdopen 至少获得C 风格的FILE *,这样您就可以使用fread 之类的内容来阅读,而不是直接使用ReadFile

标签: c++ performance caching memory io


【解决方案1】:

基准测试,特别是微基准测试是一个非常复杂的场景,您可能会通过多种方式无意中收集到错误的性能数据。您应该查看诸如 google/benchmark 之类的微型基准测试库,并使用其中之一来执行您的测试。

从您的示例中可以看出,文件系统缓存等外部因素可能会导致单个运行的时间差异很大。

【讨论】:

  • 你能再解释一下you may inadvertently gather false performance data吗?
  • 我提到了 i/o 缓存,但这并不是唯一会导致问题的东西。甚至您的磁盘驱动器也有自己的缓存。不同的指令路径、乱序执行、推测执行等也可以在 cpu 内部进行。
  • 要考虑的一件事是延迟加载/实例化共享库。第一次运行可能涉及隐藏的基本初始化成本。编辑:也是惰性静态初始化。
  • 我认为第一次运行正常,因为 IO 速度是 100 MB/秒,第二次运行是 400 MBps,相当/超高。
【解决方案2】:

以下是我用于我的 Windows drivespeed32 基准测试的代码(免费的东西 - Google for drivespeed32),然后是通过 Windows 7 获得的 2000 MB 文件的结果以及较小文件的缓存速度。还显示了 Linux 版本的代码。

if (useCache)
{
    hFile = CreateFile(testFile, GENERIC_READ,
         FILE_SHARE_READ | FILE_SHARE_WRITE,
         NULL, OPEN_EXISTING,
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
}
else
{
    hFile = CreateFile(testFile, GENERIC_READ,
         FILE_SHARE_READ | FILE_SHARE_WRITE,
         NULL, OPEN_EXISTING,
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN
                            | FILE_FLAG_NO_BUFFERING, NULL);
}
if (hFile == INVALID_HANDLE_VALUE)
{
    SetCurrentDirectory(currentDir);
    printf (" Cannot open data file for reading\n\n");
    fprintf (outfile, " Cannot open data file for reading\n\n");
    fclose(outfile);
    printf(" Press Enter\n");
    g  = getchar();
    return 0;
}

 Intended for smaller files like 8, 16, 32 MB, so times out after 1 set.

 2000 MB File         1          2          3          4          5
 Writing MB/sec      85.51      85.40      85.64      83.79      83.19
 Reading MB/sec      84.34      85.77      85.60      85.88      85.15

 Running Time Too Long At 246 Seconds - No More File Sizes
 ---------------------------------------------------------------------
 8 MB Cached File      1          2          3          4          5
 Writing MB/sec    1650.43    1432.86    1536.61    1504.16    1481.58
 Reading MB/sec    2225.53    2361.99    2271.81    2235.04    2316.13


Linux Version

if (useCache)
{
      handle = open(testFile, O_RDONLY);
}
else
{
      handle = open(testFile, O_RDONLY | O_DIRECT);
}
if (handle == -1)
{
    printf (" Cannot open data file for reading\n\n");
    fprintf (outfile, " Cannot open data file for reading\n\n");
    fclose(outfile);
    printf(" Press Enter\n");
    g  = getchar();
    return 0;
}

【讨论】:

  • 我认为,我没有使用相同的缓存级别,因为在第二次运行中我的 io 速度变为 400 MB 左右,而第一次是 100 MB。
  • 第一次运行可能会将一些数据留在文件缓存中,但仍会从磁盘读取一些数据。我的缓存测试仅使用了 8 MB 的缓存,结果代表内存速度。
  • 你能看看我在问题中的测试结果吗?我做了一些测试并添加了结果
  • 我不确定您在做什么,但我认为从缓冲更改为无缓冲时,您不能多次读取同一个文件。缓冲时,它可能仍位于文件缓存中,未缓冲的读取请求可能会从那里读取它。其次,4 MB 不足以避免访问开销。在 4 MB 时,我的基准显示在 50 到 90 MB/秒(44-80 毫秒)之间。同样使用 FFNB,您需要以磁盘扇区大小倍数的块读取文件。我的基准测试使用 1048576 (2048 x 512) - 大块以获得最佳性能。
猜你喜欢
  • 2013-03-07
  • 1970-01-01
  • 2012-06-27
  • 2017-03-21
  • 2015-06-09
  • 2020-03-17
  • 2020-08-27
  • 2019-08-09
  • 1970-01-01
相关资源
最近更新 更多