【问题标题】:Fast parallel bipartite distance calculation in RR中的快速并行二分距离计算
【发布时间】:2021-02-04 10:42:01
【问题描述】:

在 R 中使用并行 Rcpp 后端计算二分距离的最快方法是什么?

parallelDist 是一个很棒的包,带有 cpp 后端并支持多线程,但不支持二分距离计算(据我所知)。

使用parallelDist() 进行二分距离矩阵计算。这涉及到计算 m1:m1 和 m2:m2 以及 m1:m2 - 效率非常低。 p>

library(parallelDist)

bipartiteDist <- function(matrix1,matrix2){
  matrix12 <- rbind(matrix1,matrix2)
  d <- parallelDist(matrix12)
  d <- as.matrix(d)[(1:nrow(matrix1)),((nrow(matrix1)+1):(nrow(matrix1)*2))]
  d
}

matrix1 <- abs(matrix(rnorm(1000),10,100000))
matrix2 <- abs(matrix(rnorm(1000),10,100000))

dist <- bipartiteDist(matrix1, matrix2)

当超过 3 个内核可用时,这种方法比 pDist 或纯 R 实现更快。

pdist 非常适合计算二分距离,但不支持多线程。

并行二分距离计算的任何快速实现?

【问题讨论】:

    标签: r optimization distance rcpp


    【解决方案1】:

    wordspace dist.matrix() 函数支持并行计算二分距离。

    wordspaceparallelDist 进行基准测试

    matrix1 <- abs(matrix(rnorm(1000),100,100000))
    matrix2 <- abs(matrix(rnorm(1000),100,100000))
    
    library(rbenchmark)
    library(parallelDist)
    library(wordspace)
    
    bipartiteDist_parallelDist <- function(matrix1,matrix2){
      matrix12 <- rbind(matrix1,matrix2)
      d <- parallelDist(matrix12, method = "euclidean")
      d <- as.matrix(d)[(1:nrow(matrix1)),((nrow(matrix1)+1):(nrow(matrix1)*2))]
      d
    }
    
    bipartiteDist_wordspace <- function(matrix1,matrix2){
      wordspace.openmp(threads = wordspace.openmp()$max)
      dist.matrix(matrix1,matrix2, byrow = TRUE, method = "euclidean", convert = FALSE)
    }
    
    benchmark("parallelDist" = {
                bd1 <- bipartiteDist_parallelDist(matrix1,matrix2)
              },
              "wordspace" = {
                bd2 <- bipartiteDist_wordspace(matrix1,matrix2)
              },
              replications = 1,
              columns = c("test", "replications", "elapsed",
                          "relative", "user.self", "sys.self"))
    
    plot(bd1,bd2) # yes, both methods give near-identical results
    

    基准测试结果:

              test replications elapsed relative user.self sys.self
    1 parallelDist            1   2.120   12.184   126.145    0.523
    2    wordspace            1   0.174    1.000     3.749    0.252
    

    我使用了 80 个线程。

    进一步提高速度的框架

    wordspace 的作者承认强调低内存负载比速度更重要,因此额外的速度提升是可能的 (source)。

    例如,这里有一个欧几里得距离的通用框架:

    bipartiteDist3 <- function(matrix1,matrix2){
      m1tm2 <- tcrossprod(matrix1,matrix2)
      sq1 <- rowSums(matrix1^2)
      sq2 <- rowSums(matrix2^2)
      out0 <- outer(sq1, sq2, "+") - 2 * m1tm2
      sqrt(out0)
    }
    

    我对针对稀疏矩阵优化的并行解决方案非常感兴趣。据我所知,wordspace 没有针对稀疏性进行优化。例如,有 tcrossprod、rowSums 和外部函数等价物的可并行稀疏矩阵实现。

    【讨论】:

    • 这个问题和你自己的答案已经做了一些很好的工作。但是,要为您的问题找到一个很好的答案似乎确实需要做很多工作。您是否考虑过使用 RcppArrayFire 之类的库转向 GPU 计算?自从它更新以来已经有一段时间了,但我相信它对于 GPU 上的矩阵代数仍然非常有用。它不会使用稀疏计算,但它可能足以解决您的问题,同时仍然易于实现。
    • @Oliver 谢谢你。我当然在这里看到了 GPU 的魅力,但由于我的管道中其他算法以 CPU 为中心的性质,它并不理想。 Wordspace 很好地满足了我目前的需求,我怀疑它对于大多数有类似需求的用户来说是最快的选择。但了解潜在的改进总是很重要的。
    猜你喜欢
    • 1970-01-01
    • 2017-11-15
    • 2016-05-19
    • 2015-10-29
    • 2019-08-02
    • 2019-07-30
    • 2023-04-10
    • 2014-09-25
    • 2015-12-20
    相关资源
    最近更新 更多