作为玩具示例,假设我们有一个名为'my_func'的函数(代码在下面),它带有两个参数'n'和'p'.我们的函数'my_func'将生成一个带有'n'行和'p'列的随机矩阵'x',并在运行时和内存使用中做一些昂贵的事情,比如计算'x'的奇异值之和.(当然,这个功能是一个单行,但我在这里为了可读性而拍摄.)
my_func <- function(n, p) {
x <- replicate(p, rnorm(n))
sum(svd(x)$d)
}
Run Code Online (Sandbox Code Playgroud)
如果我们希望为'n'的几个值计算'my_func',并且对于'n'的每个值,我们有几个'p'值,然后向量化函数然后将组合应用到'my_func'是很简单的:
n <- 10 * seq_len(5)
p <- 100 * seq_len(10)
grid <- expand.grid(n = n, p = p)
my_func <- Vectorize(my_func)
set.seed(42)
do.call(my_func, grid)
[1] 98.61785 195.50822 292.21575 376.79186 468.13570 145.18359
[7] 280.67456 421.03196 557.87138 687.75040 168.42994 340.42452
[13] 509.65528 683.69883 851.29063 199.08474 400.25584 595.18311
[19] 784.21508 982.34591 220.73215 448.23698 669.02622 895.34184
[25] 1105.48817 242.52422 487.56694 735.67588 976.93840 1203.25949
Run Code Online (Sandbox Code Playgroud)
请注意,每次调用'my_func'对于大'n'和'p'来说都会非常缓慢(对于初学者来说,尝试n = 1000和p = 2000).
现在,在我使用类似构造函数的实际应用程序中,'grid'中的行数远大于此处给出的行数.因此,我试图更好地理解R中的矢量化.
第一个问题:在上面的例子中,是否按顺序执行对'my_func'的调用,以便在下一次调用之前对一次调用中的内存使用情况进行垃圾收集?我经常使用矢量化但从未停止过问这个问题.
第二个问题:(这个问题可能取决于第一)假设呼叫的数量足够大,并且"my_func,并将"足够慢,在这里并行保证?我假设是的.我真正的问题是:如果相反'my_func'为每次调用传递了相同的大矩阵,那么这里是否需要并行化?为了论证,假设矩阵称为'y',有1000行和5000列,并且是即时计算的.当然,将矩阵"y"传递给每个并行节点将导致一些滞后.
我理解第二个问题的答案可能是"这取决于......"如果是这种情况,请告诉我,我会尝试提供更多细节.
此外,我感谢任何建议,反馈或OMFG WTF N00B你还没有看到这个其他的相关的一些相关的讨论?? !!! 111oneone1
第一个问题的答案非常清楚是:R中的几乎所有内容都是默认的串行.(内部开始使用OpenMP的内容很少,但作为引擎的R可能仍然是单线程的).
所以对于第二个问题:是的,请尝试一下.我用Vectorize()得不多,但我喜欢这个*apply()家庭.解决它lapply(),然后加载多核软件包并使用mclapply()它来运行你所拥有的核心数量.这是一个例子:
R> system.time(res <- lapply(1:nrow(grid),
+ function(i) my_func(grid[i,1],grid[i,2])))
user system elapsed
0.470 0.000 0.459
R> system.time(res <- mclapply(1:nrow(grid),
+ function(i) my_func(grid[i,1], grid[i,2])))
user system elapsed
0.610 0.140 0.135
R>
Run Code Online (Sandbox Code Playgroud)
注意现在经过的时间大约是原始时间的29%(= 0.135/0.459).
从这里你可以进一步推广跨多台机器的并行执行- 高性能计算与R的任务视图有进一步的指示.10月31日到期的R 2.14.0将有一个新的'并行'包,它结合了多核和雪的部分.