Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 递归、堆栈和缓存未命中_C++_Caching_Memory - Fatal编程技术网

C++ 递归、堆栈和缓存未命中

C++ 递归、堆栈和缓存未命中,c++,caching,memory,C++,Caching,Memory,想象一下我需要穿过一棵树。据我所知,如果以递归方式进行,则每个递归函数调用都需要将其局部参数保存在堆栈帧中。堆栈帧驻留在堆栈内存中,每个帧由堆栈指针指向 堆栈内存何时加载到CPU缓存中?每次函数返回时?例如,如果我做了很多递归函数调用,它会“垃圾”我的CPU缓存吗 在遍历树的过程中,递归地完成一些更容易的事情(因为函数所处理的数据结构受到限制),我是否会因为堆栈本身而遭受大量缓存未命中 目标是在遍历树时尽量减少缓存未命中。可能堆栈没有完全加载到缓存中,而是只加载所需的缓存线。处理器不知道哪个内存

想象一下我需要穿过一棵树。据我所知,如果以递归方式进行,则每个递归函数调用都需要将其局部参数保存在堆栈帧中。堆栈帧驻留在堆栈内存中,每个帧由堆栈指针指向

堆栈内存何时加载到CPU缓存中?每次函数返回时?例如,如果我做了很多递归函数调用,它会“垃圾”我的CPU缓存吗

在遍历树的过程中,递归地完成一些更容易的事情(因为函数所处理的数据结构受到限制),我是否会因为堆栈本身而遭受大量缓存未命中


目标是在遍历树时尽量减少缓存未命中。

可能堆栈没有完全加载到缓存中,而是只加载所需的缓存线。处理器不知道哪个内存属于堆栈,它只看到内存地址和缓存线

所以它不会破坏你的缓存。很难做出准确的预测。特别是如果你使用非平凡的析构函数

如果使用,编译器将优化代码,在某些情况下,当递归调用完成时,堆栈将被删除,因此始终只存储一个堆栈


一些智者说:抢占式优化是万恶之源。

可能堆栈没有完全加载到缓存中,而是只加载所需的缓存线。处理器不知道哪个内存属于堆栈,它只看到内存地址和缓存线

所以它不会破坏你的缓存。很难做出准确的预测。特别是如果你使用非平凡的析构函数

如果使用,编译器将优化代码,在某些情况下,当递归调用完成时,堆栈将被删除,因此始终只存储一个堆栈

一些智者说:先发制人的优化是万恶之源。

(是的,是的,我知道。TLDR;)

在我曾经工作过的PPC上(我想是860),有两个 缓存、数据和代码。(我想它们不在CPU中,但我 假设他们住在哪里并不重要。)

对于函数调用,特定的GCC编译器(您的编译器 结果可能会有所不同)生成的代码

a) 将函数参数推送到被调用函数的堆栈上(即参数加载)

然后

b) “操纵”堆栈(指针,通常是cpu寄存器)到 为所有外部自动范围建立空间 变量(堆栈变量)。(通常只需添加一个简单的 堆栈指针的字节计数。)

注意:这两个步骤都是在进入 函数/方法代码

按下函数参数将导致某些数据缓存被删除 标记为“触碰”(或者它仍然被称为脏的?),但多久 实际到达堆栈内存的触摸数据取决于 硬件缓存处理程序

函数/方法“entry”(跳转到新pc位置)没有 无需初始化自动变量,这是 程序员的责任。因此,数据缓存不受影响 为了他们


堆栈内存何时加载到CPU缓存中

修改堆栈数据项时。涉及数据缓存 当代码将数据写入堆栈时

每次函数返回时

没有

每个递归函数调用都需要保存其本地 堆栈帧中的参数

我认为函数调用序列比自动调用序列更重要 在函数开始运行之前,变量已安装在堆栈内存位置,位于从堆栈指针开始的编译器计算的固定偏移量处。因此,当递归(或调用任何其他函数)时,“本地”参数已经在堆栈中,因此已经“保存”。在函数调用(或返回)中不会有额外的另存为一部分

也许您混淆了“函数调用”和“上下文” 开关“?(其中cpu寄存器也必须向ram推出) 函数调用比上下文调用快2到3个数量级 由于此sudo“寄存器交换”和其他操作系统操作而切换

例如,如果我正在进行大量递归函数调用, 它会“垃圾”我的CPU缓存吗

不知道你说的“垃圾箱”是什么意思。(另请参见我下面的最后一段)我猜您正在考虑缓存块大小和潜在触发 以某种方式写入额外的缓存块。既然你提到 递归,也许你担心递归算法会 更容易发生这样的事情

缓存复杂性和缓存块大小的多样性意味着 方法是测试

然而,对我来说,这样的担忧有点像是预先成熟的优化。 如果递归足够快,如果它满足要求,为什么 你能调查一下吗

作为一个例子,我有一些使用递归方法的代码 比循环实现更快(以及 可读)。当您可以实现尾部递归时,您不需要这样做 麻烦手动重新编码并重新测试。“-O3”优化已经完成 完全删除堆栈使用。(易于测试。)

在穿越树时,做一些事情要容易得多 递归地(由于数据结构的限制) 函数正在处理)我是否会遭受大量缓存 由于堆栈单独导致的未命中

就我个人而言,我喜欢递归。如果你的问题“更容易”解决 阅读并理解使用递归,而不是您应该使用它。我 最重视可读性。否则您将如何确定正确性


在我前面提到的嵌入式PPC上,我可以从命令行启用/禁用数据缓存和指令缓存

我希望指令缓存能够提供良好的性能提升, 我并没有失望

我对数据缓存的期望值较低,对此我感到非常惊讶 在震级上。我当时正在编写的代码 锂