R语言之并行计算(kendall相关系数篇)

    对于属性较多的数据,我们一般都会去计算两两属性之间的相关性,用以探讨属性之间的关系.

    相对于皮尔森相关系数,我们更喜欢使用spearman和kendall相关系数,因为作为非参数相关系数,稳定性更好.

    一般来说,计算kendall相关系数可以用以下语句:

cor(x, y, method = "kendall")

    在本文一开始提到的场景下,这十分耗时.我们可以从以下3个方面减少计算时间:

    1.优化算法,pcaPP包提供的cor.fk函数具有更好的效率,大规模计算kendall系数的话,多使用这个函数.

pcaPP::cor.fk(x, y)

    2.将任务拆分成几个并行的子任务分别在不同的计算机上运行,如果能够得到这些计算机的权限,这个方法可以归于第3个方法,这里不多讲.

    3.将任务拆分成几个并行的子任务分别在某台计算机的多个cpu上进行计算,这是本文的重点.

    R语言提供简单并行计算的包有parallel包.下面以实例说明如何进行并行计算.

##### 生成测试数据 #####
library(parallel)
set.seed(0)
n <- 1000  # 设定需要计算两两相关系数的属性个数
test <- matrix(runif(100 * n), 100, n)  # 样本容量为100
pair <- t(combn(1:n, 2))  # 生成两两配对数据

##### 并行计算集群初始化及任务拆分 #####
nt <- detectCores()  # detectCores函数可以获得本地计算机cpu个数,本地cpu为4
cl <- makeCluster(type = "SOCK", rep("localhost", nt - 1))  # 初始化并行计算集群,cpu个数为总个数减1
ichunk <- split(as.data.frame(pair), 2:nt)  # 将配对数据拆分为nt - 1份

##### f0为非并行计算kendall函数 #####
f0 <- function(x) {
  nc <- ncol(x)
  res <- NULL
  for (i in 1:(nc - 1)) {
    tmp <- (i + 1):nc
    res <- c(res, cor(x[, i], x[, tmp], method = "kendall"))
  }
  cbind(pair, res)
}

##### f1为并行计算kendall函数子函数,也可作为主函数使用 #####
f1 <- function(id, x) {
  nr <- nrow(id)
  res <- matrix(0, nr, 1)
  k <- 1
  for (i in 1:nr) {
    res[k, ] <- pcaPP::cor.fk(x[, id[i, 1]], x[, id[i, 2]])
    k <- k + 1
  }
  cbind(id, res)
}

##### 计算两两相关系数 #####
system.time(res0 <- f0(test))
system.time(res1 <- f1(pair, test))
system.time(res1p <- clusterApply(cl, ichunk, f1, test))

stopCluster(cl)  # 关闭并行计算集群

    设n为100,实际运行结果如下:

> system.time(res0 <- f0(test))
 用户  系统  流逝 
1.584 0.000 1.587 
> system.time(res1 <- f1(pair, test))
用户 系统 流逝 
0.56 0.00 0.56 
> system.time(res1p <- clusterApply(cl, ichunk, f1, test))
 用户  系统  流逝 
0.008 0.000 0.526

    设n为1000,实际运行结果如下:

> system.time(res0 <- f0(test))
   user  system elapsed 
 156.84    1.86  162.17
> system.time(res1 <- f1(pair, test))
  用户   系统   流逝 
57.056  0.020 57.186 
> system.time(res1p <- clusterApply(cl, ichunk, f1, test))
  用户   系统   流逝 
 0.176  0.124 46.035

    可见:

    1.即使f0的循环次数比f1的循环次数少得多,但是运行时间还是慢很多,这主要是cor.fk的性能比cor好很多的原因.    

    2.使用了3个cpu,但是加速的效率却不是3倍的,这主要的是并行计算时需要传递数据等其他运算.

你可能感兴趣的:(r,parallel,Kendall)