首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++,将数据结构从内存加载到缓存的延迟

C++,将数据结构从内存加载到缓存的延迟
EN

Stack Overflow用户
提问于 2011-02-20 05:51:20
回答 3查看 1.1K关注 0票数 1

我在C++中有以下函数

代码语言:javascript
复制
int readData ( Class1 *data)  
{    
//StartTime     
   try{  
       char *a1 = data->name1;  
       int a2 = data->age1;     

        char *b1 = data->name1;
        int b2 = data->age1; 
        .
        .
        . 
        char *e1 = data->name5;
        int e2 = data->age5;
   }
   catch(...)
   {
        return -1;
   } 
  //endTime
        return 0;
}

它遵循着一种模式

我第一次调用这个函数需要9-10微秒才能返回,第二次调用这个函数需要1-2微秒,第二次调用在第一次调用的500毫秒内完成

我第三次调用这个函数,它需要9-10微秒,因此第三次调用是在第三次调用后2 -3秒之后

你能告诉我为什么在2-3秒后调用会花费这么多时间吗?这个问题的解决方案是什么,使它总是需要1-2微米。

注意:我已经把标签从我测量时间的地方放到了那里。我使用的是cputicks,所以我确信时间配置文件是正确的。

谢谢,

Ila Agarwal

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-02-20 06:08:25

你们两次通话之间发生了什么?最明显的是,由于您在几秒钟内什么都没做,所以CPU L1、L2缓存中充满了其他数据。当您再次访问内存位置时,必须再次从主内存加载数据,这要慢得多。C++没有GC之类的东西,所以你和机器之间没有任何东西。仅操作系统和硬件。您应该检查当您的代码和数据已经进入页面文件之后,您在午餐后再次测量所需的时间。那么你的第一次调用就慢了1000多倍。

你的,阿洛伊斯·克劳斯

票数 0
EN

Stack Overflow用户

发布于 2011-02-20 06:06:04

仅从你的描述,我不能100%确定它实际上是与缓存相关的。这些是确定这一点的一些问题。

  • 您正在读取多少数据?
  • 数据布局是什么(即数据是如何在内存中分配的)?
  • 您的CPU是什么?
  • 您使用的是什么编译器/优化?
  • 是否有其他进程/线程在运行?
  • 您的应用程序正在使用多少内存,它是否有可能开始交换(使用的内存超过可用内存)
  • 您使用的是哪个操作系统?对于Linux,您可以使用PAPI读取CPU内部计数器,这些计数器会告诉您缓存未命中等信息。
  • 在第二次调用和第三次调用之间的2秒内发生了什么。

但现在让我们假设这是与缓存相关的,最初数据在主内存中。

第一次执行该函数时,中央处理器必须将其从存储器中提取到L2/L1 DCache。

现在,如果您再次“快速”调用该函数,则可以从CPU-Cache中检索数据,这比访问主存花费的时间要少得多。

在经过的两秒钟内,其他代码将运行,包括操作系统,其他代码将访问内存中的不同数据-这将覆盖先前存储在缓存中的数据。

因此,第三次执行将再次变慢。

然而,对我来说,填充缓存的10ms似乎很长,我怀疑内存访问模式非常糟糕,并且您没有有效地使用可用带宽来主存。优化代码以获得良好的缓存访问是一个复杂的主题。有许多技巧可以优化内存访问模式,其中大多数都是由编译器和CPU自己完成的。你可以控制的要点是,内存中的数据布局,内存访问模式/循环,编译器标志(和选择)。如果你提供更多关于你的代码的信息,我们也许能帮上忙。

票数 0
EN

Stack Overflow用户

发布于 2011-02-20 07:39:16

稍微复制了其他答案,但您所看到的是预期的:

  • 缓存未命中。两次命中的间隔越长,你的代码和/或数据就越有可能从L1、L2和L3 (如果你有)缓存中消失。
  • 在缓存的顶端,还有TLB未命中(内存管理单元)。这里通常有2-3层的间接层,这是一个巨大的延迟。
  • ,然后是DDR作为最后的手段,这是一个巨大的延迟,与CPU时钟相比。
  • 你可能已经开启了节能方案,这意味着当空闲2-3秒时,它将在唤醒后以更小的时钟运行一段时间。因此,您将在几个时间片中运行较慢的时间片。
  • DDR还具有积极的省电模式,这会导致空闲/休眠产生更多的周期损失。

如何解决这个问题?这非常困难:

  • TLB锁定。对硬件TLB进行编程,为将要命中的代码和数据保留条目。这会降低所有其他内容的TLB效率。
  • 缓存锁定。为代码和数据预留一个路径或条目。这会减少缓存的有效大小。
  • 不使用节能。这对所有其他用例都不好。

换句话说,不要这样做。你需要围绕最坏的情况进行设计,而不是试图让一切都变得最好。在现代操作系统上,你绝对不可能在x86上安排上面的内容。您可能需要付出一些努力才能使其在Linux的ARM上运行。但这并不是一个明智的方法。如果你真的需要微秒级的响应时间,你需要一个专用的硬件,或者只需要一个微型的(例如基于ARM的)来完成这个任务。如果这是一个多用户操作系统,你基本上没有保证,我甚至会很高兴得到10usec的延迟。另一方面,如果您实际上已经在micro上这样做了,那么一定要使用TLB/Cache锁定方法:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5053767

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档