vignettes/future.Rmd
future.Rmd
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 amount of speedup
you might expect.
The Seurat package also
uses future
for parallelization, and you can see the Seurat
vignette
for more information.
The following functions currently enable parallelization in Signac:
Parallelization can be enabled simply by importing the
future
package and setting the plan
.
## Warning: package 'future' was built under R version 4.3.3
plan()
## sequential:
## - args: function (..., envir = parent.frame())
## - tweaked: FALSE
## - call: NULL
By default the plan is set to sequential processing (no
parallelization). We can change this to multicore
or
multisession
to get asynchronous processing, and set the
number of workers to change the number of cores used.
## multicore:
## - args: function (..., workers = 10, envir = parent.frame())
## - tweaked: TRUE
## - call: plan("multicore", workers = 10)
You might also need to increase the maximum memory usage:
options(future.globals.maxSize = 50 * 1024 ^ 3) # 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
144,023 peaks for 9,688 human PBMCs under different parallelization
options:
The following code was run on REHL with Intel Platinum 8268 CPU @ 2.00GHz
# download data
wget https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_10k_nextgem/atac_pbmc_10k_nextgem_fragments.tsv.gz
wget https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_10k_nextgem/atac_pbmc_10k_nextgem_fragments.tsv.gz.tbi
wget https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_10k_nextgem/atac_pbmc_10k_nextgem_peaks.bed
wget https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_10k_nextgem/atac_pbmc_10k_nextgem_singlecell.csv
library(Signac)
# load data
fragments <- "../vignette_data/atac_pbmc_10k_nextgem_fragments.tsv.gz"
peaks.10k <- read.table(
file = "../vignette_data/atac_pbmc_10k_nextgem_peaks.bed",
col.names = c("chr", "start", "end")
)
peaks <- GenomicRanges::makeGRangesFromDataFrame(peaks.10k)
md <- read.csv("../vignette_data/atac_pbmc_10k_nextgem_singlecell.csv", row.names = 1, header = TRUE)[-1, ]
cells <- rownames(md[md[['is__cell_barcode']] == 1, ])
fragments <- CreateFragmentObject(path = fragments, cells = cells, validate.fragments = FALSE)
# set number of replicates
nrep <- 5
results <- data.frame()
process_n <- 2000
# run sequentially
timing.sequential <- c()
for (i in seq_len(nrep)) {
start <- Sys.time()
fmat <- FeatureMatrix(fragments = fragments, features = peaks, cells = cells, process_n = process_n)
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("multicore", 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, process_n = process_n)
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("multicore", workers = 10)
timing.10core <- c()
for (i in seq_len(nrep)) {
start <- Sys.time()
fmat <- FeatureMatrix(fragments = fragments, features = peaks, cells = cells, process_n = process_n)
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 = paste0("../vignette_data/pbmc10k/timings_", Sys.Date(), ".tsv"),
quote = FALSE,
row.names = FALSE
)
## R version 4.3.1 (2023-06-16)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Sonoma 14.5
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: Asia/Singapore
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplot2_3.5.1 future_1.34.0
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.5 jsonlite_1.8.8 highr_0.11 dplyr_1.1.4
## [5] compiler_4.3.1 tidyselect_1.2.1 parallel_4.3.1 jquerylib_0.1.4
## [9] globals_0.16.3 systemfonts_1.1.0 scales_1.3.0 textshaping_0.4.0
## [13] yaml_2.3.10 fastmap_1.2.0 R6_2.5.1 labeling_0.4.3
## [17] generics_0.1.3 knitr_1.48 htmlwidgets_1.6.4 tibble_3.2.1
## [21] desc_1.4.3 munsell_0.5.1 pillar_1.9.0 bslib_0.8.0
## [25] rlang_1.1.4 utf8_1.2.4 cachem_1.1.0 xfun_0.47
## [29] fs_1.6.4 sass_0.4.9 memoise_2.0.1 cli_3.6.3
## [33] withr_3.0.1 pkgdown_2.0.9 magrittr_2.0.3 digest_0.6.37
## [37] grid_4.3.1 lifecycle_1.0.4 vctrs_0.6.5 evaluate_0.24.0
## [41] glue_1.7.0 farver_2.1.2 listenv_0.9.1 codetools_0.2-19
## [45] ragg_1.3.2 fansi_1.0.6 parallelly_1.38.0 colorspace_2.1-1
## [49] rmarkdown_2.28 purrr_1.0.2 pkgconfig_2.0.3 tools_4.3.1
## [53] htmltools_0.5.8.1