Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/71.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
在R中,For循环的速度是使用rpy2库的Python中的几倍_Python_R_Performance_Rpy2 - Fatal编程技术网

在R中,For循环的速度是使用rpy2库的Python中的几倍

在R中,For循环的速度是使用rpy2库的Python中的几倍,python,r,performance,rpy2,Python,R,Performance,Rpy2,以下简单的for块在R中完成大约需要3秒: library(MASS) nruns <- 2000 nelems <- 50 maxX <- 1 maxY <- 1 for(i in 1:nruns) { dataX <- runif(nelems, 0, maxX) dataY <- runif(nelems, 0, maxY) kde2d(dataX, dataY, n=50, lims=c(0, maxX, 0, maxY) )

以下简单的
for
块在
R
中完成大约需要3秒:

library(MASS)
nruns <- 2000
nelems <- 50
maxX <- 1
maxY <- 1
for(i in 1:nruns) {
    dataX <- runif(nelems, 0, maxX)
    dataY <- runif(nelems, 0, maxY)
    kde2d(dataX, dataY, n=50, lims=c(0, maxX, 0, maxY) )
}

这仅仅是因为我正在使用
rpy2
库与
R
进行通信,还是有其他原因在起作用?这能以任何方式得到改进吗(同时仍然在Python中运行代码)?

当然,连接到外部语言API会比直接运行外部语言慢。但是,请考虑将所有的东西保存在Python层中,避免<代码> r()>代码>调用。< /P>
from rpy2.robjects.packages import importr

base = importr("base")
stats = importr("stats")
mass = importr("MASS")

nruns = 2000
nelems = 50
maxX = 1
maxY =  1

for _ in range(nruns):
    dataX = stats.runif(nelems, 0, maxX)
    dataY = stats.runif(nelems, 0, maxY)
    kde2dmap = mass.kde2d(dataX, dataY, n=50, lims=base.c(0, maxX, 0, maxY))

4到5倍的速度似乎有点慢,但如果您使用自定义转换,则可能会出现这种情况(rpy2可以动态地将R对象转换为任意Python对象-请参阅文档)

或者,您可能是在HPC上,对于安装Python和包的位置,NFS访问速度较慢,而R在更快的本地磁盘上(这可能会对启动时间产生很大影响)

否则,也可以将循环保持在R中,以评估这是否会改变运行时间:

from rpy2.robjects import r
from rpy2.robjects.packages import importr

# importr('MASS')
# Calling 'importr' will perform quite a bit of work behind the
# scene. That works allows a more intuitive/pythonic use of the
# content of the R library "MASS", but if you are just passing
# a string to be evaluated for R evaluation you can skip it
# replace it with the following:
r('library("MASS")')

nruns = 2000
r.assign('nelems', 50)
r.assign('maxX', 1)
r.assign('maxY', 1)
r.assign('nruns', nruns)
r("""
for(i in 1:nruns) {
  dataX <- runif(nelems, 0, maxX)
  dataY <- runif(nelems, 0, maxY)
  kde2dmap <- kde2d(dataX, dataY, n=50, lims=c(0, maxX, 0, maxY) )
}
""")

关于性能的另一个评论是,rpy2从C扩展到
cffi
的转换导致了使用R的C API管理对话框的代码结构的显著改进(以及修复的一些棘手的错误),但在这里和那里的性能上有暂时的损失。速度优化正在逐步重新引入。

我不知道你能做到这一点。这比完整的
R
实现稍微慢一点。非常感谢。很高兴听到。没问题。如果不需要Python对象传递到R,请考虑调用<代码>子进程< /C>来直接运行R脚本。哇,这比PARFIT的答案快很多。他们的代码执行
importr()
行大约需要6.5秒,执行循环大约需要7.5秒。你的答案需要大约4秒的时间。这是怎么回事?为什么这么快?(哦,谢谢!)在R中调用
importr()
应该比调用
library()
要花更多的时间。我在回答中添加了一个关于这一点的注释。当然,@Gabriel,因为lgautier是
rpy2
。也许在未来的
rpy2
版本中,R方法可以隐式转换作为参数发送的Python类型(int->IntVector,float->FloatVector)而且
importr
可以简化包的映射?@Parfait:
rpy2
已经能够自动将
int
float
类型的Python标量转换为R长度的一个向量。然而,在这个关于优化的示例中,
maxX
maxY
nelems
在循环期间是恒定的。为所有迭代创建一次相应的R向量将节省一点额外的时间。回答得很好,非常感谢你们两位!
from rpy2.robjects import r
from rpy2.robjects.packages import importr

# importr('MASS')
# Calling 'importr' will perform quite a bit of work behind the
# scene. That works allows a more intuitive/pythonic use of the
# content of the R library "MASS", but if you are just passing
# a string to be evaluated for R evaluation you can skip it
# replace it with the following:
r('library("MASS")')

nruns = 2000
r.assign('nelems', 50)
r.assign('maxX', 1)
r.assign('maxY', 1)
r.assign('nruns', nruns)
r("""
for(i in 1:nruns) {
  dataX <- runif(nelems, 0, maxX)
  dataY <- runif(nelems, 0, maxY)
  kde2dmap <- kde2d(dataX, dataY, n=50, lims=c(0, maxX, 0, maxY) )
}
""")
 import rpy2.rinterface as ri
 ri.initr()
 ri.baseenv['library']("MASS")
 # early bindings for R functions:
 runif = ri.globalenv.find('runif')
 kde2d = ri.globalenv.find('kde2d')
 # create constant values in loop as R objects
 maxX = ri.IntVector((1, ))
 maxY = ri.IntVector((1, ))
 nelems = ri.IntVector((50, ))
 zero = ri.IntVector((0, ))
 limits = ri.IntVector((0, maxX[0], 0, maxY[0]))
 for i in range(nruns):
     dataX = runif(nelems, zero, maxX)
     dataY = runif(nelems, zero, maxY)
     kde2dmap = kde2d(dataX, dataY, n=nelems, lims=limits)