【问题标题】:Is there a good way to access information outside of a function?有没有一种访问函数外部信息的好方法?
【发布时间】:2021-10-10 23:44:35
【问题描述】:

目前,我正在使用 C++ 开发一个递归函数,该函数需要传递一个大数组和几个常量变量。这是递归的结构:

void recurse_objects(std::vector<Object> &objects, int i, int j, double merge_distance, double size_enclosure, double timestep){

    //operations performed

    //recursion performed
    if(j+1 < objects.size()){
        recurse_objects(objects, i, j+1, merge_distance, size_enclosure, timestep);
    }else if(i+2 < objects.size()){
        recurse_objects(objects, i+1, i+2, merge_distance, size_enclosure, timestep);
    }

    //more operations performed
}

该函数通过每个唯一的对象对 (i, j) 递归。问题是,在我正在处理的对象数量(500-2000 个对象)中,由于堆栈填满,函数分段错误 - 它适用于 350 个以下的对象。

感觉如果我可以将数组和常量变量存储在其他地方,我可以节省空间并能够在最后几个对象上运行计算。这个问题有一个通用的解决方法吗?我唯一能想到的是使用全局变量——这是不可行的,因为值是由系统输入决定的,批处理,这会完全降低效率,或者只是将程序更改为非递归程序。

【问题讨论】:

  • 矢量引用中的对象已经存储在别处。加倍如此。首先是因为向量使用动态内存,其次是因为只有一个向量,其引用是递归传递的。
  • 而真正的解决方案是使用迭代解决方案而不是递归解决方案
  • 我的经验表明,递归函数的调用深度应与 O(log n) 最大值成正比。像分治或树遍历算法。如果深度在O(n),很容易发生栈溢出,但算法一般可以转化为循环。
  • 听起来我将不得不使用迭代 - 这个项目的目标是缓存优化,这是我想尝试递归的唯一原因(除了看起来更干净)。谢谢大家

标签: c++ recursion optimization


【解决方案1】:

如果您的编译器没有执行尾调用优化,运行时间过长的递归函数总是会导致堆栈溢出。减少存储在每个堆栈帧中的内存量会延迟这一不可避免的情况,并让您在更大的数据集上运行它,但它们不会解决问题,因为即使是 堆栈帧也会加起来。

您的函数似乎已经开始进行尾递归,如果在递归调用之后没有更多操作。

如果您可以在递归调用之后摆脱那些,这很可能归结为您发送编译器进行优化的标志。

【讨论】:

  • @Richard 真的吗?我认为尾递归优化的要点是,如果您的唯一递归点是return nextRecusriveCall(...);,那么您可以将当前堆栈帧重用于nextRecursiveCall。如果当前调用在nextRecursiveCall 返回后还有更多操作要做,我不知道会发生这种情况。
  • @Nathan 我的错。我将这些调用解释为在功能上等同于 return 给定的 void,但你是对的,它们不需要。
  • 这两个计算都是必要的:首先计算所有加速度,然后计算速度之后的操作。我不得不拆分递归。可能会使用迭代。
猜你喜欢
  • 1970-01-01
  • 2013-11-04
  • 2012-09-07
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 2012-08-08
相关资源
最近更新 更多