【问题标题】:Optimizing the computation of a recursive sequence优化递归序列的计算
【发布时间】:2010-12-01 12:21:14
【问题描述】:

在 R 中计算递归序列的最快方法是什么,定义为

x[1] <- x1 
x[n] <- f(x[n-1])

我假设适当长度的向量 x 是预先分配的。有没有比循环更聪明的方法?

变体:将其扩展到向量:

 x[,1] <- x1 
 x[,n] <- f(x[,n-1])

【问题讨论】:

  • f(x) 可以表达为 cumsum()'s, cumprod()'s 的组合吗?
  • 几个 cmets:i) 在这里迭代而不是递归并不能节省很多时间; ii)似乎加速事情的唯一方法是编写C代码,也许是内联的。我希望有一个包可以以一种富有表现力的方式为我完成这项工作。不是这样的。
  • 是 f() 非常慢还是 n 非常大的问题?如果是后一种情况,您可能可以在 R 中进行改进,但是,如果是前一种情况,在 C 中重写 f() 可能是必要的......

标签: algorithm r recursion


【解决方案1】:

如果您需要整个序列,它的速度有多快?假设函数是 O(1),你不能比 O(n) 做得更好,循环就会给你。

【讨论】:

  • 更糟糕的是,如果您在每次修改部分对象时都替换整个对象,有时会在 R 中得到 O(n^2)。我认为最初的问题是关于避免这个问题......
【解决方案2】:

一般来说,语法 x$y [[<- 不会每次都重新分配整个列表。所以我认为你可以合理有效地做到:

x[[1]] <- x1 
for (m in seq(2, n))
    x[[m]] <- f(x[[m-1]])

这里唯一浪费的方面是您必须为 for 循环生成一个长度为 n-1 的数组,这并不理想,但这可能不是一个大问题。如果您愿意,可以用 while 循环替换它。通常的矢量化技巧(lapply 等)在这里不起作用...

(双括号为您提供了一个列表元素,这可能是您想要的,而不是单例列表。)

有关详细信息,请参阅《钱伯斯》(2008 年)。数据分析软件。页。 473-474。

【讨论】:

    【解决方案3】:

    您可以考虑用 C / C++ / Fortran 编写它,并使用方便的 inline 包为您处理编译、链接和加载。

    当然,如果你的函数 f() 需要保持为 R 函数,它可能是一个真正的约束。 Rcpp 中有一个从 C++ 到 R 的回调示例,但这需要比仅使用内联更多的工作。

    【讨论】:

    • Dirk,可以将 R 函数指针传递给 C 吗?我没想到。
    • 是的,我刚刚在 Rcpp 源代码中再次查看了它。在我需要重新组织的文档中有点混乱——一旦加载了 Rcpp,请查看“example(RcppExample)”中示例的结尾,以及 src/RcppExample.cpp 和 Rcpp.h 中的相应代码和rcpp.cpp。不是微不足道的,而是可行的。作为计时练习会很好。
    【解决方案4】:

    关于这是否可以以任何方式完全“矢量化”的问题,我认为答案可能是“不”。数组编程背后的基本思想是操作同时应用于整组值。同样对于“令人尴尬的并行”计算的问题。在这种情况下,由于您的递归算法取决于每个先前的状态,因此无法从并行处理中获得速度:它必须串行运行。

    话虽如此,加快程序速度的常用建议仍然适用。例如,尽可能多地在递归函数之外进行计算。对一切进行排序。预定义您的数组长度,以便它们在循环期间不必增长。等等See this question for a similar discussionTim Hesterberg's article on efficient S-Plus Programming中还有一个伪代码示例。

    【讨论】:

      【解决方案5】:

      解决递归关系;)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多