作者Wush978 (拒看低质媒体)
看板R_Language
标题Re: [问题] 应用回圈於资料处理的效率
时间Tue Aug 4 22:26:37 2015
: 因此我的问题如下:
:
: (1) R 的回圈为何可以慢成这样? 我知道有研究过底层的高手理解来龙去脉,但对於
: 新手而言,有没有什麽简单的说法可以 give some insight?
:
: --
:
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.127.14.10
: ※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1438686610.A.4DE.html
: → Wush978: (1) R对记忆体的使用上比较没效率,所以用for写的演算法 08/04 19:52
: → Wush978: 很容易写出没有重复利用记忆体的写法,导致记忆体管理拖 08/04 19:53
: → Wush978: 累效能 08/04 19:53
: → celestialgod: 我看到的是要做很多直译动作而浪费掉时间~~~ 08/04 19:56
: → celestialgod: 简单说明就是有很多不必要的动作在回圈中被使用 08/04 19:57
: → celestialgod: 出处:http://tinyurl.com/a7l7zyb 08/04 19:58
我觉得这边有很多地方可以讨论。
首先,我觉得大部分的状况,直译带来的overhead是可以忍受的:
根据出处的例子,一个1e5的回圈跑0.37秒:
在我的电脑,1e7大概跑4 ~ 5秒左右。
```
system.time({
I = 0
while (I < 1e7) {
10
I = I + 1
}
})
```
在一般的状况下,这样的overhead应该是可接受的。
透过compiler套件,也可以简单改善直译带来的overhead
ps. 直译的意思是,把上述的R 程式码,转换成CPU的操作指令。
在C 等编译式语言,程式码会直接转换成CPU 的操作指令後才能执行。
R 、Python、PHP等直译式语言,则是在使用者按下Enter之後才转换
程式码成CPU 的操作指令,这样的动作会导致执行的效能比较慢。
而牵涉到记忆体操作的回圈,如:
```
x <- c()
system.time({
for(i in 1:1e5) {
x <- append(x, length(x))
}
})
```
才1e5次就要12秒,而且慢的幅度是以平方的规模成长,这类的效应很容易让你的执行
时间在回圈次数不大的状况下成长到数天或数星期。
最後给一个也是和记忆体相关的范例:
```
mat <- matrix(1, 100, 100)
tracemem(mat)
system.time({
for(i in 1:1e2) {
for(j in 1:1e2) {
mat[i,j] <- i + j
}
}
})
system.time({
for(i in 1:1e2) {
for(j in 1:1e2) {
tmp <- mat
tmp[i,j] <- i + j
}
}
})
```
这段程式码是一个显示copy on write导致R 复制矩阵的范例。
一开始tracemem函数是让R 告诉你说:「R 正在复制mat的内容」
第一个system.time有做write in place, 所以mat没有被复制,执行时间只有0.01秒
而第二个system.time在对tmp做操作时会触发copy on write,所以执行时间变成0.65秒
而这个变慢的速度和mat有关。
所以你可以想像当你处理很大的资料时,一些暂存物件
会很显着拖慢你的回圈!
就我个人的经验,
通常会让你的回圈跑到分钟以上,都是因为你的函数有牵涉到大量记忆体的存取。
另一个我这里没说明的,是演算法的复杂度。有时候我们会写出复杂度为O(n^2)以上的
R 函数而不自知,这除了去学一点演算法,以及了解R 如何配置记忆体之外,也没有帝
王之路了。
最後,我觉得celestialgod大大贴的连结,下面有人给的文章写的很好:
R Help Desk
How Can I Avoid This Loop or Make It Faster?
by Uwe Ligges and John Fox
<
https://www.r-project.org/doc/Rnews/Rnews_2008-1.pdf>
这两位作者都是R 界的大大,他们给出的看法也非常非常的中肯。
文中对於Loop的看法是:
Loops!
> Many comments about R state that using loops is a
> particularly bad idea. This is not necessarily true. In
> certain cases, it is difficult to write vectorized code,
> or vectorized code may consume a huge amount of
> memory. Also note that it is in many instances much
> better to solve a problem with a loop than to use re-
> cursive function calls.
里面许多对撰写Loop的建议都是很棒的。
细节就麻烦你去读原文了。
ps. 如果你有兴趣的话,很欢迎翻译或节录重点,贴回来本版。
R 版非常欢迎版友能在这里成长的同时,回馈你的经验给R 版。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.34.60.59
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1438698401.A.A59.html
※ 编辑: Wush978 (1.34.60.59), 08/04/2015 22:27:37
※ 编辑: Wush978 (1.34.60.59), 08/04/2015 22:28:14
1F:→ celestialgod: loops那篇在很多R速度的讨论可以看到 08/04 22:35
2F:→ celestialgod: 那篇的建议非常实用! 08/04 22:35
3F:→ cywhale: 实用推 以前避写loop 後来发现耗用大量记忆体真的没较快 08/05 09:02