【问题标题】:Python Rpy R data processing optimizationPython Rpy R 数据处理优化
【发布时间】:2010-07-14 01:00:41
【问题描述】:

我正在用 Python 和 R 编写一个与 Rpy2 桥接的数据处理程序。

输入数据是二进制的,我使用 Python 读取数据并将它们传递给 R,然后收集结果输出。

数据被组织成片段,每个片段大约 100 个字节(每个值 1 个字节 * 100 个值)。

他们现在才工作,但速度非常低。以下是我对 1GB 大小(即 10^7 条)数据的一些测试:

如果我禁用 Rpy2 调用以进行空运行,Python 大约需要 90 分钟才能使用一个单线程在 Intel(R) Xeon(TM) CPU 3.06GHz 上循环完成。

如果我在 Xeon 双核上启用全部功能和多线程,(估计)程序需要大约 200 小时才能完成。

我多次杀死Python程序调用堆栈几乎总是指向Rpy2函数接口。我也做了分析,得到了类似的结果。

所有这些观察表明 Rpy2 调用的 R 部分是瓶颈。所以我分析了我的 R 程序的独立版本,但分析摘要指向“匿名”。我仍在努力查看我的 R 脚本的哪一部分是最耗时的。 ****已更新,请参阅下面的编辑*****

有两个可疑的候选通过,一个是使用 cran[1] 的 wmtsa 的连续小波变换 (CWT) 和小波变换模最大值 (WTMM),另一个是前高斯曲线的非线性拟合。

我想到的是:

  1. 为了拟合,我可以用内联 C 代码代替 R 路由吗? C 和 fortran 中有很多合适的库可用......(来自网络的想法;我从来没有这样做过;不确定)

  2. 对于小波算法....我将不得不分析 wmtsa 包以重写 C 中的热点? .... 使用 C 或 fortran 重新实现整个 wmtsa 包对我来说非常重要。我没有太多编程经验。

  3. 文件中的数据以 20 个连续字节组织,我可以直接映射到类似 C 的 char* 数组吗?目前我的 Python 程序一次只读取一个字节并将其附加到一个列表中,这很慢。这部分代码需要 1.5 小时,而 R 需要约 200 小时,所以没有那么紧急。

这是我第一次在解决实际问题时遇到程序效率。我对这些信息感到不知所措。请给我一些关于下一步做什么和如何做的建议。

干杯!

脚注:

  1. http://cran.r-project.org/web/packages/wmtsa/index.html

* 更新 *

感谢 cran 的 proftools,我设法创建了一个调用堆栈图。我可以看到大约 56% 的时间都花在了 wmtsa 上,代码 sn-p 是这样的:

W <- wavCWT(s,wavelet="gaussian1",variance=1/p) # 1/4
W.tree <-wavCWTTree(W) # 1/2
holderSpectrum(W.tree) # 1/4

~28% 的时间花在 nls 上:

nls(y ~ Q * dexGAUS(x, m, abs(s), abs(n)) + B, start = list(Q = 1000, m = h$time[i], s = 3, n = 8, B = 0), algorithm="default", trace=FALSE)

从 gamlss.dist 包中评估 dexGAUS 需要花费大部分时间。

剩余约 10% 的 R 时间用于数据传递/拆分/聚合/子集。

【问题讨论】:

  • 您需要提供更多详细信息,也许是您认为是 R 代码可疑区域的 sn-ps。在这一点上,您的问题有太多可能的解决方案。但有一件事是,你可能不得不接受你正在做的事情需要一段时间。例如,选项 1,即拟合,通常(同样,细节不够)在 R 中进行了高度优化。其他方式不太可能更快。
  • 非常感谢约翰。我已经更新了我的帖子。请看一下:P
  • 看看你有什么......这只是需要很长时间。如果有地方可以加速你的 R,你可能想看看burns-stat.com/pages/Tutor/R_inferno.pdf
  • 约翰,你的意思是没有一点加速空间?我检查了小波函数,它们已经用 C 实现了。顺便说一句,那是一本好书。
  • 如果你的 R 调用不是多次调用,并且以独立的方式(在这种情况下你可以考虑一个简单的并行化),你确实剩下: - 研究算法并尝试优化它们(我认为 dexGAUS 占用了 28% 的大部分运行时间有点令人担忧 - 你是从循环内部调用它,不是吗?) - 改变方法

标签: python r rpy2


【解决方案1】:

对于选项 3.. 有效地获取您的数据...在 python 中将其全部读取为一个 long str 类型,并从文件中读取一次。假设它被称为 myStr。

import array
myNums = array.array('B', myStr)

现在 myNums 是一个易于转换的每个字节的数组...参见 help(array.array)... 事实上,看起来您可以通过数组直接从文件中获取它。

这应该可以省去 1.4 小时的数据读取时间。

【讨论】:

  • 然后当我更仔细地阅读你的问题时,看起来你并没有要求 python 做任何无法在 R 中完全完成的事情。那么,为什么要使用 python 代码呢?
  • 我只是不知道在R中处理高度自定义的数据。我在数据文件的描述区域使用python进行词法分析。
【解决方案2】:

我的理解是你有:

  • 在某些地方使用 rpy2 的 python 代码

  • 可追溯到对 rpy2 的调用的性能问题

  • 性能问题目前似乎与 rpy2 本身没有太大关系,因为底层 R 主要负责运行时间

  • 您的 R 代码的一部分是一次读取一个字节并将它们附加到一个列表中,您通过将该部分移至 Python 来改进它

在没有看到实际代码的情况下尝试提供帮助有点困难,您可能需要考虑:

  • 读取字节的缓冲策略(John 已经回答了这个问题)。

  • 优化您的 R 代码

  • 考虑微不足道的并行化(并最终租用云上的计算空间)

【讨论】:

  • 嗨 lgautier,你的理解是正确的,除了第四点:我用 Python 从二进制文件中读取数据,然后通过 Rpy 将它们传递给 R。该读取策略是逐字节的,并未优化。我使用了琐碎的并行化,所消耗的时间仍然无法接受。我的帖子中有一些关于分析 R 代码的更新。请看一下:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 2021-07-14
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
相关资源
最近更新 更多