diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index a5c0ce3b0..bf63442fb 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14243,15 +14243,17 @@ test(1997.06, setDTthreads(percent=NULL), error="but is length 0") test(1997.07, setDTthreads(percent=1:2), error="but is length 2") test(1997.08, setDTthreads(restore_after_fork=21), error="must be TRUE, FALSE, or NULL") old = getDTthreads() # (1) -oldenv1 = Sys.getenv("R_DATATABLE_NUM_PROCS_PERCENT") -oldenv2 = Sys.getenv("R_DATATABLE_NUM_THREADS") +oldenv.PERCENT = Sys.getenv("R_DATATABLE_NUM_PROCS_PERCENT") +oldenv.THREADS = Sys.getenv("R_DATATABLE_NUM_THREADS") Sys.setenv(R_DATATABLE_NUM_THREADS="") # in case user has this set, so we can test PROCS_PERCENT -Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="3.0") -test(1997.09, setDTthreads(), old, ignore.warning="Ignoring invalid.*Please remove any.*not a digit") +Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="3a0") +test(1997.09, setDTthreads(), old, warning="Ignoring invalid.*") +Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="-12.5") +test(1997.091, setDTthreads(), old, warning="Environment variable.*") new = getDTthreads() # old above at (1) may not have been default. new now is. test(1997.10, getDTthreads(), new) Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="1") -test(1997.11, setDTthreads(), new, ignore.warning="Ignoring invalid.*integer between 2 and 100") +test(1997.11, setDTthreads(), new, warning="Ignoring invalid.*integer between 2 and 100") test(1997.12, getDTthreads(), new) Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="75") test(1997.13, setDTthreads(), new) @@ -14265,14 +14267,26 @@ Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT="75") Sys.setenv(R_DATATABLE_NUM_THREADS=allcpu) setDTthreads() test(1997.15, getDTthreads(), allcpu) -Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT=oldenv1) -Sys.setenv(R_DATATABLE_NUM_THREADS=oldenv2) +Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT=oldenv.PERCENT) +Sys.setenv(R_DATATABLE_NUM_THREADS=oldenv.THREADS) test(1997.16, setDTthreads(old), allcpu) test(1997.17, getDTthreads(), old) test(1997.18, setDTthreads(throttle=NA), error="throttle.*must be a single number, non-NA, and >=1") setDTthreads(throttle=65536) test(1997.19, getDTthreads(TRUE), output="throttle==65536") setDTthreads(throttle=1024) +## THRESHOLD test. +oldenv.PERCENT = Sys.getenv("R_DATATABLE_NUM_PROCS_PERCENT") +oldenv.THREADS = Sys.getenv("R_DATATABLE_NUM_THREADS") +oldenv.THRESH = Sys.getenv("_R_CHECK_EXAMPLE_TIMING_CPU_TO_ELAPSED_THRESHOLD_") +Sys.unsetenv("R_DATATABLE_NUM_THREADS") +Sys.unsetenv("R_DATATABLE_NUM_PROCS_PERCENT") +Sys.setenv("_R_CHECK_EXAMPLE_TIMING_CPU_TO_ELAPSED_THRESHOLD_"=2.5) +setDTthreads() +test(1997.20, getDTthreads(), 2L) +Sys.setenv(R_DATATABLE_NUM_PROCS_PERCENT=oldenv.PERCENT) +Sys.setenv(R_DATATABLE_NUM_THREADS=oldenv.THREADS) +Sys.setenv("_R_CHECK_EXAMPLE_TIMING_CPU_TO_ELAPSED_THRESHOLD_"=oldenv.THRESH) # test that a copy is being made and output is printed, #3385 after partial revert of #3281 x = 5L diff --git a/src/openmp-utils.c b/src/openmp-utils.c index 483a91654..e2afb8bfa 100644 --- a/src/openmp-utils.c +++ b/src/openmp-utils.c @@ -16,14 +16,18 @@ static int getIntEnv(const char *name, int def) size_t nchar = strlen(val); if (nchar==0) return def; char *end; - errno = 0; - long int ans = strtol(val, &end, 10); // ignores leading whitespace. If it fully consumed the string, *end=='\0' and isspace('\0')==false + double number = strtod(val, &end); // ignores leading whitespace. If it fully consumed the string, *end=='\0' and isspace('\0')==false while (isspace(*end)) end++; // ignore trailing whitespace - if (errno || (size_t)(end-val)!=nchar || ans<1 || ans>INT_MAX) { - warning(_("Ignoring invalid %s==\"%s\". Not an integer >= 1. Please remove any characters that are not a digit [0-9]. See ?data.table::setDTthreads."), name, val); + int ans = number; + if ((size_t)(end-val)!=nchar) { + warning(_("Ignoring invalid %s==\"%s\", which should be interpretable as a number. See ?data.table::setDTthreads."), name, val); return def; } - return (int)ans; + if (ans<1 || ans>INT_MAX) { + warning(_("Environment variable %s==\"%s\" was interpreted as %d, which is not a positive integer, so instead using default %d. See ?data.table::setDTthreads."), name, val, ans, def); + return def; + } + return ans; } static inline int imin(int a, int b) { return a < b ? a : b; } @@ -52,6 +56,7 @@ void initDTthreads(void) { // max_threads() -vs- num_procs(): https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/302866 ans = imin(ans, getIntEnv("OMP_THREAD_LIMIT", INT_MAX)); // user might expect `Sys.setenv(OMP_THREAD_LIMIT=2);setDTthreads()` to work. Satisfy this ans = imin(ans, getIntEnv("OMP_NUM_THREADS", INT_MAX)); // expectation by reading them again now. OpenMP just reads them on startup (quite reasonably) + ans = imin(ans, getIntEnv("_R_CHECK_EXAMPLE_TIMING_CPU_TO_ELAPSED_THRESHOLD_", INT_MAX));// CRAN sets this to 2.5 during checks. ans = imax(ans, 1); // just in case omp_get_* returned <=0 for any reason, or the env variables above are set <=0 DTthreads = ans; DTthrottle = imax(1, getIntEnv("R_DATATABLE_THROTTLE", 1024)); // 2nd thread is used only when n>1024, 3rd thread when n>2048, etc