2021-12-03 20:44:51 +00:00
|
|
|
//============================================================================
|
|
|
|
// 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/Algorithm.h>
|
|
|
|
#include <vtkm/cont/Logging.h>
|
|
|
|
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
|
|
|
|
|
|
|
#include <vtkm/filter/NewFilter.h>
|
|
|
|
#include <vtkm/filter/TaskQueue.h>
|
|
|
|
|
|
|
|
#include <future>
|
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace filter
|
|
|
|
{
|
2022-08-11 17:43:49 +00:00
|
|
|
|
2022-08-15 18:30:13 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
void RunFilter(NewFilter* self,
|
|
|
|
vtkm::filter::DataSetQueue& input,
|
|
|
|
vtkm::filter::DataSetQueue& output)
|
2021-12-03 20:44:51 +00:00
|
|
|
{
|
2022-08-12 19:29:38 +00:00
|
|
|
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
|
2022-08-18 10:38:15 +00:00
|
|
|
bool prevVal = tracker.GetThreadFriendlyMemAlloc();
|
2022-08-15 18:30:13 +00:00
|
|
|
tracker.SetThreadFriendlyMemAlloc(true);
|
2022-08-11 17:43:49 +00:00
|
|
|
|
2021-12-03 20:44:51 +00:00
|
|
|
std::pair<vtkm::Id, vtkm::cont::DataSet> task;
|
|
|
|
while (input.GetTask(task))
|
|
|
|
{
|
|
|
|
auto outDS = self->Execute(task.second);
|
|
|
|
output.Push(std::make_pair(task.first, std::move(outDS)));
|
|
|
|
}
|
|
|
|
|
|
|
|
vtkm::cont::Algorithm::Synchronize();
|
2022-08-18 10:38:15 +00:00
|
|
|
tracker.SetThreadFriendlyMemAlloc(prevVal);
|
2021-12-03 20:44:51 +00:00
|
|
|
}
|
|
|
|
|
2022-08-15 18:30:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NewFilter::~NewFilter() = default;
|
2021-12-04 02:13:06 +00:00
|
|
|
|
|
|
|
bool NewFilter::CanThread() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-03 20:44:51 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2021-12-13 19:17:15 +00:00
|
|
|
vtkm::cont::PartitionedDataSet NewFilter::DoExecutePartitions(
|
|
|
|
const vtkm::cont::PartitionedDataSet& input)
|
2021-12-03 20:44:51 +00:00
|
|
|
{
|
|
|
|
vtkm::cont::PartitionedDataSet output;
|
|
|
|
|
|
|
|
if (this->GetRunMultiThreadedFilter())
|
|
|
|
{
|
|
|
|
vtkm::filter::DataSetQueue inputQueue(input);
|
|
|
|
vtkm::filter::DataSetQueue outputQueue;
|
|
|
|
|
|
|
|
vtkm::Id numThreads = this->DetermineNumberOfThreads(input);
|
|
|
|
|
|
|
|
//Run 'numThreads' filters.
|
|
|
|
std::vector<std::future<void>> futures(static_cast<std::size_t>(numThreads));
|
|
|
|
for (std::size_t i = 0; i < static_cast<std::size_t>(numThreads); i++)
|
|
|
|
{
|
2022-08-15 18:30:13 +00:00
|
|
|
auto f = std::async(
|
|
|
|
std::launch::async, RunFilter, this, std::ref(inputQueue), std::ref(outputQueue));
|
2021-12-03 20:44:51 +00:00
|
|
|
futures[i] = std::move(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& f : futures)
|
|
|
|
f.get();
|
|
|
|
|
|
|
|
//Get results from the outputQueue.
|
|
|
|
output = outputQueue.Get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (const auto& inBlock : input)
|
|
|
|
{
|
|
|
|
vtkm::cont::DataSet outBlock = this->Execute(inBlock);
|
|
|
|
output.AppendPartition(outBlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:55:54 +00:00
|
|
|
return this->CreateResult(input, output);
|
2021-12-03 20:44:51 +00:00
|
|
|
}
|
2021-12-10 00:28:44 +00:00
|
|
|
|
2021-12-04 02:13:06 +00:00
|
|
|
vtkm::cont::DataSet NewFilter::Execute(const vtkm::cont::DataSet& input)
|
|
|
|
{
|
|
|
|
return this->DoExecute(input);
|
|
|
|
}
|
2021-12-03 20:44:51 +00:00
|
|
|
|
|
|
|
vtkm::cont::PartitionedDataSet NewFilter::Execute(const vtkm::cont::PartitionedDataSet& input)
|
|
|
|
{
|
|
|
|
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf,
|
|
|
|
"NewFilter (%d partitions): '%s'",
|
|
|
|
(int)input.GetNumberOfPartitions(),
|
|
|
|
vtkm::cont::TypeToString<decltype(*this)>().c_str());
|
|
|
|
|
2022-08-26 12:55:54 +00:00
|
|
|
return this->DoExecutePartitions(input);
|
2021-12-03 20:44:51 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 00:11:11 +00:00
|
|
|
vtkm::cont::DataSet NewFilter::CreateResult(const vtkm::cont::DataSet& inDataSet) const
|
|
|
|
{
|
|
|
|
vtkm::cont::DataSet clone;
|
2022-10-31 17:22:37 +00:00
|
|
|
clone.CopyPartsFromExcept(
|
|
|
|
inDataSet, vtkm::cont::DataSet::Parts::Fields | vtkm::cont::DataSet::Parts::Coordinates);
|
|
|
|
this->MapFieldsOntoOutput(inDataSet,
|
|
|
|
this->GetFieldsToPass(),
|
|
|
|
clone,
|
|
|
|
[](vtkm::cont::DataSet& out, const vtkm::cont::Field& fieldToPass) {
|
|
|
|
out.AddField(fieldToPass);
|
|
|
|
});
|
2022-01-27 00:11:11 +00:00
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:55:54 +00:00
|
|
|
vtkm::cont::PartitionedDataSet NewFilter::CreateResult(
|
|
|
|
const vtkm::cont::PartitionedDataSet& input,
|
2022-08-26 16:03:20 +00:00
|
|
|
const vtkm::cont::PartitionedDataSet& resultPartitions) const
|
2022-08-26 12:55:54 +00:00
|
|
|
{
|
2022-08-29 18:58:31 +00:00
|
|
|
auto fieldMapper = [](vtkm::cont::PartitionedDataSet& out, const vtkm::cont::Field& fieldToPass) {
|
|
|
|
out.AddField(fieldToPass);
|
|
|
|
};
|
|
|
|
return this->CreateResult(input, resultPartitions, fieldMapper);
|
2022-08-26 12:55:54 +00:00
|
|
|
}
|
|
|
|
|
2021-12-03 20:44:51 +00:00
|
|
|
vtkm::Id NewFilter::DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input)
|
|
|
|
{
|
|
|
|
vtkm::Id numDS = input.GetNumberOfPartitions();
|
|
|
|
|
|
|
|
vtkm::Id availThreads = 1;
|
|
|
|
|
|
|
|
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
|
|
|
|
|
|
|
|
if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagCuda{}))
|
2022-08-10 20:06:42 +00:00
|
|
|
availThreads = this->NumThreadsPerGPU;
|
2021-12-03 20:44:51 +00:00
|
|
|
else if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagKokkos{}))
|
|
|
|
{
|
|
|
|
//Kokkos doesn't support threading on the CPU.
|
|
|
|
#ifdef VTKM_KOKKOS_CUDA
|
2022-08-10 20:06:42 +00:00
|
|
|
availThreads = this->NumThreadsPerGPU;
|
2021-12-03 20:44:51 +00:00
|
|
|
#else
|
|
|
|
availThreads = 1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagSerial{}))
|
|
|
|
availThreads = 1;
|
|
|
|
else
|
2022-08-10 20:06:42 +00:00
|
|
|
availThreads = this->NumThreadsPerCPU;
|
2021-12-03 20:44:51 +00:00
|
|
|
|
|
|
|
vtkm::Id numThreads = std::min<vtkm::Id>(numDS, availThreads);
|
|
|
|
return numThreads;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace filter
|
|
|
|
} // namespace vtkm
|