Это версия, основанная на ответе Томми, но избегающая всех петель:
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) вы можете заменить mclapply
выше на lapply
и получить лишь небольшое ускорение по сравнению с ответом Томми.Но обратите внимание, что результат будет отличаться для параллельных версий, поскольку он будет использовать разные последовательности RNG.
Обратите внимание, что любой код C, который должен оценивать функции R, будет по своей сути медленным (поскольку интерпретируемый код медленный).Я добавил arms.C
только для того, чтобы удалить все накладные расходы R-> C, чтобы осчастливить moli;), но это не имеет значения.
Вы можете выжать еще несколько миллисекунд, используя column-основная обработка (код вопроса был главным по строке, который требует повторного копирования, поскольку матрицы R всегда являются основными по столбцам).
Редактировать: Я заметил, что Моли слегка изменила вопрос, так как Томми ответил- поэтому вместо части sum(...)
вы должны использовать цикл, поскольку y[i]
являются зависимыми, поэтому 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 }