Parallel computing is supported in Signac through the future package, making it easy to specify different parallelization options. Here we demonstrate parallelization of the FeatureMatrix
function and show some benchmark results to get a sense for the amout of speedup you might expect.
The Seurat package also uses future
for parallelization, and you can see the Seurat vignette for more information.
Parallelization can be enabled simply by importing the future
package and setting the plan
.
## sequential:
## - args: function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, seed = NULL, globals = TRUE, local = TRUE, earlySignal = FALSE, label = NULL, ...)
## - tweaked: FALSE
## - call: NULL
By default the plan is set to sequential processing (no parallelization). We can change this to multicore
, multiprocessor
, or multisession
to get parallel processing, and set the number of workers to change the number of cores used.
## multiprocess:
## - args: function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, seed = NULL, globals = TRUE, workers = 10, gc = FALSE, earlySignal = FALSE, label = NULL, ...)
## - tweaked: TRUE
## - call: plan("multiprocess", workers = 10)
You may also need to increase the maximum memory usage:
options(future.globals.maxSize = 50000 * 1024^2) # for 50 Gb RAM
Note that as of future
version 1.14.0, forked processing is disabled when running in RStudio. To enable parallel computing in RStudio, you will need to select the “multisession” option.
Here we demonstrate the runtime of FeatureMatrix
run on 90,686 peaks for 10,247 human PBMCs under different parallelization options:
View benchmarking code
The following code was run on Ubuntu 18.04 LTS with 12 Intel Xeon W-2135 CPUs @ 3.70GHz and 500 Gb RAM.
library(Signac) # load data fragments <- "/home/stuartt/data/pbmc10k/atac_pbmc_10k_nextgem_fragments.tsv.gz" peaks.10k <- read.table( file = "/home/stuartt/data/pbmc10k/atac_pbmc_10k_nextgem_peaks.bed", col.names = c("chr", "start", "end") ) peaks <- GenomicRanges::makeGRangesFromDataFrame(peaks.10k) cells <- readLines("/home/stuartt/data/pbmc10k/cells.txt") # set number of replicates nrep <- 5 results <- data.frame() # run sequentially timing.sequential <- c() for (i in seq_len(nrep)) { start <- Sys.time() fmat <- FeatureMatrix(fragments = fragments, features = peaks, cells = cells) timing.sequential <- c(timing.sequential, as.numeric(Sys.time() - start, units = "secs")) } res <- data.frame( "setting" = rep("Sequential", nrep), "cores" = rep(1, nrep), "replicate" = seq_len(nrep), "time" = timing.sequential ) results <- rbind(results, res) # 4 core library(future) plan("multiprocess", workers = 4) options(future.globals.maxSize = 100000 * 1024^2) timing.4core <- c() for (i in seq_len(nrep)) { start <- Sys.time() fmat <- FeatureMatrix(fragments = fragments, features = peaks, cells = cells) timing.4core <- c(timing.4core, as.numeric(Sys.time() - start, units = "secs")) } res <- data.frame( "setting" = rep("Parallel", nrep), "cores" = rep(4, nrep), "replicate" = seq_len(nrep), "time" = timing.4core ) results <- rbind(results, res) # 10 core plan("multiprocess", workers = 10) timing.10core <- c() for (i in seq_len(nrep)) { start <- Sys.time() fmat <- FeatureMatrix(fragments = fragments, features = peaks, cells = cells) timing.10core <- c(timing.10core, as.numeric(Sys.time() - start, units = "secs")) } res <- data.frame( "setting" = rep("Parallel", nrep), "cores" = rep(10, nrep), "replicate" = seq_len(nrep), "time" = timing.10core ) results <- rbind(results, res) # save results write.table( x = results, file = "timings.tsv", quote = FALSE, row.names = FALSE )
Session Info
## R version 4.0.1 (2020-06-06)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
##
## locale:
## [1] LC_CTYPE=en_AU.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplot2_3.3.2 future_1.17.0
##
## loaded via a namespace (and not attached):
## [1] compiler_4.0.1 pillar_1.4.4 tools_4.0.1 digest_0.6.25
## [5] evaluate_0.14 memoise_1.1.0 lifecycle_0.2.0 tibble_3.0.1
## [9] gtable_0.3.0 pkgconfig_2.0.3 rlang_0.4.6 yaml_2.2.1
## [13] parallel_4.0.1 pkgdown_1.5.1 xfun_0.14 withr_2.2.0
## [17] stringr_1.4.0 dplyr_1.0.0 knitr_1.28 desc_1.2.0
## [21] generics_0.0.2 fs_1.4.1 vctrs_0.3.1 globals_0.12.5
## [25] rprojroot_1.3-2 grid_4.0.1 tidyselect_1.1.0 glue_1.4.1
## [29] listenv_0.8.0 R6_2.4.1 rmarkdown_2.2 farver_2.0.3
## [33] purrr_0.3.4 magrittr_1.5 backports_1.1.8 scales_1.1.1
## [37] codetools_0.2-16 htmltools_0.5.0 ellipsis_0.3.1 MASS_7.3-51.6
## [41] assertthat_0.2.1 colorspace_1.4-1 labeling_0.3 stringi_1.4.6
## [45] munsell_0.5.0 crayon_1.3.4