diff --git a/vtkm/cont/Initialize.cxx b/vtkm/cont/Initialize.cxx index f99135dcf..cf0bb042d 100644 --- a/vtkm/cont/Initialize.cxx +++ b/vtkm/cont/Initialize.cxx @@ -15,10 +15,6 @@ #include #include -#if defined(VTKM_ENABLE_KOKKOS) -#include -#endif - #include #include @@ -128,12 +124,6 @@ InitializeResult Initialize(int& argc, char* argv[], InitializeOptions opts) vtkm::cont::InitLogging(argc, argv, loggingFlag); } - -#ifdef VTKM_ENABLE_KOKKOS - // TODO: remove this once runtime config updates are completely implemented - vtkm::cont::kokkos::internal::Initialize(argc, argv); -#endif - { // Parse VTKm options std::vector usage; if ((opts & InitializeOptions::AddHelp) != InitializeOptions::None) diff --git a/vtkm/cont/RuntimeDeviceInformation.cxx b/vtkm/cont/RuntimeDeviceInformation.cxx index 50b2ed0f1..bd97adae0 100644 --- a/vtkm/cont/RuntimeDeviceInformation.cxx +++ b/vtkm/cont/RuntimeDeviceInformation.cxx @@ -92,20 +92,20 @@ public: } VTKM_CONT virtual vtkm::cont::internal::RuntimeDeviceConfigReturnCode SetThreads( - const vtkm::Id&) const override final + const vtkm::Id&) override final { throw vtkm::cont::ErrorBadDevice("Tried to set the number of threads on an invalid device"); } VTKM_CONT virtual vtkm::cont::internal::RuntimeDeviceConfigReturnCode SetNumaRegions( - const vtkm::Id&) const override final + const vtkm::Id&) override final { throw vtkm::cont::ErrorBadDevice( "Tried to set the number of numa regions on an invalid device"); } VTKM_CONT virtual vtkm::cont::internal::RuntimeDeviceConfigReturnCode SetDeviceInstance( - const vtkm::Id&) const override final + const vtkm::Id&) override final { throw vtkm::cont::ErrorBadDevice("Tried to set the device instance on an invalid device"); } @@ -128,6 +128,18 @@ public: { throw vtkm::cont::ErrorBadDevice("Tried to get the device instance on an invalid device"); } + + VTKM_CONT virtual vtkm::cont::internal::RuntimeDeviceConfigReturnCode GetMaxThreads( + vtkm::Id&) const override final + { + throw vtkm::cont::ErrorBadDevice("Tried to get the max number of threads on an invalid device"); + } + + VTKM_CONT virtual vtkm::cont::internal::RuntimeDeviceConfigReturnCode GetMaxDevices( + vtkm::Id&) const override final + { + throw vtkm::cont::ErrorBadDevice("Tried to get the max number of devices on an invalid device"); + } }; diff --git a/vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h b/vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h index abc1cc9f2..a4369e915 100644 --- a/vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h +++ b/vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h @@ -29,8 +29,7 @@ class RuntimeDeviceConfiguration return vtkm::cont::DeviceAdapterTagCuda{}; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetDeviceInstance( - const vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetDeviceInstance(const vtkm::Id&) override final { // TODO: set the cuda device instance return RuntimeDeviceConfigReturnCode::SUCCESS; @@ -41,6 +40,11 @@ class RuntimeDeviceConfiguration // TODO: Get the cuda device instance (also maybe a list of available devices?) return RuntimeDeviceConfigReturnCode::SUCCESS; } + + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetMaxDevices(vtkm::Id&) const override final + { + return RuntimeDeviceConfigReturnCode::SUCCESS; + } }; } // namespace vtkm::cont::internal } // namespace vtkm::cont diff --git a/vtkm/cont/internal/RuntimeDeviceConfiguration.cxx b/vtkm/cont/internal/RuntimeDeviceConfiguration.cxx index 03ba320d0..b47b3db02 100644 --- a/vtkm/cont/internal/RuntimeDeviceConfiguration.cxx +++ b/vtkm/cont/internal/RuntimeDeviceConfiguration.cxx @@ -7,6 +7,7 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include namespace vtkm @@ -16,52 +17,112 @@ namespace cont namespace internal { +namespace +{ +VTKM_CONT +std::string RuntimeDeviceConfigReturnCodeToString(const RuntimeDeviceConfigReturnCode& code) +{ + switch (code) + { + case RuntimeDeviceConfigReturnCode::SUCCESS: + return "SUCCESS"; + case RuntimeDeviceConfigReturnCode::OUT_OF_BOUNDS: + return "OUT_OF_BOUNDS"; + case RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE: + return "INVALID_FOR_DEVICE"; + case RuntimeDeviceConfigReturnCode::INVALID_VALUE: + return "INVALID_VALUE"; + case RuntimeDeviceConfigReturnCode::NOT_APPLIED: + return "NOT_APPLIED"; + default: + return ""; + } +} + +VTKM_CONT +void LogReturnCode(const RuntimeDeviceConfigReturnCode& code, + const std::string& function, + const vtkm::Id& value, + const std::string& deviceName) +{ + // Note that we intentionally are not logging a warning for INVALID_FOR_DEVICE. When a + // user provides a command line argument, it gets sent to all possible devices during + // `Initialize` regardless of whether it is used. The user does not need a lot of + // useless warnings about (for example) the serial device not supporting parameters + // intended for a real parallel device. + if (code != RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE || + code != RuntimeDeviceConfigReturnCode::SUCCESS) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Warn, + function << " for device: " << deviceName << " had code: " + << RuntimeDeviceConfigReturnCodeToString(code) << " with value: " << value); + } +#ifndef VTKM_ENABLE_LOGGING + (void)function; + (void)value; + (void)deviceName; +#endif +} + +template +VTKM_CONT void InitializeOption(RuntimeDeviceOption option, + SetFunc setFunc, + const std::string& funcName, + const std::string& deviceName) +{ + if (option.IsSet()) + { + auto value = option.GetValue(); + auto code = setFunc(value); + LogReturnCode(code, funcName, value, deviceName); + } +} + +} // namespace anonymous + RuntimeDeviceConfigurationBase::~RuntimeDeviceConfigurationBase() noexcept = default; void RuntimeDeviceConfigurationBase::Initialize( - const RuntimeDeviceConfigurationOptions& configOptions) const + const RuntimeDeviceConfigurationOptions& configOptions) { - if (configOptions.VTKmNumThreads.IsSet()) - { - auto value = configOptions.VTKmNumThreads.GetValue(); - auto code = this->SetThreads(value); - this->LogReturnCode(code, "SetThreads", value); - } - if (configOptions.VTKmNumaRegions.IsSet()) - { - auto value = configOptions.VTKmNumaRegions.GetValue(); - auto code = this->SetNumaRegions(value); - this->LogReturnCode(code, "SetNumaRegions", value); - } - if (configOptions.VTKmDeviceInstance.IsSet()) - { - auto value = configOptions.VTKmDeviceInstance.GetValue(); - auto code = this->SetDeviceInstance(value); - this->LogReturnCode(code, "SetDeviceInstance", value); - } + InitializeOption( + configOptions.VTKmNumThreads, + [&](const vtkm::Id& value) { return this->SetThreads(value); }, + "SetThreads", + this->GetDevice().GetName()); + InitializeOption( + configOptions.VTKmNumaRegions, + [&](const vtkm::Id& value) { return this->SetNumaRegions(value); }, + "SetNumaRegions", + this->GetDevice().GetName()); + InitializeOption( + configOptions.VTKmDeviceInstance, + [&](const vtkm::Id& value) { return this->SetDeviceInstance(value); }, + "SetDeviceInstance", + this->GetDevice().GetName()); + this->InitializeSubsystem(); } void RuntimeDeviceConfigurationBase::Initialize( const RuntimeDeviceConfigurationOptions& configOptions, int& argc, - char* argv[]) const + char* argv[]) { this->ParseExtraArguments(argc, argv); this->Initialize(configOptions); } -RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetThreads(const vtkm::Id&) const +RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetThreads(const vtkm::Id&) { return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; } -RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetNumaRegions(const vtkm::Id&) const +RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetNumaRegions(const vtkm::Id&) { return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; } -RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetDeviceInstance( - const vtkm::Id&) const +RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::SetDeviceInstance(const vtkm::Id&) { return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; } @@ -81,35 +142,20 @@ RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::GetDeviceInstance( return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; } -void RuntimeDeviceConfigurationBase::ParseExtraArguments(int&, char*[]) const {} - -void RuntimeDeviceConfigurationBase::LogReturnCode(const RuntimeDeviceConfigReturnCode& code, - const std::string& function, - const vtkm::Id& value) const +RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::GetMaxThreads(vtkm::Id&) const { - // Note that we intentionally are not logging a warning for INVALID_FOR_DEVICE. When a - // user provides a command line argument, it gets sent to all possible devices during - // `Initialize` regardless of whether it is used. The user does not need a lot of - // useless warnings about (for example) the serial device not supporting parameters - // intended for a real parallel device. - if (code == RuntimeDeviceConfigReturnCode::OUT_OF_BOUNDS) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Warn, - function << " for " << this->GetDevice().GetName() - << "was OUT_OF_BOUNDS with value: " << value); - } - else if (code == RuntimeDeviceConfigReturnCode::INVALID_VALUE) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Warn, - function << "for " << this->GetDevice().GetName() - << "had INVLAID_VALUE for value: " << value); - } -#ifndef VTKM_ENABLE_LOGGING - (void)function; - (void)value; -#endif + return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; } +RuntimeDeviceConfigReturnCode RuntimeDeviceConfigurationBase::GetMaxDevices(vtkm::Id&) const +{ + return RuntimeDeviceConfigReturnCode::INVALID_FOR_DEVICE; +} + +void RuntimeDeviceConfigurationBase::ParseExtraArguments(int&, char*[]) {} +void RuntimeDeviceConfigurationBase::InitializeSubsystem() {} + + } // namespace vtkm::cont::internal } // namespace vtkm::cont } // namespace vtkm diff --git a/vtkm/cont/internal/RuntimeDeviceConfiguration.h b/vtkm/cont/internal/RuntimeDeviceConfiguration.h index 794b9074c..f71623d3d 100644 --- a/vtkm/cont/internal/RuntimeDeviceConfiguration.h +++ b/vtkm/cont/internal/RuntimeDeviceConfiguration.h @@ -29,7 +29,8 @@ enum class RuntimeDeviceConfigReturnCode SUCCESS, OUT_OF_BOUNDS, INVALID_FOR_DEVICE, - INVALID_VALUE + INVALID_VALUE, + NOT_APPLIED }; class VTKM_CONT_EXPORT RuntimeDeviceConfigurationBase @@ -44,38 +45,42 @@ public: /// Each `Set*` method is called only if the corresponding vtk-m option is set, and a /// warning is logged based on the value of the `RuntimeDeviceConfigReturnCode` returned /// via the `Set*` method. - VTKM_CONT void Initialize(const RuntimeDeviceConfigurationOptions& configOptions) const; + VTKM_CONT void Initialize(const RuntimeDeviceConfigurationOptions& configOptions); VTKM_CONT void Initialize(const RuntimeDeviceConfigurationOptions& configOptions, int& argc, - char* argv[]) const; + char* argv[]); /// The following public methods should be overriden in each individual device. /// A method should return INVALID_FOR_DEVICE if the overriden device does not /// support the particular set method. - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) const; - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetNumaRegions(const vtkm::Id&) const; - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetDeviceInstance(const vtkm::Id&) const; + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id& value); + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetNumaRegions(const vtkm::Id& value); + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetDeviceInstance(const vtkm::Id& value); + /// The following public methods are overriden in each individual device and store the + /// values that were set via the above Set* methods for the given device. VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetThreads(vtkm::Id& value) const; VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetNumaRegions(vtkm::Id& value) const; VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetDeviceInstance(vtkm::Id& value) const; + /// The following public methods should be overriden as needed for each individual device + /// as they describe various device parameters. + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetMaxThreads(vtkm::Id& value) const; + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetMaxDevices(vtkm::Id& value) const; + protected: /// An overriden method that can be used to perform extra command line argument parsing /// for cases where a specific device may use additional command line arguments. At the /// moment Kokkos is the only device that overrides this method. - VTKM_CONT virtual void ParseExtraArguments(int&, char*[]) const; + /// Note: This method assumes that vtk-m arguments have already been parsed and removed + /// from argv. + VTKM_CONT virtual void ParseExtraArguments(int& argc, char* argv[]); - /// Used during Initialize to log a warning message dependent on the return code when - /// calling a specific `Set*` method. - /// - /// params: - /// code - The code to log a message for - /// function - The name of the `Set*` function the code was returned from - /// value - The value used as the argument to the `Set*` call. - VTKM_CONT virtual void LogReturnCode(const RuntimeDeviceConfigReturnCode& code, - const std::string& function, - const vtkm::Id& value) const; + /// An overriden method that can be used to perform extra initialization after Extra + /// Arguments are parsed and the Initialized ConfigOptions are used to call the various + /// Set* methods at the end of Initialize. Particuarly useful when initializing + /// additional subystems (like Kokkos). + VTKM_CONT virtual void InitializeSubsystem(); }; template diff --git a/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.cxx b/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.cxx index de33076ed..7ebb9c214 100644 --- a/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.cxx +++ b/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.cxx @@ -9,6 +9,9 @@ //============================================================================ #include +#include +#include + namespace vtkm { namespace cont @@ -16,42 +19,83 @@ namespace cont namespace internal { -RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions() - : VTKmNumThreads(option::OptionIndex::NUM_THREADS, "VTKM_NUM_THREADS") - , VTKmNumaRegions(option::OptionIndex::NUMA_REGIONS, "VTKM_NUMA_REGIONS") - , VTKmDeviceInstance(option::OptionIndex::DEVICE_INSTANCE, "VTKM_DEVICE_INSTANCE") - , Initialized(false) +namespace { -} - -RuntimeDeviceConfigurationOptions::~RuntimeDeviceConfigurationOptions() noexcept = default; - -RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions( - std::vector& usage) - : RuntimeDeviceConfigurationOptions() +void AppendOptionDescriptors(std::vector& usage, + const bool& useOptionIndex = true) { usage.push_back( - { option::OptionIndex::NUM_THREADS, + { useOptionIndex ? static_cast(option::OptionIndex::NUM_THREADS) : 0, 0, "", "vtkm-num-threads", option::VtkmArg::Required, " --vtkm-num-threads \tSets the number of threads to use for the selected device" }); usage.push_back( - { option::OptionIndex::NUMA_REGIONS, + { useOptionIndex ? static_cast(option::OptionIndex::NUMA_REGIONS) : 1, 0, "", "vtkm-numa-regions", option::VtkmArg::Required, " --vtkm-numa-regions \tSets the number of numa regions when using kokkos/OpenMP" }); - usage.push_back({ option::OptionIndex::DEVICE_INSTANCE, - 0, - "", - "vtkm-device-instance", - option::VtkmArg::Required, - " --vtkm-device-instance \tSets the device instance to use when using " - "kokkos/cuda" }); + usage.push_back( + { useOptionIndex ? static_cast(option::OptionIndex::DEVICE_INSTANCE) : 2, + 0, + "", + "vtkm-device-instance", + option::VtkmArg::Required, + " --vtkm-device-instance \tSets the device instance to use when using " + "kokkos/cuda" }); } +} // anonymous namespace + +RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions(const bool& useOptionIndex) + : VTKmNumThreads(useOptionIndex ? option::OptionIndex::NUM_THREADS : 0, "VTKM_NUM_THREADS") + , VTKmNumaRegions(useOptionIndex ? option::OptionIndex::NUMA_REGIONS : 1, "VTKM_NUMA_REGIONS") + , VTKmDeviceInstance(useOptionIndex ? option::OptionIndex::DEVICE_INSTANCE : 2, + "VTKM_DEVICE_INSTANCE") + , Initialized(false) +{ +} + +RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions() + : RuntimeDeviceConfigurationOptions(true) +{ +} + + +RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions( + std::vector& usage) + : RuntimeDeviceConfigurationOptions(true) +{ + AppendOptionDescriptors(usage); +} + +RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions(int& argc, char* argv[]) + : RuntimeDeviceConfigurationOptions(false) +{ + std::vector usage; + AppendOptionDescriptors(usage, false); + usage.push_back({ option::OptionIndex::UNKNOWN, 0, "", "", option::VtkmArg::UnknownOption, "" }); + usage.push_back({ 0, 0, 0, 0, 0, 0 }); + + option::Stats stats(usage.data(), argc, argv); + std::unique_ptr options{ new option::Option[stats.options_max] }; + std::unique_ptr buffer{ new option::Option[stats.buffer_max] }; + option::Parser parse(usage.data(), argc, argv, options.get(), buffer.get()); + + if (parse.error()) + { + std::stringstream streamBuffer; + option::printUsage(streamBuffer, usage.data()); + std::cerr << streamBuffer.str(); + exit(1); + } + + this->Initialize(options.get()); +} + +RuntimeDeviceConfigurationOptions::~RuntimeDeviceConfigurationOptions() noexcept = default; void RuntimeDeviceConfigurationOptions::Initialize(const option::Option* options) { diff --git a/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h b/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h index 55a7d7d75..619093b59 100644 --- a/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h +++ b/vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h @@ -30,13 +30,16 @@ namespace internal class VTKM_CONT_EXPORT RuntimeDeviceConfigurationOptions { public: - /// Sets the option indices and environment varaible names for the vtkm supported options. VTKM_CONT RuntimeDeviceConfigurationOptions(); /// Calls the default constructor and additionally pushes back additional command line /// options to the provided usage vector for integration with the vtkm option parser. VTKM_CONT RuntimeDeviceConfigurationOptions(std::vector& usage); + /// Allows the caller to initialize these runtime config arguments directly from + /// command line arguments + VTKM_CONT RuntimeDeviceConfigurationOptions(int& argc, char* argv[]); + VTKM_CONT virtual ~RuntimeDeviceConfigurationOptions() noexcept; /// Calls Initialize for each of this class's current configuration options and marks @@ -48,6 +51,12 @@ public: RuntimeDeviceOption VTKmNumaRegions; RuntimeDeviceOption VTKmDeviceInstance; +protected: + /// Sets the option indices and environment varaible names for the vtkm supported options. + /// If useOptionIndex is set the OptionParserArguments enum for option indices will be used, + /// otherwise ints from 0 - numOptions will be used. + VTKM_CONT RuntimeDeviceConfigurationOptions(const bool& useOptionIndex); + private: bool Initialized; }; diff --git a/vtkm/cont/internal/RuntimeDeviceOption.cxx b/vtkm/cont/internal/RuntimeDeviceOption.cxx index ffeb4b8b4..fee8e0f89 100644 --- a/vtkm/cont/internal/RuntimeDeviceOption.cxx +++ b/vtkm/cont/internal/RuntimeDeviceOption.cxx @@ -10,6 +10,7 @@ #include #include +#include #include @@ -92,6 +93,11 @@ void RuntimeDeviceOption::SetOption(const vtkm::Id& value) vtkm::Id RuntimeDeviceOption::GetValue() const { + if (!this->IsSet()) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Warn, + "GetValue() called on Argument '" << this->EnvName << "' when it was not set."); + } return this->Value; } diff --git a/vtkm/cont/internal/testing/UnitTestRuntimeConfigurationOptions.cxx b/vtkm/cont/internal/testing/UnitTestRuntimeConfigurationOptions.cxx index 4af16f602..f13bf1139 100644 --- a/vtkm/cont/internal/testing/UnitTestRuntimeConfigurationOptions.cxx +++ b/vtkm/cont/internal/testing/UnitTestRuntimeConfigurationOptions.cxx @@ -23,47 +23,12 @@ namespace opt = internal::option; namespace { -static std::vector> envVars{}; - enum { UNKNOWN, TEST }; -template -void MakeArgs(int& argc, char**& argv, T&&... args) -{ - constexpr std::size_t numArgs = sizeof...(args); - - std::array stringArgs = { { args... } }; - - // These static variables are declared as static so that the memory will stick around but won't - // be reported as a leak. - static std::array, numArgs> vecArgs; - static std::array finalArgs; - std::cout << " starting args:"; - for (std::size_t i = 0; i < numArgs; ++i) - { - std::cout << " " << stringArgs[i]; - // Safely copying a C-style string is a PITA - vecArgs[i].resize(0); - vecArgs[i].reserve(stringArgs[i].size() + 1); - for (auto&& c : stringArgs[i]) - { - vecArgs[i].push_back(c); - } - vecArgs[i].push_back('\0'); - - finalArgs[i] = vecArgs[i].data(); - } - finalArgs[numArgs] = nullptr; - std::cout << std::endl; - - argc = static_cast(numArgs); - argv = finalArgs.data(); -} - std::unique_ptr GetOptions(int& argc, char** argv, std::vector& usage) @@ -81,25 +46,6 @@ std::unique_ptr GetOptions(int& argc, return options; } -void my_setenv(const std::string& var, const std::string& value) -{ -#ifdef _MSC_VER - auto iter = envVars.emplace(envVars.end(), var, value); - _putenv_s(iter->first.c_str(), iter->second.c_str()); -#else - setenv(var.c_str(), value.c_str(), 1); -#endif -} - -void my_unsetenv(const std::string& var) -{ -#ifdef _MSC_VER - my_setenv(var, ""); -#else - unsetenv(var.c_str()); -#endif -} - void TestRuntimeDeviceOptionHappy() { std::vector usage; @@ -108,7 +54,7 @@ void TestRuntimeDeviceOptionHappy() usage.push_back({ 0, 0, 0, 0, 0, 0 }); const std::string env{ "TEST_OPTION" }; - my_unsetenv(env); + vtkm::cont::testing::Testing::UnsetEnv(env); // Basic no value initialize { @@ -117,7 +63,7 @@ void TestRuntimeDeviceOptionHappy() VTKM_TEST_ASSERT(!testOption.IsSet(), "test option should not be set"); } - my_setenv(env, "1"); + vtkm::cont::testing::Testing::SetEnv(env, "1"); // Initialize from environment { @@ -131,7 +77,7 @@ void TestRuntimeDeviceOptionHappy() int argc; char** argv; - MakeArgs(argc, argv, "--test-option", "2"); + vtkm::cont::testing::Testing::MakeArgs(argc, argv, "--test-option", "2"); auto options = GetOptions(argc, argv, usage); VTKM_TEST_ASSERT(options[TEST], "should be and option"); @@ -158,7 +104,7 @@ void TestRuntimeDeviceOptionHappy() VTKM_TEST_ASSERT(testOption.GetValue() == 3, "Option value should be 3"); } - my_unsetenv(env); + vtkm::cont::testing::Testing::UnsetEnv(env); } void TestRuntimeDeviceOptionError() @@ -169,14 +115,14 @@ void TestRuntimeDeviceOptionError() usage.push_back({ 0, 0, 0, 0, 0, 0 }); const std::string env{ "TEST_OPTION" }; - my_unsetenv(env); + vtkm::cont::testing::Testing::UnsetEnv(env); bool threw = true; // Parse a non integer { internal::RuntimeDeviceOption testOption(TEST, env); - my_setenv(env, "bad"); + vtkm::cont::testing::Testing::SetEnv(env, "bad"); try { testOption.Initialize(nullptr); @@ -196,7 +142,7 @@ void TestRuntimeDeviceOptionError() // Parse an integer that's too large { internal::RuntimeDeviceOption testOption(TEST, env); - my_setenv(env, "9938489298493882949384989"); + vtkm::cont::testing::Testing::SetEnv(env, "9938489298493882949384989"); try { testOption.Initialize(nullptr); @@ -216,7 +162,7 @@ void TestRuntimeDeviceOptionError() // Parse an integer with some stuff on the end { internal::RuntimeDeviceOption testOption(TEST, env); - my_setenv(env, "100bad"); + vtkm::cont::testing::Testing::SetEnv(env, "100bad"); try { testOption.Initialize(nullptr); @@ -233,40 +179,11 @@ void TestRuntimeDeviceOptionError() VTKM_TEST_ASSERT(threw, "Should have thrown"); } - my_unsetenv(env); + vtkm::cont::testing::Testing::UnsetEnv(env); } -void TestRuntimeDeviceConfigurationOptions() +void TestConfigOptionValues(const internal::RuntimeDeviceConfigurationOptions& configOptions) { - std::vector usage; - usage.push_back({ opt::OptionIndex::DEVICE, 0, "", "tester", opt::VtkmArg::Required, "" }); - usage.push_back({ opt::OptionIndex::LOGLEVEL, 0, "", "filler", opt::VtkmArg::Required, "" }); - usage.push_back({ opt::OptionIndex::HELP, 0, "", "fancy", opt::VtkmArg::Required, "" }); - usage.push_back( - { opt::OptionIndex::DEPRECATED_DEVICE, 0, "", "just", opt::VtkmArg::Required, "" }); - usage.push_back( - { opt::OptionIndex::DEPRECATED_LOGLEVEL, 0, "", "gotta", opt::VtkmArg::Required, "" }); - - internal::RuntimeDeviceConfigurationOptions configOptions(usage); - - usage.push_back({ opt::OptionIndex::UNKNOWN, 0, "", "", opt::VtkmArg::UnknownOption, "" }); - usage.push_back({ 0, 0, 0, 0, 0, 0 }); - - int argc; - char** argv; - MakeArgs(argc, - argv, - "--vtkm-num-threads", - "100", - "--vtkm-numa-regions", - "2", - "--vtkm-device-instance", - "1"); - auto options = GetOptions(argc, argv, usage); - - VTKM_TEST_ASSERT(!configOptions.IsInitialized(), - "runtime config options should not be initialized"); - configOptions.Initialize(options.get()); VTKM_TEST_ASSERT(configOptions.IsInitialized(), "runtime config options should be initialized"); VTKM_TEST_ASSERT(configOptions.VTKmNumThreads.IsSet(), "num threads should be set"); @@ -278,6 +195,54 @@ void TestRuntimeDeviceConfigurationOptions() VTKM_TEST_ASSERT(configOptions.VTKmDeviceInstance.GetValue() == 1, "device instance should == 1"); } +void TestRuntimeDeviceConfigurationOptions() +{ + { + std::vector usage; + usage.push_back({ 0, 0, "", "need", opt::VtkmArg::Required, "" }); + usage.push_back({ 1, 0, "", "filler", opt::VtkmArg::Required, "" }); + usage.push_back({ 2, 0, "", "args", opt::VtkmArg::Required, "" }); + usage.push_back({ 3, 0, "", "to", opt::VtkmArg::Required, "" }); + usage.push_back({ 4, 0, "", "pass", opt::VtkmArg::Required, "" }); + internal::RuntimeDeviceConfigurationOptions configOptions(usage); + + usage.push_back({ opt::OptionIndex::UNKNOWN, 0, "", "", opt::VtkmArg::UnknownOption, "" }); + usage.push_back({ 0, 0, 0, 0, 0, 0 }); + + int argc; + char** argv; + vtkm::cont::testing::Testing::MakeArgs(argc, + argv, + "--vtkm-num-threads", + "100", + "--vtkm-numa-regions", + "2", + "--vtkm-device-instance", + "1"); + auto options = GetOptions(argc, argv, usage); + + VTKM_TEST_ASSERT(!configOptions.IsInitialized(), + "runtime config options should not be initialized"); + configOptions.Initialize(options.get()); + TestConfigOptionValues(configOptions); + } + + { + int argc; + char** argv; + vtkm::cont::testing::Testing::MakeArgs(argc, + argv, + "--vtkm-num-threads", + "100", + "--vtkm-numa-regions", + "2", + "--vtkm-device-instance", + "1"); + internal::RuntimeDeviceConfigurationOptions configOptions(argc, argv); + TestConfigOptionValues(configOptions); + } +} + void TestRuntimeConfigurationOptions() { TestRuntimeDeviceOptionHappy(); diff --git a/vtkm/cont/kokkos/internal/CMakeLists.txt b/vtkm/cont/kokkos/internal/CMakeLists.txt index 077c3046c..083fa3c71 100644 --- a/vtkm/cont/kokkos/internal/CMakeLists.txt +++ b/vtkm/cont/kokkos/internal/CMakeLists.txt @@ -13,7 +13,6 @@ set(headers DeviceAdapterMemoryManagerKokkos.h DeviceAdapterRuntimeDetectorKokkos.h DeviceAdapterTagKokkos.h - Initialize.h KokkosAlloc.h KokkosTypes.h RuntimeDeviceConfigurationKokkos.h @@ -32,7 +31,6 @@ if (TARGET vtkm::kokkos) ${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterAlgorithmKokkos.cxx ${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterMemoryManagerKokkos.cxx ${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterRuntimeDetectorKokkos.cxx - ${CMAKE_CURRENT_SOURCE_DIR}/Initialize.cxx ${CMAKE_CURRENT_SOURCE_DIR}/KokkosAlloc.cxx ${CMAKE_CURRENT_SOURCE_DIR}/KokkosTypes.cxx) target_sources(vtkm_cont PRIVATE ${sources}) diff --git a/vtkm/cont/kokkos/internal/Initialize.cxx b/vtkm/cont/kokkos/internal/Initialize.cxx deleted file mode 100644 index 953c572f4..000000000 --- a/vtkm/cont/kokkos/internal/Initialize.cxx +++ /dev/null @@ -1,65 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ -#include - -#include -#include - -VTKM_THIRDPARTY_PRE_INCLUDE -#include -VTKM_THIRDPARTY_POST_INCLUDE - -#include -#include -#include - -namespace -{ -// Performs an in-place change to the name of an argument in the parameter list. -// Requires `newName` length to be <= `origName` length. -inline void ChangeArgumentName(const std::string& origName, - const std::string& newName, - int argc, - char* argv[]) -{ - VTKM_ASSERT(newName.length() <= origName.length()); - - for (int i = 0; i < argc; ++i) - { - auto argStr = std::string(argv[i]); - auto argName = argStr.substr(0, argStr.find_first_of('=')); - if (argName == origName) - { - auto newArg = newName + argStr.substr(argName.length()); - newArg.copy(argv[i], newArg.length()); - argv[i][newArg.length()] = '\0'; - } - } -} -} // anonymous namespace - -void vtkm::cont::kokkos::internal::Initialize(int& argc, char* argv[]) -{ - // TODO: remove this argument mangling once DEPRECATED options are fully removed - // mangle --device to prevent conflict - ChangeArgumentName("--device", "--vtkm_d", argc, argv); - // rename to what is expected by kokkos - ChangeArgumentName("--kokkos_device", "--device", argc, argv); - ChangeArgumentName("--kokkos_device-id", "--device-id", argc, argv); - - if (!Kokkos::is_initialized()) - { - Kokkos::initialize(argc, argv); - std::atexit(Kokkos::finalize); - } - - // de-mangle - ChangeArgumentName("--vtkm_d", "--device", argc, argv); -} diff --git a/vtkm/cont/kokkos/internal/RuntimeDeviceConfigurationKokkos.h b/vtkm/cont/kokkos/internal/RuntimeDeviceConfigurationKokkos.h index f46dc26c1..d143b47b2 100644 --- a/vtkm/cont/kokkos/internal/RuntimeDeviceConfigurationKokkos.h +++ b/vtkm/cont/kokkos/internal/RuntimeDeviceConfigurationKokkos.h @@ -10,10 +10,16 @@ #ifndef vtk_m_cont_kokkos_internal_RuntimeDeviceConfigurationKokkos_h #define vtk_m_cont_kokkos_internal_RuntimeDeviceConfigurationKokkos_h +#include #include #include +VTKM_THIRDPARTY_PRE_INCLUDE #include +VTKM_THIRDPARTY_POST_INCLUDE + +#include +#include namespace vtkm { @@ -22,6 +28,52 @@ namespace cont namespace internal { +namespace +{ +VTKM_CONT +RuntimeDeviceConfigReturnCode GetArgFromList(const std::vector& argList, + const std::string& argName, + vtkm::Id& value) +{ + size_t pos; + try + { + for (auto argItr = argList.rbegin(); argItr != argList.rend(); argItr++) + { + if (argItr->rfind(argName, 0) == 0) + { + if (argItr->size() == argName.size()) + { + value = std::stoi(*(--argItr), &pos, 10); + return RuntimeDeviceConfigReturnCode::SUCCESS; + } + else + { + value = std::stoi(argItr->substr(argName.size() + 1), &pos, 10); + return RuntimeDeviceConfigReturnCode::SUCCESS; + } + } + } + } + catch (const std::invalid_argument&) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, + "Unable to get arg " + argName + + "from kokkos argList, invalid argument thrown... This shouldn't have happened"); + return RuntimeDeviceConfigReturnCode::INVALID_VALUE; + } + catch (const std::out_of_range&) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, + "Unable to get arg " + argName + + "from kokkos argList, out of range thrown... This shouldn't have happened"); + return RuntimeDeviceConfigReturnCode::INVALID_VALUE; + } + return RuntimeDeviceConfigReturnCode::NOT_APPLIED; +} + +} // namespace anonymous + template <> class RuntimeDeviceConfiguration : public vtkm::cont::internal::RuntimeDeviceConfigurationBase @@ -32,54 +84,114 @@ public: return vtkm::cont::DeviceAdapterTagKokkos{}; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id& value) override final { - // TODO: set the kokkos threads + if (Kokkos::is_initialized()) + { + VTKM_LOG_S( + vtkm::cont::LogLevel::Warn, + "SetThreads was called but Kokkos was already initailized! Updates will not be applied."); + return RuntimeDeviceConfigReturnCode::NOT_APPLIED; + } + this->KokkosArguments.insert(this->KokkosArguments.begin(), + "--kokkos-threads=" + std::to_string(value)); return RuntimeDeviceConfigReturnCode::SUCCESS; } VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetNumaRegions( - const vtkm::Id&) const override final + const vtkm::Id& value) override final { - // TODO: set the kokkos numa regions + if (Kokkos::is_initialized()) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Warn, + "SetNumaRegions was called but Kokkos was already initailized! Updates will not " + "be applied."); + return RuntimeDeviceConfigReturnCode::NOT_APPLIED; + } + this->KokkosArguments.insert(this->KokkosArguments.begin(), + "--kokkos-numa=" + std::to_string(value)); return RuntimeDeviceConfigReturnCode::SUCCESS; } VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetDeviceInstance( - const vtkm::Id&) const override final + const vtkm::Id& value) override final { - // TODO: set the kokkos device instance + if (Kokkos::is_initialized()) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Warn, + "SetDeviceInstance was called but Kokkos was already initailized! Updates will " + "not be applied."); + return RuntimeDeviceConfigReturnCode::NOT_APPLIED; + } + this->KokkosArguments.insert(this->KokkosArguments.begin(), + "--kokkos-device-id=" + std::to_string(value)); return RuntimeDeviceConfigReturnCode::SUCCESS; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetThreads(vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetThreads(vtkm::Id& value) const override final { - // TODO: get the kokkos threads - return RuntimeDeviceConfigReturnCode::SUCCESS; + return GetArgFromList(this->KokkosArguments, "--kokkos-threads", value); } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetNumaRegions(vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetNumaRegions( + vtkm::Id& value) const override final { - // TODO: get the kokkos numa regions - return RuntimeDeviceConfigReturnCode::SUCCESS; + return GetArgFromList(this->KokkosArguments, "--kokkos-numa", value); } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetDeviceInstance(vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetDeviceInstance( + vtkm::Id& value) const override final { - // TODO: get the kokkos device instance - return RuntimeDeviceConfigReturnCode::SUCCESS; + return GetArgFromList(this->KokkosArguments, "--kokkos-device-id", value); } protected: - VTKM_CONT virtual void ParseExtraArguments(int&, char*[]) const override final + /// Store a copy of the current arguments when initializing the Kokkos subsystem later + /// Appends a copy of the argv values in the KokkosArguments vector: this assumes the + /// argv values contain kokkos command line arguments (like --kokkos-threads, etc) + VTKM_CONT virtual void ParseExtraArguments(int& argc, char* argv[]) override final { - // TODO: ugh, kokkos. Manually parse the kokkos config args, store them for usage + if (argc > 0 && argv) + { + this->KokkosArguments.insert(this->KokkosArguments.end(), argv, argv + argc); + } + } + + /// Calls kokkos initiailze if kokkos has not been initialized yet and sets up an atexit + /// to call kokkos finalize. Converts the KokkosArguments vector to a standard argc/argv + /// list of arguments when calling kokkos initialize. + /// + /// When using vtkm::Initialize, the standard order for kokkos argument priority is as + /// follows (this assumes kokkos still prioritizes arguments found at the end of the + /// argv list over similarly named arguements found earlier in the list): + /// 1. Environment Variables + /// 2. Kokkos Command Line Arguments + /// 3. VTK-m Interpreted Command Line Arguements + VTKM_CONT virtual void InitializeSubsystem() override final + { + if (!Kokkos::is_initialized()) + { + std::vector argv; + for (auto& arg : this->KokkosArguments) + { + argv.push_back(&arg[0]); + } + int size = argv.size(); + Kokkos::initialize(size, argv.data()); + std::atexit(Kokkos::finalize); + } + else + { + VTKM_LOG_S( + vtkm::cont::LogLevel::Warn, + "Attempted to Re-initialize Kokkos! The Kokkos subsystem can only be initialized once"); + } } private: - Kokkos::InitArguments ParsedCommandLineArgs; - Kokkos::InitArguments VTKmInitializedArgs; + std::vector KokkosArguments; }; + } // namespace vtkm::cont::internal } // namespace vtkm::cont } // namespace vtkm diff --git a/vtkm/cont/kokkos/testing/CMakeLists.txt b/vtkm/cont/kokkos/testing/CMakeLists.txt index 8b6501b1a..add2f786e 100644 --- a/vtkm/cont/kokkos/testing/CMakeLists.txt +++ b/vtkm/cont/kokkos/testing/CMakeLists.txt @@ -23,6 +23,7 @@ set(unit_tests UnitTestKokkosDeviceAdapter.cxx UnitTestKokkosImplicitFunction.cxx UnitTestKokkosPointLocatorSparseGrid.cxx + UnitTestKokkosRuntimeDeviceConfiguration.cxx ) if (NOT VTKm_NO_DEPRECATED_VIRTUAL) diff --git a/vtkm/cont/kokkos/internal/Initialize.h b/vtkm/cont/kokkos/testing/UnitTestKokkosRuntimeDeviceConfiguration.cxx similarity index 51% rename from vtkm/cont/kokkos/internal/Initialize.h rename to vtkm/cont/kokkos/testing/UnitTestKokkosRuntimeDeviceConfiguration.cxx index f7a86c59d..cf5d716e0 100644 --- a/vtkm/cont/kokkos/internal/Initialize.h +++ b/vtkm/cont/kokkos/testing/UnitTestKokkosRuntimeDeviceConfiguration.cxx @@ -7,22 +7,13 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_cont_kokkos_internal_Initialize_h -#define vtk_m_cont_kokkos_internal_Initialize_h +#include +#include +#include -namespace vtkm +int UnitTestKokkosRuntimeDeviceConfiguration(int argc, char* argv[]) { -namespace cont -{ -namespace kokkos -{ -namespace internal -{ - -void Initialize(int& argc, char* argv[]); + vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagKokkos{}); + return vtkm::cont::testing::TestingRuntimeDeviceConfiguration< + vtkm::cont::DeviceAdapterTagKokkos>::Run(argc, argv); } -} -} -} // vtkm::cont::kokkos::internal - -#endif // vtk_m_cont_kokkos_internal_Initialize_h diff --git a/vtkm/cont/openmp/internal/RuntimeDeviceConfigurationOpenMP.h b/vtkm/cont/openmp/internal/RuntimeDeviceConfigurationOpenMP.h index 6675e57f5..5386d5d5f 100644 --- a/vtkm/cont/openmp/internal/RuntimeDeviceConfigurationOpenMP.h +++ b/vtkm/cont/openmp/internal/RuntimeDeviceConfigurationOpenMP.h @@ -29,14 +29,13 @@ class RuntimeDeviceConfiguration return vtkm::cont::DeviceAdapterTagOpenMP{}; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) override final { // TODO: Set the threads in OpenMP return RuntimeDeviceConfigReturnCode::SUCCESS; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetNumaRegions( - const vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetNumaRegions(const vtkm::Id&) override final { // TODO: Set the numa regions in OpenMP return RuntimeDeviceConfigReturnCode::SUCCESS; @@ -53,6 +52,11 @@ class RuntimeDeviceConfiguration // TODO: Get the number of OpenMP NumaRegions return RuntimeDeviceConfigReturnCode::SUCCESS; } + + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetMaxThreads(vtkm::Id&) const override final + { + return RuntimeDeviceConfigReturnCode::SUCCESS; + } }; } // namespace vtkm::cont::internal } // namespace vtkm::cont diff --git a/vtkm/cont/tbb/internal/RuntimeDeviceConfigurationTBB.h b/vtkm/cont/tbb/internal/RuntimeDeviceConfigurationTBB.h index ffa6ed7aa..10df385fd 100644 --- a/vtkm/cont/tbb/internal/RuntimeDeviceConfigurationTBB.h +++ b/vtkm/cont/tbb/internal/RuntimeDeviceConfigurationTBB.h @@ -29,7 +29,7 @@ class RuntimeDeviceConfiguration return vtkm::cont::DeviceAdapterTagTBB{}; } - VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) const override final + VTKM_CONT virtual RuntimeDeviceConfigReturnCode SetThreads(const vtkm::Id&) override final { // TODO: vtk-m set the number of global threads return RuntimeDeviceConfigReturnCode::SUCCESS; @@ -40,6 +40,11 @@ class RuntimeDeviceConfiguration // TODO: Get number of TBB threads here (essentially just threads supported by architecture) return RuntimeDeviceConfigReturnCode::SUCCESS; } + + VTKM_CONT virtual RuntimeDeviceConfigReturnCode GetMaxThreads(vtkm::Id&) const override final + { + return RuntimeDeviceConfigReturnCode::SUCCESS; + } }; } // namespace vktm::cont::internal } // namespace vtkm::cont diff --git a/vtkm/cont/testing/CMakeLists.txt b/vtkm/cont/testing/CMakeLists.txt index dd967f8c2..e64a3ab05 100644 --- a/vtkm/cont/testing/CMakeLists.txt +++ b/vtkm/cont/testing/CMakeLists.txt @@ -25,6 +25,7 @@ set(headers TestingFancyArrayHandles.h TestingImplicitFunction.h TestingPointLocatorSparseGrid.h + TestingRuntimeDeviceConfiguration.h TestingSerialization.h TestingVirtualObjectHandle.h ) diff --git a/vtkm/cont/testing/Testing.h b/vtkm/cont/testing/Testing.h index ba73f12c2..ac291c36a 100644 --- a/vtkm/cont/testing/Testing.h +++ b/vtkm/cont/testing/Testing.h @@ -101,20 +101,8 @@ public: } template - static VTKM_CONT int Run(Func function, int& argc, char* argv[]) + static VTKM_CONT int ExecuteFunction(Func function) { - std::unique_ptr env_diy = nullptr; - if (!vtkmdiy::mpi::environment::initialized()) - { - env_diy.reset(new vtkmdiy::mpi::environment(argc, argv)); - } - - vtkm::cont::Initialize(argc, argv); - ParseAdditionalTestArgs(argc, argv); - - // Turn on floating point exception trapping where available - vtkm::testing::FloatingPointExceptionTrapEnable(); - try { function(); @@ -144,6 +132,23 @@ public: return 0; } + template + static VTKM_CONT int Run(Func function, int& argc, char* argv[]) + { + std::unique_ptr env_diy = nullptr; + if (!vtkmdiy::mpi::environment::initialized()) + { + env_diy.reset(new vtkmdiy::mpi::environment(argc, argv)); + } + + vtkm::cont::Initialize(argc, argv); + ParseAdditionalTestArgs(argc, argv); + + // Turn on floating point exception trapping where available + vtkm::testing::FloatingPointExceptionTrapEnable(); + return ExecuteFunction(function); + } + template static VTKM_CONT int RunOnDevice(Func function, int argc, char* argv[]) { @@ -151,33 +156,66 @@ public: auto config = vtkm::cont::Initialize(argc, argv, opts); ParseAdditionalTestArgs(argc, argv); - try + return ExecuteFunction([&]() { function(config.Device); }); + } + + template + static VTKM_CONT void MakeArgs(int& argc, char**& argv, T&&... args) + { + constexpr std::size_t numArgs = sizeof...(args); + + std::array stringArgs = { { args... } }; + + // These static variables are declared as static so that the memory will stick around but won't + // be reported as a leak. + static std::array, numArgs> vecArgs; + static std::array finalArgs; + std::cout << " starting args:"; + for (std::size_t i = 0; i < numArgs; ++i) { - function(config.Device); + std::cout << " " << stringArgs[i]; + // Safely copying a C-style string is a PITA + vecArgs[i].resize(0); + vecArgs[i].reserve(stringArgs[i].size() + 1); + for (auto&& c : stringArgs[i]) + { + vecArgs[i].push_back(c); + } + vecArgs[i].push_back('\0'); + + finalArgs[i] = vecArgs[i].data(); } - catch (vtkm::testing::Testing::TestFailure& error) - { - std::cerr << "Error at " << error.GetFile() << ":" << error.GetLine() << ":" - << error.GetFunction() << "\n\t" << error.GetMessage() << "\n"; - return 1; - } - catch (vtkm::cont::Error& error) - { - std::cerr << "Uncaught VTKm exception thrown.\n" << error.GetMessage() << "\n"; - std::cerr << "Stacktrace:\n" << error.GetStackTrace() << "\n"; - return 1; - } - catch (std::exception& error) - { - std::cerr << "STL exception throw.\n\t" << error.what() << "\n"; - return 1; - } - catch (...) - { - std::cerr << "Unidentified exception thrown.\n"; - return 1; - } - return 0; + finalArgs[numArgs] = nullptr; + std::cout << std::endl; + + argc = static_cast(numArgs); + argv = finalArgs.data(); + } + + template + static VTKM_CONT void MakeArgsAddProgramName(int& argc, char**& argv, T&&... args) + { + MakeArgs(argc, argv, "program-name", args...); + } + + static void SetEnv(const std::string& var, const std::string& value) + { + static std::vector> envVars{}; +#ifdef _MSC_VER + auto iter = envVars.emplace(envVars.end(), var, value); + _putenv_s(iter->first.c_str(), iter->second.c_str()); +#else + setenv(var.c_str(), value.c_str(), 1); +#endif + } + + static void UnsetEnv(const std::string& var) + { +#ifdef _MSC_VER + SetEnv(var, ""); +#else + unsetenv(var.c_str()); +#endif } private: @@ -248,143 +286,141 @@ private: // Method to parse the extra arguments given to unit tests static VTKM_CONT void ParseAdditionalTestArgs(int& argc, char* argv[]) { - { // Parse test arguments - std::vector usage; + std::vector usage; - usage.push_back({ DATADIR, - 0, - "", - "vtkm-data-dir", - opt::VtkmArg::Required, - " --vtkm-data-dir " - " \tPath to the " - "base data directory in the VTK-m " - "src dir." }); - usage.push_back({ BASELINEDIR, - 0, - "", - "vtkm-baseline-dir", - opt::VtkmArg::Required, - " --vtkm-baseline-dir " - " " - "\tPath to the base dir " - "for regression test " - "images" }); - usage.push_back({ WRITEDIR, - 0, - "", - "vtkm-write-dir", - opt::VtkmArg::Required, - " --vtkm-write-dir " - " " - "\tPath to the write dir " - "to store generated " - "regression test images" }); - usage.push_back({ DEPRECATED_DATADIR, - 0, - "D", - "data-dir", - opt::VtkmArg::Required, - " --data-dir " - " " - "\tDEPRECATED: use --vtkm-data-dir instead" }); - usage.push_back({ DEPRECATED_BASELINEDIR, - 0, - "B", - "baseline-dir", - opt::VtkmArg::Required, - " --baseline-dir " - " " - "\tDEPRECATED: use --vtkm-baseline-dir instead" }); - usage.push_back({ WRITEDIR, - 0, - "", - "write-dir", - opt::VtkmArg::Required, - " --write-dir " - " " - "\tDEPRECATED: use --vtkm-write-dir instead" }); + usage.push_back({ DATADIR, + 0, + "", + "vtkm-data-dir", + opt::VtkmArg::Required, + " --vtkm-data-dir " + " \tPath to the " + "base data directory in the VTK-m " + "src dir." }); + usage.push_back({ BASELINEDIR, + 0, + "", + "vtkm-baseline-dir", + opt::VtkmArg::Required, + " --vtkm-baseline-dir " + " " + "\tPath to the base dir " + "for regression test " + "images" }); + usage.push_back({ WRITEDIR, + 0, + "", + "vtkm-write-dir", + opt::VtkmArg::Required, + " --vtkm-write-dir " + " " + "\tPath to the write dir " + "to store generated " + "regression test images" }); + usage.push_back({ DEPRECATED_DATADIR, + 0, + "D", + "data-dir", + opt::VtkmArg::Required, + " --data-dir " + " " + "\tDEPRECATED: use --vtkm-data-dir instead" }); + usage.push_back({ DEPRECATED_BASELINEDIR, + 0, + "B", + "baseline-dir", + opt::VtkmArg::Required, + " --baseline-dir " + " " + "\tDEPRECATED: use --vtkm-baseline-dir instead" }); + usage.push_back({ WRITEDIR, + 0, + "", + "write-dir", + opt::VtkmArg::Required, + " --write-dir " + " " + "\tDEPRECATED: use --vtkm-write-dir instead" }); - // Required to collect unknown arguments when help is off. - usage.push_back({ TEST_UNKNOWN, 0, "", "", opt::VtkmArg::UnknownOption, "" }); - usage.push_back({ 0, 0, 0, 0, 0, 0 }); + // Required to collect unknown arguments when help is off. + usage.push_back({ TEST_UNKNOWN, 0, "", "", opt::VtkmArg::UnknownOption, "" }); + usage.push_back({ 0, 0, 0, 0, 0, 0 }); - // Remove argv[0] (executable name) if present: - int vtkmArgc = argc > 0 ? argc - 1 : 0; - char** vtkmArgv = argc > 0 ? argv + 1 : argv; + // Remove argv[0] (executable name) if present: + int vtkmArgc = argc > 0 ? argc - 1 : 0; + char** vtkmArgv = argc > 0 ? argv + 1 : argv; - opt::Stats stats(usage.data(), vtkmArgc, vtkmArgv); - std::unique_ptr options{ new opt::Option[stats.options_max] }; - std::unique_ptr buffer{ new opt::Option[stats.buffer_max] }; - opt::Parser parse(usage.data(), vtkmArgc, vtkmArgv, options.get(), buffer.get()); + opt::Stats stats(usage.data(), vtkmArgc, vtkmArgv); + std::unique_ptr options{ new opt::Option[stats.options_max] }; + std::unique_ptr buffer{ new opt::Option[stats.buffer_max] }; + opt::Parser parse(usage.data(), vtkmArgc, vtkmArgv, options.get(), buffer.get()); - if (parse.error()) - { - std::cerr << "Internal Initialize parser error" << std::endl; - exit(1); - } + if (parse.error()) + { + std::cerr << "Internal Initialize parser error" << std::endl; + exit(1); + } - if (options[DEPRECATED_DATADIR]) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Error, - "Supplied deprecated datadir flag: " - << std::string{ options[DEPRECATED_DATADIR].name } - << ", use --vtkm-data-dir instead"); - SetAndGetTestDataBasePath(options[DEPRECATED_DATADIR].arg); - } + if (options[DEPRECATED_DATADIR]) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, + "Supplied deprecated datadir flag: " + << std::string{ options[DEPRECATED_DATADIR].name } + << ", use --vtkm-data-dir instead"); + SetAndGetTestDataBasePath(options[DEPRECATED_DATADIR].arg); + } - if (options[DEPRECATED_BASELINEDIR]) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Error, - "Supplied deprecated baselinedir flag: " - << std::string{ options[DEPRECATED_BASELINEDIR].name } - << ", use --vtkm-baseline-dir instead"); - SetAndGetRegressionImageBasePath(options[DEPRECATED_BASELINEDIR].arg); - } + if (options[DEPRECATED_BASELINEDIR]) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, + "Supplied deprecated baselinedir flag: " + << std::string{ options[DEPRECATED_BASELINEDIR].name } + << ", use --vtkm-baseline-dir instead"); + SetAndGetRegressionImageBasePath(options[DEPRECATED_BASELINEDIR].arg); + } - if (options[DEPRECATED_WRITEDIR]) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Error, - "Supplied deprecated writedir flag: " - << std::string{ options[DEPRECATED_WRITEDIR].name } - << ", use --vtkm-write-dir instead"); - SetAndGetWriteDirBasePath(options[DEPRECATED_WRITEDIR].arg); - } + if (options[DEPRECATED_WRITEDIR]) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, + "Supplied deprecated writedir flag: " + << std::string{ options[DEPRECATED_WRITEDIR].name } + << ", use --vtkm-write-dir instead"); + SetAndGetWriteDirBasePath(options[DEPRECATED_WRITEDIR].arg); + } - if (options[DATADIR]) - { - SetAndGetTestDataBasePath(options[DATADIR].arg); - } + if (options[DATADIR]) + { + SetAndGetTestDataBasePath(options[DATADIR].arg); + } - if (options[BASELINEDIR]) - { - SetAndGetRegressionImageBasePath(options[BASELINEDIR].arg); - } + if (options[BASELINEDIR]) + { + SetAndGetRegressionImageBasePath(options[BASELINEDIR].arg); + } - if (options[WRITEDIR]) - { - SetAndGetWriteDirBasePath(options[WRITEDIR].arg); - } + if (options[WRITEDIR]) + { + SetAndGetWriteDirBasePath(options[WRITEDIR].arg); + } - for (const opt::Option* opt = options[TEST_UNKNOWN]; opt != nullptr; opt = opt->next()) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Info, - "Unknown option to internal Initialize: " << opt->name << "\n"); - } + for (const opt::Option* opt = options[TEST_UNKNOWN]; opt != nullptr; opt = opt->next()) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "Unknown option to internal Initialize: " << opt->name << "\n"); + } - for (int nonOpt = 0; nonOpt < parse.nonOptionsCount(); ++nonOpt) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Info, - "Unknown argument to internal Initialize: " << parse.nonOption(nonOpt) << "\n"); - } + for (int nonOpt = 0; nonOpt < parse.nonOptionsCount(); ++nonOpt) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "Unknown argument to internal Initialize: " << parse.nonOption(nonOpt) << "\n"); } } }; -} -} } // namespace vtkm::cont::testing +} // namespace vtkm::cont +} // namespace vtkm //============================================================================ template diff --git a/vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h b/vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h new file mode 100644 index 000000000..4a050c750 --- /dev/null +++ b/vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h @@ -0,0 +1,185 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_cont_testing_TestingRuntimeDeviceConfiguration_h +#define vtk_m_cont_testing_TestingRuntimeDeviceConfiguration_h + +#include +#include +#include +#include +#include +#include + +namespace internal = vtkm::cont::internal; + +namespace vtkm +{ +namespace cont +{ +namespace testing +{ + +template +struct TestingRuntimeDeviceConfiguration +{ + + VTKM_CONT + static internal::RuntimeDeviceConfigurationOptions DefaultInitializeConfigOptions() + { + internal::RuntimeDeviceConfigurationOptions runtimeDeviceOptions{}; + runtimeDeviceOptions.VTKmNumThreads.SetOption(8); + runtimeDeviceOptions.VTKmNumaRegions.SetOption(0); + runtimeDeviceOptions.VTKmDeviceInstance.SetOption(2); + runtimeDeviceOptions.Initialize(nullptr); + VTKM_TEST_ASSERT(runtimeDeviceOptions.IsInitialized(), + "Failed to default initialize runtime config options."); + return runtimeDeviceOptions; + } + + VTKM_CONT + static void TestSerial() {} + + VTKM_CONT + static void TestTBB() {} + + VTKM_CONT + static void TestOpenMP() {} + + VTKM_CONT + static void TestCuda() {} + + VTKM_CONT + static void TestKokkos() + { + int argc; + char** argv; + vtkm::cont::testing::Testing::MakeArgs(argc, argv, "--kokkos-numa=4"); + vtkm::cont::testing::Testing::SetEnv("KOKKOS_DEVICE_ID", "0"); + auto deviceOptions = TestingRuntimeDeviceConfiguration::DefaultInitializeConfigOptions(); + bool threw = false; + try + { + RuntimeDeviceInformation{}.GetRuntimeConfiguration( + DeviceAdapterTag(), deviceOptions, argc, argv); + } + catch (const std::runtime_error& e) + { + threw = true; + } + VTKM_TEST_ASSERT( + threw, "GetRuntimeConfiguration should have thrown, env KOKKOS_DEVICE_ID didn't match"); + VTKM_TEST_ASSERT(!Kokkos::is_initialized(), "Kokkos should not be initialized at this point"); + deviceOptions.VTKmDeviceInstance.SetOption(0); + internal::RuntimeDeviceConfigurationBase& config = + RuntimeDeviceInformation{}.GetRuntimeConfiguration( + DeviceAdapterTag(), deviceOptions, argc, argv); + VTKM_TEST_ASSERT(Kokkos::is_initialized(), "Kokkos should be initialized at this point"); + + // Test that args are set and the right arg priority is applied + vtkm::Id testValue; + VTKM_TEST_ASSERT(config.GetThreads(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set threads"); + VTKM_TEST_ASSERT(testValue == 8, + "Set threads does not match expected value: 8 != " + + std::to_string(testValue)); + VTKM_TEST_ASSERT(config.GetNumaRegions(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set numa regions"); + VTKM_TEST_ASSERT(testValue == 4, + "Set numa regions does not match expected value: 4 != " + + std::to_string(testValue)); + VTKM_TEST_ASSERT(config.GetDeviceInstance(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set device instance"); + VTKM_TEST_ASSERT(testValue == 0, + "Set device instance does not match expected value: 0 != " + + std::to_string(testValue)); + + // Ensure that with kokkos we can't re-initialize or set values after the first initialize + // Should pop up a few warnings in the test logs + deviceOptions.VTKmNumThreads.SetOption(16); + deviceOptions.VTKmNumaRegions.SetOption(2); + deviceOptions.VTKmDeviceInstance.SetOption(5); + config.Initialize(deviceOptions); + VTKM_TEST_ASSERT(config.SetThreads(1) == internal::RuntimeDeviceConfigReturnCode::NOT_APPLIED, + "Shouldn't be able to set threads after kokkos is initalized"); + VTKM_TEST_ASSERT(config.SetNumaRegions(1) == + internal::RuntimeDeviceConfigReturnCode::NOT_APPLIED, + "Shouldn't be able to set numa regions after kokkos is initalized"); + VTKM_TEST_ASSERT(config.SetDeviceInstance(1) == + internal::RuntimeDeviceConfigReturnCode::NOT_APPLIED, + "Shouldn't be able to set device instnace after kokkos is initalized"); + + // make sure all the values are the same + VTKM_TEST_ASSERT(config.GetThreads(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set threads"); + VTKM_TEST_ASSERT(testValue == 8, + "Set threads does not match expected value: 8 != " + + std::to_string(testValue)); + VTKM_TEST_ASSERT(config.GetNumaRegions(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set numa regions"); + VTKM_TEST_ASSERT(testValue == 4, + "Set numa regions does not match expected value: 4 != " + + std::to_string(testValue)); + VTKM_TEST_ASSERT(config.GetDeviceInstance(testValue) == + internal::RuntimeDeviceConfigReturnCode::SUCCESS, + "Failed to get set device instance"); + VTKM_TEST_ASSERT(testValue == 0, + "Set device instance does not match expected value: 0 != " + + std::to_string(testValue)); + + vtkm::cont::testing::Testing::UnsetEnv("KOKKOS_DEVICE_ID"); + } + + struct TestRunner + { + VTKM_CONT + void operator()() const + { + switch (DeviceAdapterTag{}.GetValue()) + { + case vtkm::cont::DeviceAdapterTagSerial{}.GetValue(): + TestingRuntimeDeviceConfiguration::TestSerial(); + break; + case vtkm::cont::DeviceAdapterTagTBB{}.GetValue(): + TestingRuntimeDeviceConfiguration::TestTBB(); + break; + case vtkm::cont::DeviceAdapterTagOpenMP{}.GetValue(): + TestingRuntimeDeviceConfiguration::TestOpenMP(); + break; + case vtkm::cont::DeviceAdapterTagCuda{}.GetValue(): + TestingRuntimeDeviceConfiguration::TestCuda(); + break; + case vtkm::cont::DeviceAdapterTagKokkos{}.GetValue(): + TestingRuntimeDeviceConfiguration::TestKokkos(); + break; + default: + break; + } + } + }; + + static VTKM_CONT int Run(int, char*[]) + { + // For the Kokkos version of this test we don't not want Initialize to be called + // so we directly execute the testing functor instead of calling Run + vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(DeviceAdapterTag()); + return vtkm::cont::testing::Testing::ExecuteFunction(TestRunner{}); + } +}; + +} // namespace vtkm::cont::testing +} // namespace vtkm::cont +} // namespace vtkm + +#endif // vtk_m_cont_testing_TestingRuntimeDeviceConfiguration_h diff --git a/vtkm/cont/testing/UnitTestInitialize.cxx b/vtkm/cont/testing/UnitTestInitialize.cxx index 2a182bce0..4e42f1603 100644 --- a/vtkm/cont/testing/UnitTestInitialize.cxx +++ b/vtkm/cont/testing/UnitTestInitialize.cxx @@ -15,47 +15,12 @@ namespace { -constexpr const char* PROGRAM_NAME = "program-name"; - -template -void MakeArgs(int& argc, char**& argv, T&&... args) -{ - constexpr std::size_t numArgs = sizeof...(args) + 1; - - std::array stringArgs = { { PROGRAM_NAME, args... } }; - - // These static variables are declared as static so that the memory will stick around but won't - // be reported as a leak. - static std::array, numArgs> vecArgs; - static std::array finalArgs; - std::cout << " starting args:"; - for (std::size_t i = 0; i < numArgs; ++i) - { - std::cout << " " << stringArgs[i]; - // Safely copying a C-style string is a PITA - vecArgs[i].resize(0); - vecArgs[i].reserve(stringArgs[i].size() + 1); - for (auto&& c : stringArgs[i]) - { - vecArgs[i].push_back(c); - } - vecArgs[i].push_back('\0'); - - finalArgs[i] = vecArgs[i].data(); - } - finalArgs[numArgs] = nullptr; - std::cout << std::endl; - - argc = static_cast(numArgs); - argv = finalArgs.data(); -} - template void CheckArgs(int argc, char* argv[], T&&... args) { constexpr std::size_t numArgs = sizeof...(args) + 1; - std::array expectedArgs = { { PROGRAM_NAME, args... } }; + std::array expectedArgs = { { "program-name", args... } }; std::cout << " expected args:"; for (std::size_t i = 0; i < numArgs; ++i) @@ -94,7 +59,7 @@ void InitializeNoOptions() int argc; char** argv; - MakeArgs(argc, argv); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, argv); vtkm::cont::InitializeResult result = vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv); @@ -108,7 +73,7 @@ void InitializeStandardOptions() int argc; char** argv; - MakeArgs(argc, argv, "--vtkm-device", "Any"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, argv, "--vtkm-device", "Any"); vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::Strict); CheckArgs(argc, argv); } @@ -119,11 +84,12 @@ void InitializeCustomOptions() int argc; char** argv; - MakeArgs(argc, argv, "--foo", "-bar", "baz", "buz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, argv, "--foo", "-bar", "baz", "buz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "-bar", "baz", "buz"); - MakeArgs(argc, argv, "--foo", "-bar", "--", "baz", "buz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo", "-bar", "--", "baz", "buz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "-bar", "--", "baz", "buz"); } @@ -134,16 +100,17 @@ void InitializeMixedOptions() int argc; char** argv; - MakeArgs(argc, argv, "--foo", "--vtkm-device", "Any", "--bar", "baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo", "--vtkm-device", "Any", "--bar", "baz"); vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::AddHelp); CheckArgs(argc, argv, "--foo", "--bar", "baz"); - MakeArgs( + vtkm::cont::testing::Testing::MakeArgsAddProgramName( argc, argv, "--foo", "--vtkm-log-level", "OFF", "--", "--vtkm-device", "Any", "--bar", "baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "--", "--vtkm-device", "Any", "--bar", "baz"); - MakeArgs(argc, argv, "--vtkm-device", "Any", "foo"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, argv, "--vtkm-device", "Any", "foo"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "foo"); } @@ -154,19 +121,23 @@ void InitializeCustomOptionsWithArgs() int argc; char** argv; - MakeArgs(argc, argv, "--vtkm-device", "Any", "--foo=bar", "--baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--vtkm-device", "Any", "--foo=bar", "--baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo=bar", "--baz"); - MakeArgs(argc, argv, "--foo=bar", "--baz", "--vtkm-device", "Any"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo=bar", "--baz", "--vtkm-device", "Any"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo=bar", "--baz"); - MakeArgs(argc, argv, "--vtkm-device", "Any", "--foo", "bar", "--baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--vtkm-device", "Any", "--foo", "bar", "--baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "bar", "--baz"); - MakeArgs(argc, argv, "--foo", "bar", "--baz", "--vtkm-device", "Any"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo", "bar", "--baz", "--vtkm-device", "Any"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "bar", "--baz"); } @@ -177,23 +148,28 @@ void InitializeDeprecatedOptionsWithArgs() int argc; char** argv; - MakeArgs(argc, argv, "--device", "Any", "--foo=bar", "--baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--device", "Any", "--foo=bar", "--baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo=bar", "--baz"); - MakeArgs(argc, argv, "--foo=bar", "--baz", "--device", "Any"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo=bar", "--baz", "--device", "Any"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo=bar", "--baz"); - MakeArgs(argc, argv, "-d", "Any", "--foo", "bar", "--baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "-d", "Any", "--foo", "bar", "--baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "bar", "--baz"); - MakeArgs(argc, argv, "--foo", "bar", "--baz", "-d", "Any"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo", "bar", "--baz", "-d", "Any"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "bar", "--baz"); - MakeArgs(argc, argv, "--foo", "-v", "OFF", "--", "--device", "Any", "--bar", "baz"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName( + argc, argv, "--foo", "-v", "OFF", "--", "--device", "Any", "--bar", "baz"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv, "--foo", "--", "--device", "Any", "--bar", "baz"); } @@ -202,16 +178,16 @@ void InitializeRuntimeDeviceConfigurationWithArgs() { int argc; char** argv; - MakeArgs(argc, - argv, - "--device", - "Any", - "--vtkm-num-threads", - "100", - "--vtkm-numa-regions", - "4", - "--vtkm-device-instance", - "2"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, + argv, + "--device", + "Any", + "--vtkm-num-threads", + "100", + "--vtkm-numa-regions", + "4", + "--vtkm-device-instance", + "2"); vtkm::cont::Initialize(argc, argv); CheckArgs(argc, argv); } @@ -222,7 +198,7 @@ void InitializeWithHelp() int argc; char** argv; - MakeArgs(argc, argv, "--vtkm-help"); + vtkm::cont::testing::Testing::MakeArgsAddProgramName(argc, argv, "--vtkm-help"); vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::AddHelp); VTKM_TEST_FAIL("Help argument did not exit as expected.");