diff --git a/arbor/include/arbor/context.hpp b/arbor/include/arbor/context.hpp index f6c0f1dc7bcb61673232f3d8280c5aee679e33d9..a61461ef65cf1b7a80a97a3bec281e727f4f00b5 100644 --- a/arbor/include/arbor/context.hpp +++ b/arbor/include/arbor/context.hpp @@ -17,7 +17,7 @@ struct dry_run_info { // By default, a proc_allocation will comprise one thread and no GPU. struct proc_allocation { - unsigned num_threads; + unsigned long num_threads; // The gpu id corresponds to the `int device` parameter used by // CUDA/HIP API calls to identify gpu devices. @@ -27,7 +27,7 @@ struct proc_allocation { proc_allocation(): proc_allocation(1, -1) {} - proc_allocation(unsigned threads, int gpu): + proc_allocation(unsigned long threads, int gpu): num_threads(threads), gpu_id(gpu) {} diff --git a/arborenv/CMakeLists.txt b/arborenv/CMakeLists.txt index 921622c0d1832113afa02131a8c96ca90a306506..16128499391839a27eff81acecd6e1e93eee9af0 100644 --- a/arborenv/CMakeLists.txt +++ b/arborenv/CMakeLists.txt @@ -1,8 +1,10 @@ set(arborenv-sources + arbenvexcept.cpp affinity.cpp concurrency.cpp - default_gpu.cpp + default_env.cpp private_gpu.cpp + read_envvar.cpp ) if(ARB_WITH_GPU) diff --git a/arborenv/arbenvexcept.cpp b/arborenv/arbenvexcept.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e905a3e17e384c86cc1f5f821b21d4360059956 --- /dev/null +++ b/arborenv/arbenvexcept.cpp @@ -0,0 +1,27 @@ +#include <stdexcept> +#include <string> + +#include <arborenv/arbenvexcept.hpp> + +using namespace std::literals; + +namespace arbenv { + +invalid_env_value::invalid_env_value(const std::string& variable, const std::string& value): + arborenv_exception("environment variable \""s+variable+"\" has invalid value \""s+value+"\""s), + env_variable(variable), + env_value(value) +{} + +// GPU enumeration, selection. + +no_such_gpu::no_such_gpu(int gpu_id): + arborenv_exception("no gpu with id "s+std::to_string(gpu_id)), + gpu_id(gpu_id) +{} + +gpu_uuid_error::gpu_uuid_error(std::string what): + arborenv_exception("error determining GPU uuids: "s+what) +{} + +} // namespace arbenv diff --git a/arborenv/concurrency.cpp b/arborenv/concurrency.cpp index 715c65fce7e56dc8c4c38b0f920d755d4f32e20f..208acee4590bda4543138242ba957817c5c9b505 100644 --- a/arborenv/concurrency.cpp +++ b/arborenv/concurrency.cpp @@ -1,6 +1,7 @@ #include <cstdlib> -#include <regex> -#include <string> +#include <limits> +#include <optional> +#include <stdexcept> #include <thread> #include <arborenv/concurrency.hpp> @@ -11,54 +12,18 @@ namespace arbenv { -// Test environment variables for user-specified count of threads. -unsigned get_env_num_threads() { - using namespace std::literals; - const char* str; - - // select variable to use: - // If ARB_NUM_THREADS_VAR is set, use $ARB_NUM_THREADS_VAR - // else if ARB_NUM_THREADS set, use it - // else if OMP_NUM_THREADS set, use it - if (auto nthreads_var_name = std::getenv("ARB_NUM_THREADS_VAR")) { - str = std::getenv(nthreads_var_name); - } - else if (! (str = std::getenv("ARB_NUM_THREADS"))) { - str = std::getenv("OMP_NUM_THREADS"); - } - - // No environment variable set, so return 0. - if (!str) { - return 0; - } - - errno = 0; - auto nthreads = std::strtoul(str, nullptr, 10); - - // check that the environment variable string describes a non-negative integer - if (errno==ERANGE || - !std::regex_match(str, std::regex("\\s*\\d*[0-9]\\d*\\s*"))) - { - errno = 0; - throw std::runtime_error("Requested number of threads \""s + str + "\" is not a valid value"s); - } - errno = 0; - - return nthreads; -} - // Take a best guess at the number of threads that can be run concurrently. // Will return at least 1. -unsigned thread_concurrency() { +unsigned long thread_concurrency() { // Attempt to get count first from affinity information if available. - unsigned n = get_affinity().size(); + unsigned long n = get_affinity().size(); // If no luck, try sysconf. #ifdef _SC_NPROCESSORS_ONLN if (!n) { long r = sysconf(_SC_NPROCESSORS_ONLN); if (r>0) { - n = (unsigned)r; + n = (unsigned long)r; } } #endif diff --git a/arborenv/default_env.cpp b/arborenv/default_env.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f55acfe45ac45eb0abb869def371639214548a7 --- /dev/null +++ b/arborenv/default_env.cpp @@ -0,0 +1,66 @@ +#include <limits> +#include <optional> + +#include <arborenv/arbenvexcept.hpp> +#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> + +#ifdef ARB_HAVE_GPU +#include "gpu_api.hpp" +#endif + +#include "read_envvar.hpp" + +namespace arbenv { + +unsigned long default_concurrency() { + unsigned long env_thread = get_env_num_threads(); + return env_thread? env_thread: thread_concurrency(); +} + +unsigned long get_env_num_threads() { + constexpr const char* env_var = "ARBENV_NUM_THREADS"; + std::optional<long long> env_val = read_env_integer(env_var, throw_on_invalid); + if (!env_val) return 0; + + if (*env_val<1 || static_cast<unsigned long long>(*env_val)>std::numeric_limits<unsigned long>::max()) { + throw invalid_env_value(env_var, std::getenv(env_var)); + } + return *env_val; +} + +#ifdef ARB_HAVE_GPU + +int default_gpu() { + constexpr const char* env_var = "ARBENV_GPU_ID"; + int n_device = -1; + get_device_count(&n_device); // error => leave n_device == -1 + + std::optional<long long> env_val = read_env_integer(env_var, throw_on_invalid); + if (env_val) { + if (*env_val<0) return -1; + if (env_val > std::numeric_limits<int>::max()) { + throw invalid_env_value(env_var, std::getenv(env_var)); + } + + int id = static_cast<int>(*env_val); + if (id>=n_device) { + throw arbenv::no_such_gpu(id); + } + + return id; + } + + return n_device>0? 0: -1; +} + +#else + +int default_gpu() { + return -1; +} + +#endif // def ARB_HAVE_GPU + +} // namespace arbenv + diff --git a/arborenv/default_gpu.cpp b/arborenv/default_gpu.cpp deleted file mode 100644 index 1121b13fdedf6e150df3edc53d329918deafcf0e..0000000000000000000000000000000000000000 --- a/arborenv/default_gpu.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifdef ARB_HAVE_GPU - -#include "gpu_api.hpp" - -namespace arbenv { - -// When arbor does not have CUDA support, return -1, which always -// indicates that no GPU is available. -int default_gpu() { - int n; - if (get_device_count(&n)) { - // if 1 or more GPUs, take the first one. - // else return -1 -> no gpu. - return n? 0: -1; - } - return -1; -} - -} // namespace arbenv - -#else // ifdef ARB_HAVE_GPU - -namespace arbenv { - -int default_gpu() { - return -1; -} - -} // namespace arbenv - -#endif // ifdef ARB_HAVE_GPU - diff --git a/arborenv/include/arborenv/arbenvexcept.hpp b/arborenv/include/arborenv/arbenvexcept.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b140ccfec61a2a2095642dd502a7a1e484c0996 --- /dev/null +++ b/arborenv/include/arborenv/arbenvexcept.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <stdexcept> +#include <string> + +// Arborenv-specific exception hierarchy. + +namespace arbenv { + +// Common base-class for arborenv run-time errors. + +struct arborenv_exception: std::runtime_error { + arborenv_exception(const std::string& what_arg): + std::runtime_error(what_arg) + {} +}; + +// Environment variable parsing errors. + +struct invalid_env_value: arborenv_exception { + invalid_env_value(const std::string& variable, const std::string& value); + std::string env_variable; + std::string env_value; +}; + +// GPU enumeration, selection. + +struct no_such_gpu: arborenv_exception { + no_such_gpu(int gpu_id); + int gpu_id; +}; + +struct gpu_uuid_error: arborenv_exception { + gpu_uuid_error(std::string what); +}; + +} // namespace arbenv diff --git a/arborenv/include/arborenv/concurrency.hpp b/arborenv/include/arborenv/concurrency.hpp index 2aa0b7709306f567a1a6c30ba51d93c00a4418de..25b0f7ac2ad1c1eeea11f32291e9097d62ec9d09 100644 --- a/arborenv/include/arborenv/concurrency.hpp +++ b/arborenv/include/arborenv/concurrency.hpp @@ -4,27 +4,10 @@ namespace arbenv { -// Test environment variables for user-specified count of threads. -// Potential environment variables are tested in this order: -// 1. use the environment variable specified by ARB_NUM_THREADS_VAR -// 2. use ARB_NUM_THREADS -// 3. use OMP_NUM_THREADS -// -// Valid values for the environment variable are: -// 0 : Arbor is responsible for picking the number of threads. -// >0 : The number of threads to use. -// -// Returns: -// >0 : the number of threads set by environment variable. -// 0 : value is not set in environment variable. -// -// Throws std::runtime_error: -// Environment variable is set with invalid value. -unsigned get_env_num_threads(); - -// Take a best guess at the number of threads that can be run concurrently. +// Attempt to determine number of available threads that can be run concurrently. // Will return at least 1. -unsigned thread_concurrency(); + +unsigned long thread_concurrency(); // The list of logical processors for which the calling thread has affinity. // If calling from the main thread at application start up, before @@ -35,6 +18,7 @@ unsigned thread_concurrency(); // // Returns an empty vector if unable to determine the number of // available cores. + std::vector<int> get_affinity(); } // namespace arbenv diff --git a/arborenv/include/arborenv/default_env.hpp b/arborenv/include/arborenv/default_env.hpp new file mode 100644 index 0000000000000000000000000000000000000000..843503b678ef1b6a0e87bdd9547f319c428a897a --- /dev/null +++ b/arborenv/include/arborenv/default_env.hpp @@ -0,0 +1,49 @@ +#pragma once + +// Use heuristics, environment variables to determine a suitable context +// proc_allocation. + +#include <arbor/context.hpp> + +#include <arborenv/arbenvexcept.hpp> +#include <arborenv/concurrency.hpp> +#include <arborenv/gpu_env.hpp> + +namespace arbenv { + +// Best-effort heuristics for thread utilization: use ARBENV_NUM_THREADS value +// if set and non-zero, throwing arbev::invalid_env_value if it has an invalid +// value, or else return the value determined by arbenv::thread_concurrency(). + +unsigned long default_concurrency(); + +// If Arbor is built without GPU support, return -1. +// +// If the ARBENV_GPU_ID environment variable is set, return -1 if it is less +// than zero (indicating no GPU should be used), or its integer value if it is +// a valid GPU device id. +// +// If ARBENV_GPU_ID is not set or empty, return 0 if 0 is a valid GPU device +// id, and -1 otherwise. +// +// Throws arbenv::invalid_env_value if ARBENV_GPU_ID is not an int value, or +// arbenv::no_such_gpu if it doesn't correspond to a valid GPU id. + +int default_gpu(); + +// Construct default proc_allocation from `default_concurrency()` and +// `default_gpu()`. + +inline arb::proc_allocation default_allocation() { + return arb::proc_allocation{static_cast<unsigned>(default_concurrency()), default_gpu()}; +} + +// Retrieve user-specified thread count from ARBENV_NUM_THREADS environment variable. +// +// * Throws arbenv::invalid_env_value if ARBENV_NUM_THREADS is set but contains a +// non-numeric, non-positive, or out of range value. +// * Returns zero if ARBENV_NUM_THREADS is unset, or set and empty. + +unsigned long get_env_num_threads(); + +} // namespace arbenv diff --git a/arborenv/include/arborenv/gpu_env.hpp b/arborenv/include/arborenv/gpu_env.hpp index 9db867af75d5da3d574123aba91d0f887b95e66f..2aefde7bae60862997405ce1595de5521ad14028 100644 --- a/arborenv/include/arborenv/gpu_env.hpp +++ b/arborenv/include/arborenv/gpu_env.hpp @@ -2,8 +2,6 @@ namespace arbenv { -int default_gpu(); - template <typename Comm> int find_private_gpu(Comm comm); diff --git a/arborenv/private_gpu.cpp b/arborenv/private_gpu.cpp index f029157112bfa0c06ec827aabb2c3a9a6bcea29f..23376454506a215669638bb6866d0e84bade1b54 100644 --- a/arborenv/private_gpu.cpp +++ b/arborenv/private_gpu.cpp @@ -5,6 +5,7 @@ #include <mpi.h> +#include <arborenv/arbenvexcept.hpp> #include <arborenv/gpu_env.hpp> #include "gpu_uuid.hpp" @@ -45,10 +46,10 @@ int find_private_gpu(MPI_Comm comm) { if (test_global_error(local_error)) { if (local_error) { - throw std::runtime_error("unable to detect the unique id of visible GPUs: " + msg); + throw gpu_uuid_error("unable to detect the unique id of visible GPUs: " + msg); } else { - throw std::runtime_error("unable to detect the unique id of visible GPUs: error on another MPI rank"); + throw gpu_uuid_error("unable to detect the unique id of visible GPUs: error on another MPI rank"); } } @@ -83,9 +84,9 @@ int find_private_gpu(MPI_Comm comm) { auto gpu = assign_gpu(global_uuids, gpu_partition, rank); if (test_global_error(gpu.error)) { - throw std::runtime_error( - "Unable to assign a unique GPU to MPI rank: the CUDA_VISIBLE_DEVICES" - " environment variable is likely incorrectly configured." ); + throw gpu_uuid_error( + "unable to assign a unique GPU to MPI rank: the CUDA_VISIBLE_DEVICES" + " environment variable is likely incorrectly configured" ); } return gpu.id; diff --git a/arborenv/read_envvar.cpp b/arborenv/read_envvar.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a39bf453e18ac955151cfd37365be7647d3bda7a --- /dev/null +++ b/arborenv/read_envvar.cpp @@ -0,0 +1,49 @@ +#include <cerrno> +#include <cstdlib> +#include <optional> +#include <stdexcept> +#include <string> + +#include <arborenv/arbenvexcept.hpp> +#include "read_envvar.hpp" + +using namespace std::literals; + +namespace arbenv { + +static std::optional<long long> read_env_integer_(const char* env_var, bool throw_on_err) { + const char* str = std::getenv(env_var); + if (!str || !*str) return std::nullopt; + + char* end = 0; + errno = 0; + long long v = std::strtoll(str, &end, 10); + bool out_of_range = errno==ERANGE; + errno = 0; + + if (out_of_range && throw_on_err) { + throw invalid_env_value(env_var, str); + } + + while (*end && std::isspace(*end)) ++end; + if (*end) { + if (throw_on_err) { + throw invalid_env_value(env_var, str); + } + else { + return std::nullopt; + } + } + + return v; +} + +std::optional<long long> read_env_integer(const char* env_var) { + return read_env_integer_(env_var, false); +} + +std::optional<long long> read_env_integer(const char* env_var, throw_on_invalid_t) { + return read_env_integer_(env_var, true); +} + +} // namespace arbenv diff --git a/arborenv/read_envvar.hpp b/arborenv/read_envvar.hpp new file mode 100644 index 0000000000000000000000000000000000000000..01f02e079c51348fed7de486c7072cbae530f401 --- /dev/null +++ b/arborenv/read_envvar.hpp @@ -0,0 +1,20 @@ +#include <optional> + +namespace arbenv { + +constexpr struct throw_on_invalid_t {} throw_on_invalid; + +// Return signed integer value represented by supplied environment variable. +// If the environment variable is unset or empty or does not represent an integer, return std::nullopt. +// If the value does not fit within the range of long long, return LLONG_MIN or LLONG_MAX based on its sign. + +std::optional<long long> read_env_integer(const char* env_var); + +// Return signed integer value represented by supplied environment variable. +// If the environment variable is unset or empty, return std::nullopt. +// If the environment variable does not represent an integer, throw arbenv::invalid_env_value. +// If the value does not fit within the range of long long, throw arbenv::invalid_env_value. + +std::optional<long long> read_env_integer(const char* env_var, throw_on_invalid_t); + +} // namespace arbenv diff --git a/doc/cpp/hardware.rst b/doc/cpp/hardware.rst index bf0dbf6ac69603c86f20d2644836364d2f88a5ff..1389039b27bff057ac531e53cd74bee0eb7ef573 100644 --- a/doc/cpp/hardware.rst +++ b/doc/cpp/hardware.rst @@ -21,23 +21,24 @@ separation of concerns, so that users have full control over how hardware resour are selected, either using the functions and types in *libarborenv*, or writing their own code for managing MPI, GPUs, and thread counts. +Functions for determining environment defaults based on system information and +user-supplied values in environment values are in the header ``arborenv/default_env.hpp``. + .. cpp:namespace:: arbenv -.. cpp:function:: arb::util::optional<int> get_env_num_threads() +.. cpp:function:: unsigned long get_env_num_threads() - Tests whether the number of threads to use has been set in an environment variable. - First checks ``ARB_NUM_THREADS``, and if that is not set checks ``OMP_NUM_THREADS``. + Retrieve user-specified number of threads to use from the environment variable + ARBENV_NUM_THREADS. Return value: - * **no value**: the :cpp:any:`optional` return value contains no value if the - no thread count was specified by an environment variable. - * **has value**: the number of threads set by the environment variable. + * Returns zero if ARBENV_NUM_THREADS is unset or empty. + * Returns positive unsigned long value on ARBENV_NUM_THREADS if set. Throws: - * throws :cpp:any:`std::runtime_error` if environment variable set with invalid - number of threads. + * Throws :cpp:any:`arbenv::invalid_env_value` if ARBENV_NUM_THREADS is set, non-empty, and not a valid representation of a positive unsigned long value. .. container:: example-code @@ -49,48 +50,47 @@ own code for managing MPI, GPUs, and thread counts. std::cout << "requested " << nt.value() << "threads \n"; } else { - std::cout << "no environment variable set\n"; + std::cout << "environment variable empty or unset\n"; } -.. cpp:function:: int thread_concurrency() - - Attempts to detect the number of available CPU cores. Returns 1 if unable to detect - the number of cores. - - .. container:: example-code +.. cpp:function:: arb::proc_allocation default_allocation() - .. code-block:: cpp + Return a :cpp:any:`proc_allocation` with thread count from :cpp:any:`default_concurrency()` + and gpu id from :cpp:any:`default_gpu()`. - #include <arborenv/concurrency.hpp> +.. cpp:function:: unsigned long default_concurrency() - // Set num_threads to value from environment variable if set, - // otherwise set it to the available number of cores. - int num_threads = 0; - if (auto nt = arbenv::get_env_num_threads()) { - num_threads = nt.value(); - } - else { - num_threads = arbenv::thread_concurrency(); - } + Returns number of threads to use from :cpp:any:`get_env_num_threads()`, or else from + :cpp:any:`thread_concurrency()` if :cpp:any:`get_env_num_threads()` returns zero. .. cpp:function:: int default_gpu() - Returns the integer identifier of the first available GPU, if a GPU is available + Determine GPU id to use from the ARBENV_GPU_ID environment variable, or from the first available + GPU id of those detected. Return value: - * **non-negative value**: if a GPU is available, the index of the selected GPU is returned. The index will be in the range ``[0, num_gpus)`` where ``num_gpus`` is the number of GPUs detected using the ``cudaGetDeviceCount`` `CUDA API call <https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html>`_. - * **-1**: if no GPU available, or if Arbor was built without GPU support. + * Return -1 if Arbor has no GPU support, or if the ARBENV_GPU_ID environment variable is set to a negative number, or if ARBENV_GPU_ID is empty or unset and no GPUs are detected. + * Return a non-negative GPU id equal to ARBENV_GPU_ID if it is set to a non-negative value that is a valid GPU id, or else to the first valid GPU id detected (typically zero). - .. container:: example-code + Throws: - .. code-block:: cpp + * Throws :cpp:any:`arbenv::invalid_env_value` if ARBENV_GPU_ID contains a non-integer value. + * Throws :cpp:any:`arbenv::no_such_gpu` if ARBENV_GPU_ID contains a non-negative integer that does not correspond to a detected GPU. - #include <arborenv/gpu_env.hpp> +The header ``arborenv/concurrency.hpp`` supplies lower-level functions for querying the threading environment. - if (arbenv::default_gpu()>-1) {} - std::cout << "a GPU is available\n"; - } +.. cpp:function:: unsigned long thread_concurrency() + + Attempts to detect the number of available CPU cores. Returns 1 if unable to detect + the number of cores. + +.. cpp:function:: std::vector<int> get_affinity() + + Returns the list of logical processor ids where the calling thread has affinity, + or an empty vector if unable to determine. + +The header ``arborenv/gpu_env.hpp`` supplies lower-level functions for queruing the GPU environment. .. cpp:function:: int find_private_gpu(MPI_Comm comm) @@ -119,10 +119,13 @@ own code for managing MPI, GPUs, and thread counts. Throws: - * :cpp:any:`std::runtime_error`: if there was an error in the CUDA runtime + * :cpp:any:`arbenv::gpu_uuid_error`: if there was an error in the CUDA runtime on the local or remote MPI ranks, i.e. if one rank throws, all ranks will throw. +The header ``arborenv/with_mpi.hpp`` provides an RAII interface for initializing MPI +and handling exceptions on MPI exit. + .. cpp:class:: with_mpi The :cpp:class:`with_mpi` type is a simple RAII scoped guard for MPI initialization @@ -186,6 +189,10 @@ own code for managing MPI, GPUs, and thread counts. return 0; } +Functions and methods in the ``arborenv`` library may throw exceptions specific to the library. +These are declared in the ``arborenv/arbenvexcept.hpp`` header, and all derive from the +class ``arborenv::arborenv_exception``, itself derived from ``std::runtime_error``. + libarbor ------------------- diff --git a/example/bench/bench.cpp b/example/bench/bench.cpp index 9006af75562143446b8005f68985248f93cc591c..0d6fb97679be57675881846ba1db1f6d143ba621 100644 --- a/example/bench/bench.cpp +++ b/example/bench/bench.cpp @@ -18,8 +18,7 @@ #include <arbor/simulation.hpp> #include <arbor/version.hpp> - -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include <arborenv/gpu_env.hpp> #include <sup/ioutil.hpp> @@ -135,22 +134,14 @@ int main(int argc, char** argv) { bool is_root = true; try { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - #ifdef ARB_MPI_ENABLED arbenv::with_mpi guard(argc, argv, false); - resources.gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); - auto context = arb::make_context(resources, MPI_COMM_WORLD); + auto num_threads = arbenv::default_concurrency(); + auto gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); + auto context = arb::make_context({num_threads, gpu_id}, MPI_COMM_WORLD); is_root = arb::rank(context) == 0; #else - resources.gpu_id = arbenv::default_gpu(); - auto context = arb::make_context(resources); + auto context = arb::make_context(arbenv::default_allocation()); #endif #ifdef ARB_PROFILE_ENABLED profile::profiler_initialize(context); diff --git a/example/brunel/brunel.cpp b/example/brunel/brunel.cpp index 40029aa0e16a4126f9215362539fda817d353078..4343e5933e2f72352eacd1bf06cae4afbd1e06a0 100644 --- a/example/brunel/brunel.cpp +++ b/example/brunel/brunel.cpp @@ -22,7 +22,7 @@ #include <arbor/simulation.hpp> #include <arbor/version.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include <arborenv/gpu_env.hpp> #include <sup/ioutil.hpp> @@ -184,22 +184,14 @@ int main(int argc, char** argv) { bool root = true; try { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - #ifdef ARB_MPI_ENABLED arbenv::with_mpi guard(argc, argv, false); - resources.gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); - auto context = arb::make_context(resources, MPI_COMM_WORLD); + unsigned num_threads = arbenv::default_concurrency(); + int gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); + auto context = arb::make_context(arb::proc_allocation{num_threads, gpu_id}, MPI_COMM_WORLD); root = arb::rank(context)==0; #else - resources.gpu_id = arbenv::default_gpu(); - auto context = arb::make_context(resources); + auto context = arb::make_context(arbenv::default_allocation()); #endif std::cout << sup::mask_stream(root); diff --git a/example/gap_junctions/gap_junctions.cpp b/example/gap_junctions/gap_junctions.cpp index c11802dcc3c591608cdbc68c9c42b5e62bbe0a91..d1ea8f6fd87be141a20baa331a513bfe47c031cf 100644 --- a/example/gap_junctions/gap_junctions.cpp +++ b/example/gap_junctions/gap_junctions.cpp @@ -25,7 +25,7 @@ #include <arbor/recipe.hpp> #include <arbor/version.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include <arborenv/gpu_env.hpp> #include <sup/ioutil.hpp> @@ -135,26 +135,18 @@ int main(int argc, char** argv) { try { bool root = true; - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - #ifdef ARB_MPI_ENABLED arbenv::with_mpi guard(argc, argv, false); - resources.gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); - auto context = arb::make_context(resources, MPI_COMM_WORLD); + unsigned nt = arbenv::default_concurrency(); + int gpu_id = arbenv::find_private_gpu(MPI_COMM_WORLD); + auto context = arb::make_context(arb::proc_allocation{nt, gpu_id}, MPI_COMM_WORLD); { int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); root = rank==0; } #else - resources.gpu_id = arbenv::default_gpu(); - auto context = arb::make_context(resources); + auto context = arb::make_context(arbenv::default_allocation()); #endif #ifdef ARB_PROFILE_ENABLED diff --git a/example/ring/ring.cpp b/example/ring/ring.cpp index 5e9c187e9e87a16225296aaed4069af573589c51..8e66f2ef2ea9fbb1547d17ab8965768ef42bf5a4 100644 --- a/example/ring/ring.cpp +++ b/example/ring/ring.cpp @@ -26,7 +26,7 @@ #include <arbor/recipe.hpp> #include <arbor/version.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include <arborenv/gpu_env.hpp> #include <sup/ioutil.hpp> @@ -128,12 +128,7 @@ int main(int argc, char** argv) { bool root = true; arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } + resources.num_threads = arbenv::default_concurrency(); #ifdef ARB_MPI_ENABLED arbenv::with_mpi guard(argc, argv, false); diff --git a/test/unit/test_domain_decomposition.cpp b/test/unit/test_domain_decomposition.cpp index b2f0db19d7041bc2799da66df447140a17dbdabf..2d71b23990634da22a07525ec4031d67a7d232f1 100644 --- a/test/unit/test_domain_decomposition.cpp +++ b/test/unit/test_domain_decomposition.cpp @@ -6,7 +6,7 @@ #include <arbor/domain_decomposition.hpp> #include <arbor/load_balance.hpp> -#include <arborenv/gpu_env.hpp> +#include <arborenv/default_env.hpp> #include "util/span.hpp" diff --git a/test/unit/test_fvm_layout.cpp b/test/unit/test_fvm_layout.cpp index 0d227ee20246978a7e28e2edddc4f7a8d61cb9d1..ac1294fb2c9b1d33f149693ecdf23b708f762efd 100644 --- a/test/unit/test_fvm_layout.cpp +++ b/test/unit/test_fvm_layout.cpp @@ -12,7 +12,7 @@ #include <arborio/label_parse.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include "backends/multicore/fvm.hpp" #include "fvm_lowered_cell.hpp" @@ -609,13 +609,7 @@ TEST(fvm_layout, synapse_targets) { } TEST(fvm_lowered, gj_example_0) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class gap_recipe: public recipe { public: @@ -661,7 +655,7 @@ TEST(fvm_lowered, gj_example_0) { std::vector<cell_gid_type> gids = {0, 1}; - auto D = fvm_cv_discretize(cells, gprop.default_parameters, context); + auto D = fvm_cv_discretize(cells, gprop.default_parameters, *context); auto gj_cvs = fvm_build_gap_junction_cv_map(cells, gids, D); auto cv_0 = D.geometry.location_cv(0, loc_0, cv_prefer::cv_nonempty); @@ -673,7 +667,7 @@ TEST(fvm_lowered, gj_example_0) { EXPECT_EQ(cv_1, gj_cvs.at(cell_member_type{1, 0})); // Check the resolved GJ connections - fvm_cell fvcell(context); + fvm_cell fvcell(*context); gap_recipe rec(cells, gprop); auto fvm_info = fvcell.initialize(gids, rec); @@ -689,7 +683,7 @@ TEST(fvm_lowered, gj_example_0) { EXPECT_EQ(gj1, gj_conns.at(1).front()); // Check the GJ mechanism data - auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, context); + auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, *context); EXPECT_EQ(1u, M.mechanisms.size()); ASSERT_EQ(1u, M.mechanisms.count("gj")); @@ -718,13 +712,7 @@ TEST(fvm_lowered, gj_example_0) { } TEST(fvm_lowered, gj_example_1) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class gap_recipe: public recipe { public: @@ -813,7 +801,7 @@ TEST(fvm_lowered, gj_example_1) { std::vector<cable_cell> cells{c0, c1, c2}; std::vector<cell_gid_type> gids = {0, 1, 2}; - auto D = fvm_cv_discretize(cells, neuron_parameter_defaults, context); + auto D = fvm_cv_discretize(cells, neuron_parameter_defaults, *context); unsigned c0_gj_cv[2], c1_gj_cv[4], c2_gj_cv[3]; for (int i = 0; i<2; ++i) c0_gj_cv[i] = D.geometry.location_cv(0, c0_gj[i], cv_prefer::cv_nonempty); for (int i = 0; i<4; ++i) c1_gj_cv[i] = D.geometry.location_cv(1, c1_gj[i], cv_prefer::cv_nonempty); @@ -833,7 +821,7 @@ TEST(fvm_lowered, gj_example_1) { EXPECT_EQ(c2_gj_cv[2], gj_cvs.at(cell_member_type{2, 2})); // Check the resolved GJ connections - fvm_cell fvcell(context); + fvm_cell fvcell(*context); gap_recipe rec(cells, gprop); auto fvm_info = fvcell.initialize(gids, rec); @@ -866,7 +854,7 @@ TEST(fvm_lowered, gj_example_1) { EXPECT_EQ(expected.at(2), gj_conns.at(2)); // Check the GJ mechanism data - auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, context); + auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, *context); EXPECT_EQ(1u, M.mechanisms.size()); ASSERT_EQ(1u, M.mechanisms.count("gj")); @@ -903,13 +891,7 @@ TEST(fvm_lowered, gj_example_1) { } TEST(fvm_layout, gj_example_2) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class gap_recipe: public recipe { public: @@ -1033,7 +1015,7 @@ TEST(fvm_layout, gj_example_2) { EXPECT_EQ(cvs_5[1], gj_cvs.at(cell_member_type{5, 1})); // Check the resolved GJ connections - fvm_cell fvcell(context); + fvm_cell fvcell(*context); gap_recipe rec(cells, gprop); auto fvm_info = fvcell.initialize(gids, rec); @@ -1080,7 +1062,7 @@ TEST(fvm_layout, gj_example_2) { EXPECT_EQ(expected.at(5), gj_conns.at(5)); // Check the GJ mechanism data - auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, context); + auto M = fvm_build_mechanism_data(gprop, cells, gids, gj_conns, D, *context); EXPECT_EQ(4u, M.mechanisms.size()); ASSERT_EQ(1u, M.mechanisms.count("gj0")); @@ -1150,14 +1132,7 @@ TEST(fvm_layout, gj_example_2) { } TEST(fvm_lowered, cell_group_gj) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class gap_recipe: public recipe { public: @@ -1217,8 +1192,8 @@ TEST(fvm_lowered, cell_group_gj) { gap_recipe rec(cell_group0, cell_group1); - fvm_cell fvcell0(context); - fvm_cell fvcell1(context); + fvm_cell fvcell0(*context); + fvm_cell fvcell1(*context); auto fvm_info_0 = fvcell0.initialize(gids_cg0, rec); auto fvm_info_1 = fvcell1.initialize(gids_cg1, rec); @@ -1226,8 +1201,8 @@ TEST(fvm_lowered, cell_group_gj) { auto num_dom0 = fvcell0.fvm_intdom(rec, gids_cg0, fvm_info_0.cell_to_intdom); auto num_dom1 = fvcell1.fvm_intdom(rec, gids_cg1, fvm_info_1.cell_to_intdom); - fvm_cv_discretization D0 = fvm_cv_discretize(cell_group0, neuron_parameter_defaults, context); - fvm_cv_discretization D1 = fvm_cv_discretize(cell_group1, neuron_parameter_defaults, context); + fvm_cv_discretization D0 = fvm_cv_discretize(cell_group0, neuron_parameter_defaults, *context); + fvm_cv_discretization D1 = fvm_cv_discretize(cell_group1, neuron_parameter_defaults, *context); auto gj_cvs_0 = fvm_build_gap_junction_cv_map(cell_group0, gids_cg0, D0); auto gj_cvs_1 = fvm_build_gap_junction_cv_map(cell_group1, gids_cg1, D1); diff --git a/test/unit/test_fvm_lowered.cpp b/test/unit/test_fvm_lowered.cpp index cee09538b14da19158480b20a10d7d3c49c6462c..434a5db473d037f17d8bd6d50765c9fd476100c1 100644 --- a/test/unit/test_fvm_lowered.cpp +++ b/test/unit/test_fvm_lowered.cpp @@ -20,10 +20,9 @@ #include <arbor/mechanism.hpp> #include <arbor/util/any_ptr.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include "backends/multicore/fvm.hpp" -#include "execution_context.hpp" #include "fvm_lowered_cell.hpp" #include "fvm_lowered_cell_impl.hpp" #include "util/meta.hpp" @@ -190,14 +189,7 @@ private: TEST(fvm_lowered, matrix_init) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); auto isnan = [](auto v) { return std::isnan(v); }; auto ispos = [](auto v) { return v>0; }; @@ -207,7 +199,7 @@ TEST(fvm_lowered, matrix_init) builder.add_branch(0, 200, 1.0/2, 1.0/2, 10, "dend"); // 10 compartments cable_cell cell = builder.make_cell(); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, cable1d_recipe(cell)); auto& J = fvcell.*private_matrix_ptr; @@ -230,16 +222,7 @@ TEST(fvm_lowered, matrix_init) } TEST(fvm_lowered, target_handles) { - using namespace arb; - - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context(proc_allocation(arbenv::default_concurrency(), -1)); cable_cell_description descriptions[] = { make_cell_ball_and_stick(), @@ -287,11 +270,11 @@ TEST(fvm_lowered, target_handles) { EXPECT_EQ(1u, targets[3].intdom_index); }; - fvm_cell fvcell0(context); + fvm_cell fvcell0(*context); auto fvm_info0 = fvcell0.initialize({0, 1}, cable1d_recipe(cells, true)); test_target_handles(fvcell0, fvm_info0.target_handles); - fvm_cell fvcell1(context); + fvm_cell fvcell1(*context); auto fvm_info1 = fvcell1.initialize({0, 1}, cable1d_recipe(cells, false)); test_target_handles(fvcell1, fvm_info1.target_handles); @@ -308,14 +291,7 @@ TEST(fvm_lowered, stimulus) { // amplitude | 0.3 | 0.1 // CV | 5 | 0 - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); auto desc = make_cell_ball_and_stick(false); @@ -335,10 +311,10 @@ TEST(fvm_lowered, stimulus) { cable_cell_global_properties gprop; gprop.default_parameters = neuron_parameter_defaults; - fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters, context); + fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters, *context); const auto& A = D.cv_area; - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, cable1d_recipe(cells)); auto& state = *(fvcell.*private_state_ptr).get(); @@ -380,7 +356,7 @@ TEST(fvm_lowered, stimulus) { TEST(fvm_lowered, ac_stimulus) { // Simple cell (one CV) with oscillating stimulus. - arb::execution_context context; // Just use default context for this one! + auto context = make_context(); // Just use default context for this one! decor dec; segment_tree tree; @@ -398,10 +374,10 @@ TEST(fvm_lowered, ac_stimulus) { cable_cell_global_properties gprop; gprop.default_parameters = neuron_parameter_defaults; - fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters, context); + fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters, *context); const auto& A = D.cv_area; - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, cable1d_recipe(cells)); auto& state = *(fvcell.*private_state_ptr).get(); @@ -440,13 +416,7 @@ TEST(fvm_lowered, derived_mechs) { // // 3. Cell with both test_kin1 and custom_kin1. - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } + auto context = make_context({arbenv::default_concurrency(), -1}); std::vector<cable_cell> cells; cells.reserve(3); @@ -482,8 +452,7 @@ TEST(fvm_lowered, derived_mechs) { { // Test initialization and global parameter values. - arb::execution_context context(resources); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0, 1, 2}, rec); // Both mechanisms will have the same internal name, "test_kin1". @@ -517,9 +486,8 @@ TEST(fvm_lowered, derived_mechs) { float times[] = {10.f, 20.f}; - auto ctx = make_context(resources); - auto decomp = partition_load_balance(rec, ctx); - simulation sim(rec, decomp, ctx); + auto decomp = partition_load_balance(rec, context); + simulation sim(rec, decomp, context); sim.add_sampler(all_probes, explicit_schedule(times), sampler); sim.run(30.0, 1.f/1024); @@ -536,13 +504,7 @@ TEST(fvm_lowered, derived_mechs) { } TEST(fvm_lowered, null_region) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } + auto context = make_context({arbenv::default_concurrency(), -1}); soma_cell_builder builder(6); builder.add_branch(0, 100, 0.5, 0.5, 4, "dend"); @@ -555,9 +517,8 @@ TEST(fvm_lowered, null_region) { rec.catalogue() = make_unit_test_catalogue(); rec.catalogue().derive("custom_kin1", "test_kin1", {{"tau", 20.0}}); - auto ctx = make_context(resources); - auto decomp = partition_load_balance(rec, ctx); - simulation sim(rec, decomp, ctx); + auto decomp = partition_load_balance(rec, context); + simulation sim(rec, decomp, context); EXPECT_NO_THROW(sim.run(30.0, 1.f/1024)); } @@ -565,13 +526,7 @@ TEST(fvm_lowered, null_region) { // Test that ion charge is propagated into mechanism variable. TEST(fvm_lowered, read_valence) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } + auto context = make_context({arbenv::default_concurrency(), -1}); { std::vector<cable_cell> cells(1); @@ -582,8 +537,7 @@ TEST(fvm_lowered, read_valence) { cable1d_recipe rec(cable_cell{cell}); rec.catalogue() = make_unit_test_catalogue(); - arb::execution_context context(resources); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, rec); // test_ca_read_valence initialization should write ca ion valence @@ -607,8 +561,7 @@ TEST(fvm_lowered, read_valence) { rec.catalogue().derive("cr_read_valence", "na_read_valence", {}, {{"na", "mn"}}); rec.add_ion("mn", 7, 0, 0, 0); - arb::execution_context context(resources); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, rec); auto cr_mech_ptr = find_mechanism(fvcell, 0); @@ -682,14 +635,7 @@ TEST(fvm_lowered, ionic_concentrations) { } TEST(fvm_lowered, ionic_currents) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); soma_cell_builder b(6); @@ -717,7 +663,7 @@ TEST(fvm_lowered, ionic_currents) { cable1d_recipe rec({cable_cell{c}}); rec.catalogue() = make_unit_test_catalogue(); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, rec); auto& state = *(fvcell.*private_state_ptr).get(); @@ -737,14 +683,7 @@ TEST(fvm_lowered, ionic_currents) { // Test correct scaling of an ionic current updated via a point mechanism TEST(fvm_lowered, point_ionic_current) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); double r = 6.0; // [µm] soma_cell_builder b(r); @@ -758,7 +697,7 @@ TEST(fvm_lowered, point_ionic_current) { cable1d_recipe rec({cable_cell{c}}); rec.catalogue() = make_unit_test_catalogue(); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, rec); // Only one target, corresponding to our point process on soma. @@ -806,14 +745,7 @@ TEST(fvm_lowered, weighted_write_ion) { // the same as a 100 µm dendrite, which makes it easier to describe the // expected weights. - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); soma_cell_builder b(5); b.add_branch(0, 100, 0.5, 0.5, 1, "dend"); @@ -835,7 +767,7 @@ TEST(fvm_lowered, weighted_write_ion) { rec.catalogue() = make_unit_test_catalogue(); rec.add_ion("ca", 2, con_int, con_ext, 0.0); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize({0}, rec); auto& state = *(fvcell.*private_state_ptr).get(); @@ -875,8 +807,8 @@ TEST(fvm_lowered, weighted_write_ion) { TEST(fvm_lowered, integration_domains) { { - execution_context context; - fvm_cell fvcell(context); + auto context = make_context(); + fvm_cell fvcell(*context); std::vector<cell_gid_type> gids = {11u, 5u, 2u, 3u, 0u, 8u, 7u}; std::vector<fvm_index_type> cell_to_intdom; @@ -888,8 +820,8 @@ TEST(fvm_lowered, integration_domains) { EXPECT_EQ(expected_doms, cell_to_intdom); } { - execution_context context; - fvm_cell fvcell(context); + auto context = make_context(); + fvm_cell fvcell(*context); std::vector<cell_gid_type> gids = {11u, 5u, 2u, 3u, 0u, 8u, 7u}; std::vector<fvm_index_type> cell_to_intdom; @@ -901,8 +833,8 @@ TEST(fvm_lowered, integration_domains) { EXPECT_EQ(expected_doms, cell_to_intdom); } { - execution_context context; - fvm_cell fvcell(context); + auto context = make_context(); + fvm_cell fvcell(*context); std::vector<cell_gid_type> gids = {5u, 2u, 3u, 0u}; std::vector<fvm_index_type> cell_to_intdom; @@ -916,13 +848,7 @@ TEST(fvm_lowered, integration_domains) { } TEST(fvm_lowered, post_events_shared_state) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class detector_recipe: public arb::recipe { public: @@ -989,7 +915,7 @@ TEST(fvm_lowered, post_events_shared_state) { for (const auto& detectors_per_cell: detectors_per_cell_vec) { detector_recipe rec(cv_per_cell, detectors_per_cell, "post_events_syn"); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize(gids, rec); auto& S = fvcell.*private_state_ptr; @@ -1010,7 +936,7 @@ TEST(fvm_lowered, post_events_shared_state) { for (const auto& detectors_per_cell: detectors_per_cell_vec) { detector_recipe rec(cv_per_cell, detectors_per_cell, "expsyn"); - fvm_cell fvcell(context); + fvm_cell fvcell(*context); fvcell.initialize(gids, rec); auto& S = fvcell.*private_state_ptr; @@ -1022,13 +948,7 @@ TEST(fvm_lowered, post_events_shared_state) { } TEST(fvm_lowered, label_data) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } else { - resources.num_threads = arbenv::thread_concurrency(); - } - arb::execution_context context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); class decorated_recipe: public arb::recipe { public: @@ -1101,7 +1021,7 @@ TEST(fvm_lowered, label_data) { std::vector<target_handle> targets; probe_association_map probe_map; - fvm_cell fvcell(context); + fvm_cell fvcell(*context); auto fvm_info = fvcell.initialize(gids, rec); for (auto gid: gids) { diff --git a/test/unit/test_mc_cell_group_gpu.cpp b/test/unit/test_mc_cell_group_gpu.cpp index d2bbcd187b60db73d6b9050e5593cfcc07b5331c..25ce0511ee077c8d3faaed9dddd948abc70462ea 100644 --- a/test/unit/test_mc_cell_group_gpu.cpp +++ b/test/unit/test_mc_cell_group_gpu.cpp @@ -2,7 +2,7 @@ #include <arbor/common_types.hpp> #include <arborio/label_parse.hpp> -#include <arborenv/gpu_env.hpp> +#include <arborenv/default_env.hpp> #include "epoch.hpp" #include "execution_context.hpp" @@ -16,13 +16,6 @@ using namespace arb; using namespace arborio::literals; namespace { - fvm_lowered_cell_ptr lowered_cell() { - arb::proc_allocation resources; - resources.gpu_id = arbenv::default_gpu(); - execution_context context(resources); - return make_fvm_lowered_cell(backend_kind::gpu, context); - } - cable_cell_description make_cell() { soma_cell_builder builder(12.6157/2.0); builder.add_branch(0, 200, 0.5, 0.5, 101, "dend"); @@ -37,6 +30,8 @@ namespace { TEST(mc_cell_group, gpu_test) { + auto context = make_context({1, arbenv::default_gpu()}); + cable_cell cell = make_cell(); auto rec = cable1d_recipe({cell}); rec.nernst_ion("na"); @@ -44,7 +39,7 @@ TEST(mc_cell_group, gpu_test) rec.nernst_ion("k"); cell_label_range srcs, tgts; - mc_cell_group group{{0}, rec, srcs, tgts, lowered_cell()}; + mc_cell_group group{{0}, rec, srcs, tgts, make_fvm_lowered_cell(backend_kind::gpu, *context)}; group.advance(epoch(0, 0., 50.), 0.01, {}); // The model is expected to generate 4 spikes as a result of the diff --git a/test/unit/test_probe.cpp b/test/unit/test_probe.cpp index dca9870b37d9efcab01056e273ef6b7f1cbf22fa..02b570b1219ab12a987cb2bbcc73f3b83c96bf44 100644 --- a/test/unit/test_probe.cpp +++ b/test/unit/test_probe.cpp @@ -18,9 +18,10 @@ #include <arbor/util/any_ptr.hpp> #include <arbor/util/pp_util.hpp> #include <arbor/version.hpp> -#include <arborenv/gpu_env.hpp> #include <arbor/mechanism.hpp> +#include <arborenv/default_env.hpp> + #include "backends/event.hpp" #include "backends/multicore/fvm.hpp" #ifdef ARB_GPU_ENABLED diff --git a/test/unit/test_recipe.cpp b/test/unit/test_recipe.cpp index 37d1a7c729a5f1a5bdb33dbf41da9fc4ac2d7197..f630f851f097fc16faa12ede8015176f012e1070 100644 --- a/test/unit/test_recipe.cpp +++ b/test/unit/test_recipe.cpp @@ -10,7 +10,7 @@ #include <arbor/recipe.hpp> #include <arbor/simulation.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include "util/span.hpp" @@ -94,14 +94,7 @@ namespace { TEST(recipe, gap_junctions) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - auto context = make_context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); auto cell_0 = custom_cell(0, 0, 3); auto cell_1 = custom_cell(0, 0, 3); @@ -140,14 +133,7 @@ TEST(recipe, gap_junctions) TEST(recipe, connections) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - auto context = make_context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); auto cell_0 = custom_cell(1, 2, 0); auto cell_1 = custom_cell(2, 1, 0); @@ -211,14 +197,7 @@ TEST(recipe, connections) } TEST(recipe, event_generators) { - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - auto context = make_context(resources); + auto context = make_context({arbenv::default_concurrency(), -1}); auto cell_0 = custom_cell(1, 2, 0); auto cell_1 = custom_cell(2, 1, 0); diff --git a/test/unit/test_spike_store.cpp b/test/unit/test_spike_store.cpp index 6cb37be8b06bf356a4980999f26417ec429ebd34..17fa46b93e0dbf4936175a0670604c34abeb62a5 100644 --- a/test/unit/test_spike_store.cpp +++ b/test/unit/test_spike_store.cpp @@ -1,7 +1,7 @@ #include "../gtest.h" #include <arbor/spike.hpp> -#include <arborenv/concurrency.hpp> +#include <arborenv/default_env.hpp> #include "execution_context.hpp" #include "thread_private_spike_store.hpp" @@ -12,15 +12,7 @@ TEST(spike_store, insert) { using store_type = arb::thread_private_spike_store; - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - - arb::execution_context context(resources); + arb::execution_context context({arbenv::default_concurrency(), -1}); store_type store(context.thread_pool); // insert 3 spike events and check that they were inserted correctly @@ -65,15 +57,7 @@ TEST(spike_store, clear) { using store_type = arb::thread_private_spike_store; - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - - arb::execution_context context(resources); + arb::execution_context context({arbenv::default_concurrency(), -1}); store_type store(context.thread_pool); // insert 3 spike events @@ -89,15 +73,7 @@ TEST(spike_store, gather) { using store_type = arb::thread_private_spike_store; - arb::proc_allocation resources; - if (auto nt = arbenv::get_env_num_threads()) { - resources.num_threads = nt; - } - else { - resources.num_threads = arbenv::thread_concurrency(); - } - - arb::execution_context context(resources); + arb::execution_context context({arbenv::default_concurrency(), -1}); store_type store(context.thread_pool); std::vector<spike> spikes =