@@ -438,36 +438,50 @@ availableCores <- function(constraints = NULL, methods = getOption2("parallelly.
438438} # availableCores()
439439
440440
441- getNproc <- function (ignore = c(" OMP_NUM_THREADS" , " OMP_THREAD_LIMIT" )) {
442- # # 'nproc' is limited by 'OMP_NUM_THREADS' and 'OMP_THREAD_LIMIT', if set.
443- # # However, that is not what we want for availableCores(). Because of
444- # # this, we unset those while querying 'nproc'.
445- if (length(ignore ) > 0 ) {
446- ignore <- intersect(ignore , names(Sys.getenv()))
441+ getNproc <- local({
442+ res <- NULL
443+
444+ function (ignore = c(" OMP_NUM_THREADS" , " OMP_THREAD_LIMIT" )) {
445+ if (! is.null(res )) return (res )
446+
447+ # # 'nproc' is limited by 'OMP_NUM_THREADS' and 'OMP_THREAD_LIMIT', if set.
448+ # # However, that is not what we want for availableCores(). Because of
449+ # # this, we unset those while querying 'nproc'.
447450 if (length(ignore ) > 0 ) {
448- oignore <- Sys.getenv(ignore , names = TRUE )
449- oignore <- as.list(oignore )
450- on.exit(do.call(Sys.setenv , args = oignore ), add = TRUE )
451- Sys.unsetenv(ignore )
451+ ignore <- intersect(ignore , names(Sys.getenv()))
452+ if (length(ignore ) > 0 ) {
453+ oignore <- Sys.getenv(ignore , names = TRUE )
454+ oignore <- as.list(oignore )
455+ on.exit(do.call(Sys.setenv , args = oignore ), add = TRUE )
456+ Sys.unsetenv(ignore )
457+ }
458+ }
459+
460+ systems <- list (linux = " nproc 2>/dev/null" )
461+ os <- names(systems )
462+ m <- pmatch(os , table = R.version $ os , nomatch = NA_integer_ )
463+ m <- os [! is.na(m )]
464+ if (length(m ) == 0L ) {
465+ res <<- NA_integer_
466+ return (res )
452467 }
453- }
454468
455- systems <- list (linux = " nproc 2>/dev/null" )
456- os <- names(systems )
457- m <- pmatch(os , table = R.version $ os , nomatch = NA_integer_ )
458- m <- os [! is.na(m )]
459- if (length(m ) == 0L ) return (NA_integer_ )
460-
461- for (cmd in systems [[m ]]) {
462- tryCatch({
463- res <- suppressWarnings(system(cmd , intern = TRUE ))
464- res <- gsub(" (^[[:space:]]+|[[:space:]]+$)" , " " , res [1 ])
465- if (grepl(" ^[[:digit:]]+$" , res )) return (as.integer(res ))
466- }, error = identity )
469+ for (cmd in systems [[m ]]) {
470+ tryCatch({
471+ value <- suppressWarnings(system(cmd , intern = TRUE ))
472+ value <- gsub(" (^[[:space:]]+|[[:space:]]+$)" , " " , value [1 ])
473+ if (grepl(" ^[[:digit:]]+$" , value )) {
474+ res <<- as.integer(value )
475+ return (res )
476+ }
477+ }, error = identity )
478+ }
479+
480+ res <<- NA_integer_
481+
482+ res
467483 }
468-
469- NA_integer_
470- }
484+ })
471485
472486
473487checkNumberOfLocalWorkers <- function (workers ) {
@@ -534,103 +548,122 @@ getopt_int <- function(name, mode = "integer") {
534548# High-Performance Compute (HPC) Schedulers
535549# --------------------------------------------------------------------------
536550# # Number of slots assigned by LSF
537- availableCoresLSF <- function () {
538- n <- getenv_int(" LSB_DJOB_NUMPROC" )
539- n
540- }
551+ availableCoresLSF <- local({
552+ n <- NULL
553+ function () {
554+ if (! is.null(n )) return (n )
555+ n <<- getenv_int(" LSB_DJOB_NUMPROC" )
556+ n
557+ }
558+ })
541559
542560
543561# # Number of cores assigned by TORQUE/PBS
544- availableCoresPBS <- function () {
545- n <- getenv_int(" PBS_NUM_PPN" )
546- if (is.na(n )) {
547- # # PBSPro sets 'NCPUS' but not 'PBS_NUM_PPN'
548- n <- getenv_int(" NCPUS" )
562+ availableCoresPBS <- local({
563+ n <- NULL
564+ function () {
565+ n <<- getenv_int(" PBS_NUM_PPN" )
566+ if (is.na(n )) {
567+ # # PBSPro sets 'NCPUS' but not 'PBS_NUM_PPN'
568+ n <<- getenv_int(" NCPUS" )
569+ }
570+ n
549571 }
550- n
551- }
572+ })
552573
553574
554575# # Number of slots assigned by Fujitsu Technical Computing Suite
555576# # We choose to call this job scheduler "PJM" based on the prefix
556577# # it's environment variables use.
557- availableCoresPJM <- function () {
558- # # PJM_VNODE_CORE: e.g. pjsub -L vnode-core=8
559- # # "This environment variable is set only when virtual nodes
560- # # are allocated, and it is not set when nodes are allocated."
561- n <- getenv_int(" PJM_VNODE_CORE" )
562- if (is.na(n )) {
563- # # PJM_PROC_BY_NODE: e.g. pjsub -L vnode-core=8
564- # # "Maximum number of processes that are generated per node by
565- # # an MPI program. However, if a single node (node=1) or virtual
566- # # node (vnode=1) is allocated and the mpi option of the pjsub
567- # # command is not specified, this environment variable is not set."
568- n <- getenv_int(" PJM_PROC_BY_NODE" )
578+ availableCoresPJM <- local({
579+ n <- NULL
580+ function () {
581+ # # PJM_VNODE_CORE: e.g. pjsub -L vnode-core=8
582+ # # "This environment variable is set only when virtual nodes
583+ # # are allocated, and it is not set when nodes are allocated."
584+ n <<- getenv_int(" PJM_VNODE_CORE" )
585+ if (is.na(n )) {
586+ # # PJM_PROC_BY_NODE: e.g. pjsub -L vnode-core=8
587+ # # "Maximum number of processes that are generated per node by
588+ # # an MPI program. However, if a single node (node=1) or virtual
589+ # # node (vnode=1) is allocated and the mpi option of the pjsub
590+ # # command is not specified, this environment variable is not set."
591+ n <<- getenv_int(" PJM_PROC_BY_NODE" )
592+ }
593+ n
569594 }
570- n
571- }
595+ })
572596
573597
574598# # Number of cores assigned by Oracle/Son/Sun/Univa Grid Engine (SGE/UGE)
575- availableCoresSGE <- function () {
576- n <- getenv_int(" NSLOTS" )
577- n
578- }
599+ availableCoresSGE <- local({
600+ n <- NULL
601+ function () {
602+ n <<- getenv_int(" NSLOTS" )
603+ n
604+ }
605+ })
579606
580607
581608# # Number of cores assigned by Slurm
582- availableCoresSlurm <- function () {
583- # # The assumption is that the following works regardless of
584- # # number of nodes requested /HB 2020-09-18
585- # # Example: --cpus-per-task={n}
586- n <- getenv_int(" SLURM_CPUS_PER_TASK" )
587- if (is.na(n )) {
588- # # Example: --nodes={nnodes} (defaults to 1, short: -N {nnodes})
589- # # From 'man sbatch':
590- # # SLURM_JOB_NUM_NODES (and SLURM_NNODES for backwards compatibility)
591- # # Total number of nodes in the job's resource allocation.
592- nnodes <- getenv_int(" SLURM_JOB_NUM_NODES" )
593- if (is.na(nnodes )) nnodes <- getenv_int(" SLURM_NNODES" )
594- if (is.na(nnodes )) nnodes <- 1L # # Can this happen? /HB 2020-09-18
595-
596- if (nnodes == 1L ) {
597- # # Example: --nodes=1 --ntasks={n} (short: -n {n})
598- # # IMPORTANT: 'SLURM_CPUS_ON_NODE' appears to be rounded up when nodes > 1.
599- # # Example 1: With --nodes=2 --cpus-per-task=3 we see SLURM_CPUS_ON_NODE=4
600- # # although SLURM_CPUS_PER_TASK=3.
601- # # Example 2: With --nodes=2 --ntasks=7, we see SLURM_CPUS_ON_NODE=6,
602- # # SLURM_JOB_CPUS_PER_NODE=6,2, no SLURM_CPUS_PER_TASK, and
603- # # SLURM_TASKS_PER_NODE=5,2.
604- # # Conclusions: We can only use 'SLURM_CPUS_ON_NODE' for nnodes = 1.
605- n <- getenv_int(" SLURM_CPUS_ON_NODE" )
606- } else {
607- # # Parse `SLURM_TASKS_PER_NODE`
608- nodecounts <- getenv_int(" SLURM_TASKS_PER_NODE" , mode = " character" )
609- if (! is.na(nodecounts )) {
610- # # Examples:
611- # # SLURM_TASKS_PER_NODE=5,2
612- # # SLURM_TASKS_PER_NODE=2(x2),1(x3) # Source: 'man sbatch'
613- n <- slurm_expand_nodecounts(nodecounts )
614- if (anyNA(n )) return (NA_real_ )
615-
616- # # ASSUMPTION: We assume that it is the first component on the list that
617- # # corresponds to the current machine. /HB 2021-03-05
618- n <- n [1 ]
609+ availableCoresSlurm <- local({
610+ n <- NULL
611+ function () {
612+ # # The assumption is that the following works regardless of
613+ # # number of nodes requested /HB 2020-09-18
614+ # # Example: --cpus-per-task={n}
615+ n <<- getenv_int(" SLURM_CPUS_PER_TASK" )
616+ if (is.na(n )) {
617+ # # Example: --nodes={nnodes} (defaults to 1, short: -N {nnodes})
618+ # # From 'man sbatch':
619+ # # SLURM_JOB_NUM_NODES (and SLURM_NNODES for backwards compatibility)
620+ # # Total number of nodes in the job's resource allocation.
621+ nnodes <- getenv_int(" SLURM_JOB_NUM_NODES" )
622+ if (is.na(nnodes )) nnodes <- getenv_int(" SLURM_NNODES" )
623+ if (is.na(nnodes )) nnodes <- 1L # # Can this happen? /HB 2020-09-18
624+
625+ if (nnodes == 1L ) {
626+ # # Example: --nodes=1 --ntasks={n} (short: -n {n})
627+ # # IMPORTANT: 'SLURM_CPUS_ON_NODE' appears to be rounded up when nodes > 1.
628+ # # Example 1: With --nodes=2 --cpus-per-task=3 we see SLURM_CPUS_ON_NODE=4
629+ # # although SLURM_CPUS_PER_TASK=3.
630+ # # Example 2: With --nodes=2 --ntasks=7, we see SLURM_CPUS_ON_NODE=6,
631+ # # SLURM_JOB_CPUS_PER_NODE=6,2, no SLURM_CPUS_PER_TASK, and
632+ # # SLURM_TASKS_PER_NODE=5,2.
633+ # # Conclusions: We can only use 'SLURM_CPUS_ON_NODE' for nnodes = 1.
634+ n <<- getenv_int(" SLURM_CPUS_ON_NODE" )
635+ } else {
636+ # # Parse `SLURM_TASKS_PER_NODE`
637+ nodecounts <- getenv_int(" SLURM_TASKS_PER_NODE" , mode = " character" )
638+ if (! is.na(nodecounts )) {
639+ # # Examples:
640+ # # SLURM_TASKS_PER_NODE=5,2
641+ # # SLURM_TASKS_PER_NODE=2(x2),1(x3) # Source: 'man sbatch'
642+ n <<- slurm_expand_nodecounts(nodecounts )
643+ if (anyNA(n )) {
644+ n <<- NA_real_
645+ return (n )
646+ }
647+
648+ # # ASSUMPTION: We assume that it is the first component on the list that
649+ # # corresponds to the current machine. /HB 2021-03-05
650+ n <<- n [1 ]
651+ }
619652 }
620653 }
621- }
622-
623- # # TODO?: Can we validate above assumptions/results? /HB 2020-09-18
624- if (FALSE && ! is.na(n )) {
625- # # Is any of the following useful?
654+
655+ # # TODO?: Can we validate above assumptions/results? /HB 2020-09-18
656+ if (FALSE && ! is.na(n )) {
657+ # # Is any of the following useful?
658+
659+ # # Example: --ntasks={ntasks} (no default, short: -n {ntasks})
660+ # # From 'man sbatch':
661+ # # SLURM_NTASKS (and SLURM_NPROCS for backwards compatibility)
662+ # # Same as -n, --ntasks
663+ ntasks <- getenv_int(" SLURM_NTASKS" )
664+ if (is.na(ntasks )) ntasks <- getenv_int(" SLURM_NPROCS" )
665+ }
626666
627- # # Example: --ntasks={ntasks} (no default, short: -n {ntasks})
628- # # From 'man sbatch':
629- # # SLURM_NTASKS (and SLURM_NPROCS for backwards compatibility)
630- # # Same as -n, --ntasks
631- ntasks <- getenv_int(" SLURM_NTASKS" )
632- if (is.na(ntasks )) ntasks <- getenv_int(" SLURM_NPROCS" )
667+ n
633668 }
634-
635- n
636- } # # availableCoresSlurm()
669+ }) # # availableCoresSlurm()
0 commit comments