2

我有一个包含 300 个句子的向量,我正在尝试使用该stringdist包查找元素 JW 距离。天真的实现的执行时间太长,导致我寻找减少运行时间的方法。我正在尝试利用doParallelandforeach包,但我没有得到任何显着的加速。这就是我要做的事情。

library(foreach)
library(doParallel)
cl = makeCluster(detectCores())
registerDoParallel(cl)

sentence = # vector containing sentences 
jw_dist = foreach(i = 1:length(sentence)) %dopar% {
 temp = sentence[sentence!=sentence[i]]
 return(mean(1 - stringdist::stringdist(sentence[i],temp,method = "jw",nthread = 3))
  }
  stopCluster(cl)

如果有人能指出我可以加速这段代码的方法,我将不胜感激。

4

1 回答 1

1

因此,您似乎正在与极端开销作斗争。

与其对单个句子进行并行化,不如将任务分成一些相当大的块,然后让apply剩下的事情去做。我选择了 10 块,每块 100 个句子,可能有一个更快的组合,但这个组合比你要求的要快得多(至少对我来说):

library(doParallel)
library(foreach)

# generate fake sentences

txt <- readLines(url('https://baconipsum.com/api/?type=all-meat&sentences=300&start-with-lorem=1&format=text'))

sentences <- strsplit(txt,'\\.\\s')[[1]]

sentences <- rep(sentences[sample(1:100,100)],10)

# pairwise combinations of sentences
cbn <- combn(1:length(sentences),2)

# simple timing
st <- Sys.time()

# Since you work on LINUX, you can use FORK
cl <-  makeCluster(detectCores(),type = 'FORK')
registerDoParallel(cl)


res <- foreach(ii = seq(1,1000,100),.combine = 'c') %dopar% {
  
  apply(cbn[,ii:(ii+99)],2,function(x) stringdist(sentences[x[1]],sentences[x[2]],method = "jw"))
   
}

stopCluster(cl)
Sys.time() - st

在我的 Ubuntu VM 上,此代码运行时间约为 1.8 秒。

眼镜:

Ubuntu 64 bit
R version 3.4
8 CPU cores
32GB RAM Memory

HTH

编辑:

在这种情况下,也许避免并行处理将是一个不错的选择。

使用这个lapply版本,我可以在大约 17 秒内计算出每个句子的平均值:

res <- do.call(rbind,lapply(1:1000,function(ii) c(ii,1-mean(stringdist(sentences[ii],sentences[-ii],method = "jw")))))

这将为您提供一个 2 列矩阵,其中包含每个句子的索引以及1-mean到相应句子的所有距离。

于 2017-06-19T13:49:32.507 回答