mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
The enumerations in `vtkm::cont::Field::Association` were renamed in the previous commit. The old names still exist, but are deprecated. Change the rest of the code to use the new names.
104 lines
3.9 KiB
C++
104 lines
3.9 KiB
C++
//============================================================================
|
|
// 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 <iostream>
|
|
#include <thread>
|
|
|
|
#include <vtkm/cont/Initialize.h>
|
|
#include <vtkm/cont/PartitionedDataSet.h>
|
|
|
|
#include "IOGenerator.h"
|
|
#include "MultiDeviceGradient.h"
|
|
#include "TaskQueue.h"
|
|
|
|
//This demo shows off using vtk-m in multiple threads in two different ways.
|
|
//
|
|
//At a high level we have 2 primary threads, an IO thread and a Worker thread
|
|
//The IO thread will generate all data using the vtk-m serial device, and
|
|
//will post this data to a worker queue as a vtk-m partitioned dataset.
|
|
//The Worker thread will pull down these vtk-m data and run a
|
|
//vtk-m filter on the partitions.
|
|
//The vtk-m filter it runs will itself have a worker pool which it will
|
|
//distribute work too. The number of workers is based on what device adapters
|
|
//are enabled but uses the following logic:
|
|
// - If TBB is enabled construct a single TBB worker
|
|
// - If CUDA is enabled construct 4 workers for each GPU on the machine
|
|
//
|
|
//Unfortunately due to some thread unsafe logic in VTK-m it is currently not
|
|
//possible to have CUDA and TBB workers at the same time. So the class will
|
|
//choose CUDA over TBB when possible.
|
|
//Once the thread unsafe logic is fixed a machine that has a single CPU
|
|
//and single GPU we should expect that we will have 2 primary 'main loop'
|
|
//threads, and 5 threads for heavy 'task' work.
|
|
|
|
void partition_processing(TaskQueue<vtkm::cont::PartitionedDataSet>& queue);
|
|
int main(int argc, char** argv)
|
|
{
|
|
auto opts =
|
|
vtkm::cont::InitializeOptions::DefaultAnyDevice | vtkm::cont::InitializeOptions::Strict;
|
|
vtkm::cont::Initialize(argc, argv, opts);
|
|
|
|
//Step 1. Construct the two primary 'main loops'. The threads
|
|
//share a queue object so we need to explicitly pass it
|
|
//by reference (the std::ref call)
|
|
TaskQueue<vtkm::cont::PartitionedDataSet> queue;
|
|
std::thread io(io_generator, std::ref(queue), 6);
|
|
std::thread worker(partition_processing, std::ref(queue));
|
|
|
|
//Step N. Wait for the work to finish
|
|
io.join();
|
|
worker.join();
|
|
return 0;
|
|
}
|
|
|
|
//=================================================================
|
|
void partition_processing(TaskQueue<vtkm::cont::PartitionedDataSet>& queue)
|
|
{
|
|
//Step 1. Construct the gradient filter outside the work loop
|
|
//so that we can reuse the thread pool it constructs
|
|
MultiDeviceGradient gradient;
|
|
gradient.SetComputePointGradient(true);
|
|
while (queue.hasTasks())
|
|
{
|
|
//Step 2. grab the next partition skipping any that are empty
|
|
//as empty ones can be returned when the queue is about
|
|
//to say it has no work
|
|
vtkm::cont::PartitionedDataSet pds = queue.pop();
|
|
if (pds.GetNumberOfPartitions() == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//Step 3. Get the first field name from the partition
|
|
std::string fieldName = pds.GetPartition(0).GetField(0).GetName();
|
|
|
|
//Step 4. Run a multi device gradient
|
|
gradient.SetActiveField(fieldName);
|
|
vtkm::cont::PartitionedDataSet result = gradient.Execute(pds);
|
|
std::cout << "finished processing a partitioned dataset" << std::endl;
|
|
|
|
//Step 5. Verify each partition has a "Gradients" field
|
|
for (auto&& partition : result)
|
|
{
|
|
// std::cout << std::endl << std::endl << std::endl;
|
|
// std::cout << "partition: " << std::endl;
|
|
// partition.PrintSummary(std::cout);
|
|
if (!partition.HasField("Gradients", vtkm::cont::Field::Association::Points))
|
|
{
|
|
std::cerr << "Gradient filter failed!" << std::endl;
|
|
std::cerr << "Missing Gradient field on output partition." << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::cout << "partition_processing finished" << std::endl;
|
|
}
|