Я предполагаю, что код, который вы указали в своем вопросе, на самом деле не тот, который вы хотите.Ваш код вычисляет расстояние между попарно рядами source
и dest
, перерабатывая source
, чтобы соответствовать длине dest
.
То, что вы, вероятно, хотите, и что дает этот ответ, это найтиближайшая точка в dest
для каждой точки в source
.(см. мои комментарии к вашему вопросу)
Расчет матриц расстояний требует больших вычислительных ресурсов.Предполагая, что R-пакеты примерно одинаково эффективны при расчете матриц расстояний, на самом деле единственный способ ускорить это - распараллелить вычисление матриц расстояний.К сожалению, матрица с большим количеством строк является опорными точками, потому что распараллеливание может происходить только по подмножествам исходных точек.(т. е. вам нужно учесть все dest
точки, чтобы найти ближайшую dest
точку к любой данной source
)
library(parallel)
library(sp)
#nonparallel version
x2 <- copy(source)
temp <- spDists(x2[, .(long,lat)],dest_mat,longlat=TRUE)
system.time(final2 <- x2[, c("long_dest","lat_dest"):=as.list(dest_mat[apply(temp,1,which.min),]) ])
#parallel version
source_l <- split(source, rep(1:10,each=100))
cl <- makeCluster(getOption("cl.cores", 4))
clusterExport(cl, "dest_mat") #this is slow but I don't think there's a way to get around this
system.time(
v <- parLapply(cl=cl, X=source_l, fun=function(x){
library(sp)
library(data.table)
temp <- spDists(x[, .(long,lat)],dest_mat,longlat=TRUE)
x[, c("long_dest","lat_dest"):=as.list(dest_mat[apply(temp,1,which.min),]) ]
x
})
)
stopCluster(cl)
final <- rbindlist(v)
identical(final[order(nrow)],final2)
Вам нужно будет поэкспериментировать с использованием более 32 процессовна самом деле ускоряет вещи.Гиперпоточность может быть смешанной, и не всегда легко предсказать, принесет ли она какую-либо пользу.К сожалению, нет гарантии, что у вас будет достаточно оперативной памяти для запуска оптимального количества процессов.Это не только медленно, но и интенсивно использует память.Если вы получаете ошибки, указывающие на то, что у вас недостаточно памяти, вам нужно уменьшить количество процессов или арендовать машину EC2 с большим объемом памяти.
Наконец, я отмечу, что which.min возвращаетИндекс первых минимумов, если есть связи.Таким образом, результаты будут зависеть от порядка строк в dest_mat.