這是一個版本的基礎上湯米的答案,但避免了所有的循環:
library(multicore) # or library(parallel) in 2.14.x
set.seed(42)
m = 100
n = 30
system.time({
arms.C <- getNativeSymbolInfo("arms")$address
bounds <- 0.3 + convex.bounds(0.3, dir = 1, function(x) (x>1e-4)*(x<20))
if (diff(bounds) < 1e-07) stop("pointless!")
# create the vector of z values
zval <- 0.00001 * rep(seq.int(n), m) * rep(seq.int(m), each = n)
# apply the inner function to each grid point and return the matrix
dmat <- matrix(unlist(mclapply(zval, function(z)
sum(unlist(lapply(seq.int(100), function(i)
.Call(arms.C, bounds, function(x) (3.5 + z * i) * log(x) - x,
0.3, 1L, parent.frame())
)))
)), m, byrow=TRUE)
})
在多核機器,這將是非常快,因爲它在覈傳播的負載。在單核機器上(或者對於Windows用戶較差的用戶),您可以使用lapply
替換上面的mclapply
,與Tommy的答案相比,只能稍微提高速度。但請注意,並行版本的結果會有所不同,因爲它將使用不同的RNG序列。
請注意,任何需要評估R函數的C代碼本質上都很慢(因爲解釋代碼很慢)。我添加了arms.C
只是爲了消除所有R-> C開銷以使moli高興;)但它沒有任何區別。
通過使用列專業處理(問題代碼爲row-major,需要重新複製,因爲R矩陣始終爲列專業),您可以擠出更多的毫秒。
編輯:我注意到,摩力變化不大,因爲湯米回答了這個問題 - 這樣,而不是你必須使用一個循環,因爲y[i]
都依賴於sum(...)
部分,所以function(z)
看起來像
function(z) { y <- 0
for (i in seq.int(99))
y <- y + .Call(arms.C, bounds, function(x) (3.5 + z * y) * log(x) - x,
0.3, 1L, parent.frame())
y }
你有三個嵌套for循環。你基本上在O(n^3)中運行。你真的需要他們嗎? – simchona 2012-02-09 18:49:13
@simchona是的。我需要他們。 – moli 2012-02-09 18:50:32
如果你想要循環,你每次都會有可怕的運行時間。您需要完全修改它以打破糟糕的時間。 – simchona 2012-02-09 18:54:13