mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge topic 'kokkos-runtime-device-config'
cd2a6c138 implement kokkos runtime device configuration Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Kenneth Moreland <morelandkd@ornl.gov> Merge-request: !2549
This commit is contained in:
commit
56cbd0abe2
@ -15,10 +15,6 @@
|
||||
#include <vtkm/cont/internal/OptionParser.h>
|
||||
#include <vtkm/cont/internal/OptionParserArguments.h>
|
||||
|
||||
#if defined(VTKM_ENABLE_KOKKOS)
|
||||
#include <vtkm/cont/kokkos/internal/Initialize.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
@ -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<opt::Descriptor> usage;
|
||||
if ((opts & InitializeOptions::AddHelp) != InitializeOptions::None)
|
||||
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -29,8 +29,7 @@ class RuntimeDeviceConfiguration<vtkm::cont::DeviceAdapterTagCuda>
|
||||
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<vtkm::cont::DeviceAdapterTagCuda>
|
||||
// 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
|
||||
|
@ -7,6 +7,7 @@
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/internal/RuntimeDeviceConfiguration.h>
|
||||
|
||||
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 <typename SetFunc>
|
||||
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
|
||||
|
@ -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 <typename DeviceAdapterTag>
|
||||
|
@ -9,6 +9,9 @@
|
||||
//============================================================================
|
||||
#include <vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
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<option::Descriptor>& usage)
|
||||
: RuntimeDeviceConfigurationOptions()
|
||||
void AppendOptionDescriptors(std::vector<option::Descriptor>& usage,
|
||||
const bool& useOptionIndex = true)
|
||||
{
|
||||
usage.push_back(
|
||||
{ option::OptionIndex::NUM_THREADS,
|
||||
{ useOptionIndex ? static_cast<uint32_t>(option::OptionIndex::NUM_THREADS) : 0,
|
||||
0,
|
||||
"",
|
||||
"vtkm-num-threads",
|
||||
option::VtkmArg::Required,
|
||||
" --vtkm-num-threads <dev> \tSets the number of threads to use for the selected device" });
|
||||
usage.push_back(
|
||||
{ option::OptionIndex::NUMA_REGIONS,
|
||||
{ useOptionIndex ? static_cast<uint32_t>(option::OptionIndex::NUMA_REGIONS) : 1,
|
||||
0,
|
||||
"",
|
||||
"vtkm-numa-regions",
|
||||
option::VtkmArg::Required,
|
||||
" --vtkm-numa-regions <dev> \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 <dev> \tSets the device instance to use when using "
|
||||
"kokkos/cuda" });
|
||||
usage.push_back(
|
||||
{ useOptionIndex ? static_cast<uint32_t>(option::OptionIndex::DEVICE_INSTANCE) : 2,
|
||||
0,
|
||||
"",
|
||||
"vtkm-device-instance",
|
||||
option::VtkmArg::Required,
|
||||
" --vtkm-device-instance <dev> \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<option::Descriptor>& usage)
|
||||
: RuntimeDeviceConfigurationOptions(true)
|
||||
{
|
||||
AppendOptionDescriptors(usage);
|
||||
}
|
||||
|
||||
RuntimeDeviceConfigurationOptions::RuntimeDeviceConfigurationOptions(int& argc, char* argv[])
|
||||
: RuntimeDeviceConfigurationOptions(false)
|
||||
{
|
||||
std::vector<option::Descriptor> 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<option::Option[]> options{ new option::Option[stats.options_max] };
|
||||
std::unique_ptr<option::Option[]> 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)
|
||||
{
|
||||
|
@ -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<option::Descriptor>& 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;
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <vtkm/cont/internal/RuntimeDeviceOption.h>
|
||||
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -23,47 +23,12 @@ namespace opt = internal::option;
|
||||
namespace
|
||||
{
|
||||
|
||||
static std::vector<std::pair<std::string, std::string>> envVars{};
|
||||
|
||||
enum
|
||||
{
|
||||
UNKNOWN,
|
||||
TEST
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
void MakeArgs(int& argc, char**& argv, T&&... args)
|
||||
{
|
||||
constexpr std::size_t numArgs = sizeof...(args);
|
||||
|
||||
std::array<std::string, numArgs> 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<std::vector<char>, numArgs> vecArgs;
|
||||
static std::array<char*, numArgs + 1> 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<int>(numArgs);
|
||||
argv = finalArgs.data();
|
||||
}
|
||||
|
||||
std::unique_ptr<opt::Option[]> GetOptions(int& argc,
|
||||
char** argv,
|
||||
std::vector<opt::Descriptor>& usage)
|
||||
@ -81,25 +46,6 @@ std::unique_ptr<opt::Option[]> 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<opt::Descriptor> 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<opt::Descriptor> 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<opt::Descriptor> 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();
|
||||
|
@ -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})
|
||||
|
@ -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 <vtkm/cont/kokkos/internal/Initialize.h>
|
||||
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <Kokkos_Core.hpp>
|
||||
VTKM_THIRDPARTY_POST_INCLUDE
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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);
|
||||
}
|
@ -10,10 +10,16 @@
|
||||
#ifndef vtk_m_cont_kokkos_internal_RuntimeDeviceConfigurationKokkos_h
|
||||
#define vtk_m_cont_kokkos_internal_RuntimeDeviceConfigurationKokkos_h
|
||||
|
||||
#include <vtkm/cont/ErrorInternal.h>
|
||||
#include <vtkm/cont/internal/RuntimeDeviceConfiguration.h>
|
||||
#include <vtkm/cont/kokkos/internal/DeviceAdapterTagKokkos.h>
|
||||
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <Kokkos_Core.hpp>
|
||||
VTKM_THIRDPARTY_POST_INCLUDE
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -22,6 +28,52 @@ namespace cont
|
||||
namespace internal
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
VTKM_CONT
|
||||
RuntimeDeviceConfigReturnCode GetArgFromList(const std::vector<std::string>& 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<vtkm::cont::DeviceAdapterTagKokkos>
|
||||
: 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<char*> 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<std::string> KokkosArguments;
|
||||
};
|
||||
|
||||
} // namespace vtkm::cont::internal
|
||||
} // namespace vtkm::cont
|
||||
} // namespace vtkm
|
||||
|
@ -23,6 +23,7 @@ set(unit_tests
|
||||
UnitTestKokkosDeviceAdapter.cxx
|
||||
UnitTestKokkosImplicitFunction.cxx
|
||||
UnitTestKokkosPointLocatorSparseGrid.cxx
|
||||
UnitTestKokkosRuntimeDeviceConfiguration.cxx
|
||||
)
|
||||
|
||||
if (NOT VTKm_NO_DEPRECATED_VIRTUAL)
|
||||
|
@ -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 <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/kokkos/DeviceAdapterKokkos.h>
|
||||
#include <vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h>
|
||||
|
||||
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
|
@ -29,14 +29,13 @@ class RuntimeDeviceConfiguration<vtkm::cont::DeviceAdapterTagOpenMP>
|
||||
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<vtkm::cont::DeviceAdapterTagOpenMP>
|
||||
// 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
|
||||
|
@ -29,7 +29,7 @@ class RuntimeDeviceConfiguration<vtkm::cont::DeviceAdapterTagTBB>
|
||||
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<vtkm::cont::DeviceAdapterTagTBB>
|
||||
// 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
|
||||
|
@ -25,6 +25,7 @@ set(headers
|
||||
TestingFancyArrayHandles.h
|
||||
TestingImplicitFunction.h
|
||||
TestingPointLocatorSparseGrid.h
|
||||
TestingRuntimeDeviceConfiguration.h
|
||||
TestingSerialization.h
|
||||
TestingVirtualObjectHandle.h
|
||||
)
|
||||
|
@ -101,20 +101,8 @@ public:
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
static VTKM_CONT int Run(Func function, int& argc, char* argv[])
|
||||
static VTKM_CONT int ExecuteFunction(Func function)
|
||||
{
|
||||
std::unique_ptr<vtkmdiy::mpi::environment> 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 <class Func>
|
||||
static VTKM_CONT int Run(Func function, int& argc, char* argv[])
|
||||
{
|
||||
std::unique_ptr<vtkmdiy::mpi::environment> 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 <class Func>
|
||||
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 <typename... T>
|
||||
static VTKM_CONT void MakeArgs(int& argc, char**& argv, T&&... args)
|
||||
{
|
||||
constexpr std::size_t numArgs = sizeof...(args);
|
||||
|
||||
std::array<std::string, numArgs> 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<std::vector<char>, numArgs> vecArgs;
|
||||
static std::array<char*, numArgs + 1> 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<int>(numArgs);
|
||||
argv = finalArgs.data();
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
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<std::pair<std::string, std::string>> 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<opt::Descriptor> usage;
|
||||
std::vector<opt::Descriptor> usage;
|
||||
|
||||
usage.push_back({ DATADIR,
|
||||
0,
|
||||
"",
|
||||
"vtkm-data-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --vtkm-data-dir "
|
||||
"<data-dir-path> \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 "
|
||||
"<baseline-dir-path> "
|
||||
"\tPath to the base dir "
|
||||
"for regression test "
|
||||
"images" });
|
||||
usage.push_back({ WRITEDIR,
|
||||
0,
|
||||
"",
|
||||
"vtkm-write-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --vtkm-write-dir "
|
||||
"<write-dir-path> "
|
||||
"\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 "
|
||||
"<data-dir-path> "
|
||||
"\tDEPRECATED: use --vtkm-data-dir instead" });
|
||||
usage.push_back({ DEPRECATED_BASELINEDIR,
|
||||
0,
|
||||
"B",
|
||||
"baseline-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --baseline-dir "
|
||||
"<baseline-dir-path> "
|
||||
"\tDEPRECATED: use --vtkm-baseline-dir instead" });
|
||||
usage.push_back({ WRITEDIR,
|
||||
0,
|
||||
"",
|
||||
"write-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --write-dir "
|
||||
"<write-dir-path> "
|
||||
"\tDEPRECATED: use --vtkm-write-dir instead" });
|
||||
usage.push_back({ DATADIR,
|
||||
0,
|
||||
"",
|
||||
"vtkm-data-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --vtkm-data-dir "
|
||||
"<data-dir-path> \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 "
|
||||
"<baseline-dir-path> "
|
||||
"\tPath to the base dir "
|
||||
"for regression test "
|
||||
"images" });
|
||||
usage.push_back({ WRITEDIR,
|
||||
0,
|
||||
"",
|
||||
"vtkm-write-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --vtkm-write-dir "
|
||||
"<write-dir-path> "
|
||||
"\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 "
|
||||
"<data-dir-path> "
|
||||
"\tDEPRECATED: use --vtkm-data-dir instead" });
|
||||
usage.push_back({ DEPRECATED_BASELINEDIR,
|
||||
0,
|
||||
"B",
|
||||
"baseline-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --baseline-dir "
|
||||
"<baseline-dir-path> "
|
||||
"\tDEPRECATED: use --vtkm-baseline-dir instead" });
|
||||
usage.push_back({ WRITEDIR,
|
||||
0,
|
||||
"",
|
||||
"write-dir",
|
||||
opt::VtkmArg::Required,
|
||||
" --write-dir "
|
||||
"<write-dir-path> "
|
||||
"\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<opt::Option[]> options{ new opt::Option[stats.options_max] };
|
||||
std::unique_ptr<opt::Option[]> 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<opt::Option[]> options{ new opt::Option[stats.options_max] };
|
||||
std::unique_ptr<opt::Option[]> 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 <typename T1, typename T2, typename StorageTag1, typename StorageTag2>
|
||||
|
185
vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h
Normal file
185
vtkm/cont/testing/TestingRuntimeDeviceConfiguration.h
Normal file
@ -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 <vtkm/cont/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/RuntimeDeviceInformation.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/internal/RuntimeDeviceConfiguration.h>
|
||||
#include <vtkm/cont/internal/RuntimeDeviceConfigurationOptions.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace internal = vtkm::cont::internal;
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
namespace testing
|
||||
{
|
||||
|
||||
template <class DeviceAdapterTag>
|
||||
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
|
@ -15,47 +15,12 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr const char* PROGRAM_NAME = "program-name";
|
||||
|
||||
template <typename... T>
|
||||
void MakeArgs(int& argc, char**& argv, T&&... args)
|
||||
{
|
||||
constexpr std::size_t numArgs = sizeof...(args) + 1;
|
||||
|
||||
std::array<std::string, numArgs> 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<std::vector<char>, numArgs> vecArgs;
|
||||
static std::array<char*, numArgs + 1> 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<int>(numArgs);
|
||||
argv = finalArgs.data();
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void CheckArgs(int argc, char* argv[], T&&... args)
|
||||
{
|
||||
constexpr std::size_t numArgs = sizeof...(args) + 1;
|
||||
|
||||
std::array<std::string, numArgs> expectedArgs = { { PROGRAM_NAME, args... } };
|
||||
std::array<std::string, numArgs> 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.");
|
||||
|
Loading…
Reference in New Issue
Block a user