亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 rpy2 庫,R 中的 For 循環比 Python 中的循環快幾倍

使用 rpy2 庫,R 中的 For 循環比 Python 中的循環快幾倍

慕姐8265434 2023-03-16 16:09:06
以下簡單的for塊大約需要 ~3 秒才能完成R:library(MASS)nruns <- 2000nelems <- 50maxX <- 1maxY <- 1for(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通過庫在 Python 中運行相同的代碼需要 4-5 倍的時間:from rpy2.robjects import rfrom rpy2.robjects.packages import importrimportr('MASS')nruns = 2000r.assign('nelems', 50)r.assign('maxX', 1)r.assign('maxY', 1)for _ in range(nruns):    r('dataX <- runif(nelems, 0, maxX)')    r('dataY <- runif(nelems, 0, maxY)')    r('kde2dmap <- kde2d(dataX, dataY, n=50, lims=c(0, maxX, 0, maxY))')這僅僅是因為我正在使用rpy2圖書館進行交流R還是有其他原因在起作用?這可以以任何方式改進嗎(同時仍然在 Python 中運行代碼)?
查看完整描述

2 回答

?
慕娘9325324

TA貢獻1783條經驗 獲得超4個贊

慢 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) )

}

""")

速度改進將來自以下方面:


您問題中的代碼在每次迭代中傳遞 Python 字符串。每次在評估該字符串之前都必須(通過 R)對其進行解析。這可能會增加一些長循環的開銷。在我提供的代碼中,解析只執行一次。


importr()@Parfait 答案中的代碼利用了為要使用的 R 函數創建 Python 對象代理這一事實。但是,在創建映射時(為 R 包中的所有importr()對象創建映射)以及從 Python 到 R 的每次迭代(對象檢查和轉換、構建要評估的 R 表達式)時,仍然存在開銷。對代碼進行概要分析可以讓您準確了解時間花在了哪里。有一些方法可以在保留更多性能的同時保留一些 pythonic 方面。例如:


 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)

關于性能的另一個評論是,rpy2 從 C 擴展到的過渡cffi導致使用 R 的 C API 管理對話的代碼結構有了顯著改進(并修復了許多棘手的錯誤),但代價是暫時的在這里和那里的表現。正在逐步重新引入速度優化。


查看完整回答
反對 回復 2023-03-16
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

自然地,連接到外部語言 API 比直接運行外部語言要慢。但是,請考慮將所有內容都保留在 Python 層中并避免r()調用。


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))


查看完整回答
反對 回復 2023-03-16
  • 2 回答
  • 0 關注
  • 138 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號