Commit c3fca079 authored by Nick's avatar Nick

Merge remote-tracking branch 'upstream/master'

parents cf491f9d 7c94c82d
Pipeline #147072 failed with stage
in 0 seconds
File added
# CellSets now don't have a name
The requirement that `vtkm::cont::CellSets` have a name was so
cell based `vtkm::cont::Field`'s could be associated with the
correct CellSet in a `vtkm::cont::DataSet`.
Now that `DataSet`'s don't support multiple CellSets, we can remove
the `CellSet` name member variable.
# DataSet queries for CellSet and Coordinate System Indices don't throw
# DataSet queries for CoordinateSystem Indices don't throw
Asking for the index of a `vtkm::cont::CellSet` or `vtkm::cont::CoordinateSystem` by
Asking for the index of a `vtkm::cont::CoordinateSystem` by
name now returns a `-1` when no matching item has been found instead of throwing
an exception.
......
# DataSet only has a single vtkm::cont::CellSet
Multiple `vtkm::cont::CellSets` on a datasets increased the
complexity of using VTK-m correctly without any significant
benefits.
It had the effect that `vtkm::cont::Fields` that representing
cell fields needed to be associated with a given cellset. This
has to be a loose coupling to allow for filters to generate
new output cellsets. At the same time it introduced errors when
that output had a different name.
It raised questions about how should filters propagate cell fields.
Should a filter drop all cell fields not associated with the active
CellSet, or is that too aggressive given the fact that maybe the
algorithm just mistakenly named the field, or the IO routine added
a field with the wrong cellset name.
It increased the complexity of filters, as the developer needed to
determine if the algorithm should support execution on a single `CellSet` or
execution over all `CellSets`.
Given these issues it was deemed that removing multiple `CellSets` was
the correct way forward. People using multiple `CellSets` will need to
move over to `vtkm::cont::MultiBlock` which supports shared points and
fields between multiple blocks.
# Fields now don't require the associated CellSet name
Now that `vtkm::cont::DataSet` can only have a single `vtkm::cont::CellSet`
the requirement that cell based `vtkm::cont::Field`s need a CellSet name
has been lifted.
# FilterField now tries to be smart when selecting active cellset
Now when a calls a `vtkm::filter::FilterField` algorithm without an explicit
active CellSet, if the field is cell based we set the active `vtkm::cont::CellSet`
to be the one associated with that field. If that `vtkm::cont::CellSet` doesn't
exist we default back to using the first CellSet in the input `vtkm::cont::DataSet`.
# vtkm::cont::Filter now don't have an active cell set
`vtkm::filter::FilterField` has removed the concept of `ActiveCellSetIndex`. This
has been done as `vtkm::cont::DataSet` now only contains a single `vtkm::cont::CellSet`.
# Fix cell derivatives for polygon cell shape
For polygon cell shapes (that are not triangles or quadrilaterals),
interpolations are done by finding the center point and creating a triangle
fan around that point. Previously, the gradient was computed in the same
way as interpolation: identifying the correct triangle and computing the
gradient for that triangle.
The problem with that approach is that makes the gradient discontinuous at
the boundaries of this implicit triangle fan. To make things worse, this
discontinuity happens right at each vertex where gradient calculations
happen frequently. This means that when you ask for the gradient at the
vertex, you might get wildly different answers based on floating point
imprecision.
Get around this problem by creating a small triangle around the point in
question, interpolating values to that triangle, and use that for the
gradient. This makes for a smoother gradient transition around these
internal boundaries.
# `MultiBlock` renamed to `PartitionedDataSet`
The `MultiBlock` class has been renamed to `PartitionedDataSet`, and its API
has been refactored to refer to "partitions", rather than "blocks".
Additionally, the `AddBlocks` method has been changed to `AppendPartitions` to
more accurately reflect the operation performed. The associated
`AssignerMultiBlock` class has also been renamed to
`AssignerPartitionedDataSet`.
This change is motivated towards unifying VTK-m's data model with VTK. VTK has
started to move away from `vtkMultiBlockDataSet`, which is a hierarchical tree
of nested datasets, to `vtkPartitionedDataSet`, which is always a flat vector
of datasets used to assist geometry distribution in multi-process environments.
This simplifies traversal during processing and clarifies the intent of the
container: The component datasets are partitions for distribution, not
organizational groupings (e.g. materials).
# Remove ArrayPortalShrink, behavior subsumed by ArrayHandleView
ArrayPortalShrink originaly allowed a user to pass in a delegate array portal
and then shrink the reported array size without actually modifying the
underlying allocation. An iterator was also provided that would
correctly iterate over the shrunken size of the stored array.
Instead of directly shrinking the original array, it is prefered
to create an ArrayHandleView from an ArrayHandle and then specify the
number of values to use in the ArrayHandleView constructor.
# A `ScanExtended` device algorithm has been added.
This new scan algorithm produces an array that contains both an inclusive scan
and an exclusive scan in the same array:
```
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValue.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleView.h>
vtkm::cont::ArrayHandle<T> inputData = ...;
const vtkm::Id size = inputData.GetNumberOfValues();
vtkm::cont::ArrayHandle<T> extendedScan;
vtkm::cont::Algorithm::ScanExtended(inputData, extendedScan);
// The exclusive scan is the first `inputSize` values starting at index 0:
auto exclusiveScan = vtkm::cont::make_ArrayHandleView(extendedScan, 0, size);
// The inclusive scan is the first `inputSize` values starting at index 1:
auto inclusiveScan = vtkm::cont::make_ArrayHandleView(extendedScan, 1, size);
// The total sum of the input data is the last value in the extended scan.
const T totalSum = vtkm::cont::ArrayGetValue(size, extendedScan);
```
This can also be thought of as an exclusive scan that appends the total sum,
rather than returning it.
......@@ -115,7 +115,7 @@ public:
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8> colors;
//get the coordinate system we are using for the 2D area
const vtkm::cont::DynamicCellSet& cells = input.GetCellSet(this->GetActiveCellSetIndex());
const vtkm::cont::DynamicCellSet& cells = input.GetCellSet();
//get the previous state of the game
input.GetField("state", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(prevstate);
......@@ -126,15 +126,10 @@ public:
//save the results
vtkm::cont::DataSet output;
output.AddCellSet(input.GetCellSet(this->GetActiveCellSetIndex()));
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
vtkm::cont::Field colorField("colors", vtkm::cont::Field::Association::POINTS, colors);
output.AddField(colorField);
vtkm::cont::Field stateField("state", vtkm::cont::Field::Association::POINTS, state);
output.AddField(stateField);
output.CopyStructure(input);
output.AddField(vtkm::cont::make_FieldPoint("colors", colors));
output.AddField(vtkm::cont::make_FieldPoint("state", state));
return output;
}
......@@ -206,7 +201,7 @@ struct RenderGameOfLife
void render(vtkm::cont::DataSet& data)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
vtkm::Int32 arraySize = (vtkm::Int32)data.GetCoordinateSystem().GetNumberOfPoints();
vtkm::Int32 arraySize = (vtkm::Int32)data.GetNumberOfPoints();
UploadData task(&this->ColorState,
data.GetField("colors", vtkm::cont::Field::Association::POINTS));
......
......@@ -80,18 +80,18 @@ int main(int argc, char* argv[])
const vtkm::Id num_bins = static_cast<vtkm::Id>(std::atoi(argv[1]));
const vtkm::Id numVals = 1024;
vtkm::cont::MultiBlock mb;
vtkm::cont::PartitionedDataSet pds;
vtkm::cont::DataSet ds;
vtkm::cont::DataSetFieldAdd::AddPointField(ds, "pointvar", CreateArray(-1024, 1024, numVals));
mb.AddBlock(ds);
pds.AppendPartition(ds);
example::HistogramMPI histogram;
histogram.SetActiveField("pointvar");
histogram.SetNumberOfBins(std::max<vtkm::Id>(1, num_bins));
vtkm::cont::MultiBlock result = histogram.Execute(mb);
vtkm::cont::PartitionedDataSet result = histogram.Execute(pds);
vtkm::cont::ArrayHandle<vtkm::Id> bins;
result.GetBlock(0).GetField("histogram").GetData().CopyTo(bins);
result.GetPartition(0).GetField("histogram").GetData().CopyTo(bins);
auto binPortal = bins.GetPortalConstControl();
if (rank == 0)
{
......
......@@ -65,16 +65,16 @@ public:
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
//@{
/// when operating on vtkm::cont::MultiBlock, we
/// when operating on vtkm::cont::PartitionedDataSet, we
/// want to do processing across ranks as well. Just adding pre/post handles
/// for the same does the trick.
template <typename DerivedPolicy>
VTKM_CONT void PreExecute(const vtkm::cont::MultiBlock& input,
VTKM_CONT void PreExecute(const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename DerivedPolicy>
VTKM_CONT void PostExecute(const vtkm::cont::MultiBlock& input,
vtkm::cont::MultiBlock& output,
VTKM_CONT void PostExecute(const vtkm::cont::PartitionedDataSet& input,
vtkm::cont::PartitionedDataSet& output,
const vtkm::filter::PolicyBase<DerivedPolicy>&);
//@}
......
......@@ -12,7 +12,7 @@
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/AssignerMultiBlock.h>
#include <vtkm/cont/AssignerPartitionedDataSet.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/cont/FieldRangeGlobalCompute.h>
......@@ -143,7 +143,7 @@ inline VTKM_CONT vtkm::cont::DataSet HistogramMPI::DoExecute(
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::MultiBlock& input,
inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
if (this->Range.IsNonEmpty())
......@@ -164,15 +164,15 @@ inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::MultiBlock& inp
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::MultiBlock&,
vtkm::cont::MultiBlock& result,
inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::PartitionedDataSet&,
vtkm::cont::PartitionedDataSet& result,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
// iterate and compute HistogramMPI for each local block.
detail::DistributedHistogram helper(result.GetNumberOfBlocks());
for (vtkm::Id cc = 0; cc < result.GetNumberOfBlocks(); ++cc)
detail::DistributedHistogram helper(result.GetNumberOfPartitions());
for (vtkm::Id cc = 0; cc < result.GetNumberOfPartitions(); ++cc)
{
auto& ablock = result.GetBlock(cc);
auto& ablock = result.GetPartition(cc);
helper.SetLocalHistogram(cc, ablock.GetField(this->GetOutputFieldName()));
}
......@@ -182,6 +182,6 @@ inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::MultiBlock&,
helper.ReduceAll(this->NumberOfBins));
output.AddField(rfield);
result = vtkm::cont::MultiBlock(output);
result = vtkm::cont::PartitionedDataSet(output);
}
} // namespace example
......@@ -194,7 +194,7 @@ inline vtkm::cont::DataSet Make3DExplicitDataSet()
conn.push_back(7);
conn.push_back(2);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates", "cells");
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates");
return dataSet;
}
......
......@@ -51,46 +51,47 @@ vtkm::cont::DataSet make_test3DImageData(vtkm::Id3 dims)
}
//=================================================================
void io_generator(TaskQueue<vtkm::cont::MultiBlock>& queue, std::size_t numberOfTasks)
void io_generator(TaskQueue<vtkm::cont::PartitionedDataSet>& queue, std::size_t numberOfTasks)
{
//Step 1. We want to build an initial set of blocks
//Step 1. We want to build an initial set of partitions
//that vary in size. This way we can generate uneven
//work to show off the vtk-m filter work distribution
vtkm::Id3 small(128, 128, 128);
vtkm::Id3 medium(256, 256, 128);
vtkm::Id3 large(512, 256, 128);
std::vector<vtkm::Id3> block_sizes;
block_sizes.push_back(small);
block_sizes.push_back(medium);
block_sizes.push_back(large);
std::vector<vtkm::Id3> partition_sizes;
partition_sizes.push_back(small);
partition_sizes.push_back(medium);
partition_sizes.push_back(large);
std::mt19937 rng;
//uniform_int_distribution is a closed interval [] so both the min and max
//can be chosen values
std::uniform_int_distribution<vtkm::Id> blockNumGen(6, 32);
std::uniform_int_distribution<std::size_t> blockPicker(0, block_sizes.size() - 1);
std::uniform_int_distribution<vtkm::Id> partitionNumGen(6, 32);
std::uniform_int_distribution<std::size_t> partitionPicker(0, partition_sizes.size() - 1);
for (std::size_t i = 0; i < numberOfTasks; ++i)
{
//Step 2. Construct a random number of blocks
const vtkm::Id numberOfBlocks = blockNumGen(rng);
//Step 2. Construct a random number of partitions
const vtkm::Id numberOfPartitions = partitionNumGen(rng);
//Step 3. Randomly pick the blocks in the dataset
vtkm::cont::MultiBlock mb(numberOfBlocks);
for (vtkm::Id b = 0; b < numberOfBlocks; ++b)
//Step 3. Randomly pick the partitions in the dataset
vtkm::cont::PartitionedDataSet pds(numberOfPartitions);
for (vtkm::Id p = 0; p < numberOfPartitions; ++p)
{
const auto& dims = block_sizes[blockPicker(rng)];
auto block = make_test3DImageData(dims);
mb.AddBlock(block);
const auto& dims = partition_sizes[partitionPicker(rng)];
auto partition = make_test3DImageData(dims);
pds.AppendPartition(partition);
}
std::cout << "adding multi-block with " << mb.GetNumberOfBlocks() << " blocks" << std::endl;
std::cout << "adding partitioned dataset with " << pds.GetNumberOfPartitions() << " partitions"
<< std::endl;
//Step 4. Add the multi-block to the queue. We explicitly
//Step 4. Add the partitioned dataset to the queue. We explicitly
//use std::move to signal that this thread can't use the
//mb object after this call
queue.push(std::move(mb));
//pds object after this call
queue.push(std::move(pds));
//Step 5. Go to sleep for a period of time to replicate
//data stream in
......
......@@ -12,9 +12,9 @@
#include "TaskQueue.h"
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
vtkm::cont::DataSet make_test3DImageData(int xdim, int ydim, int zdim);
void io_generator(TaskQueue<vtkm::cont::MultiBlock>& queue, std::size_t numberOfTasks);
void io_generator(TaskQueue<vtkm::cont::PartitionedDataSet>& queue, std::size_t numberOfTasks);
#endif
......@@ -12,7 +12,7 @@
#include <thread>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include "IOGenerator.h"
#include "MultiDeviceGradient.h"
......@@ -22,9 +22,9 @@
//
//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 multiblock.
//The Worker thread will pull down these vtk-m multiblock data and run a
//vtk-m filter on the multiblock.
//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:
......@@ -38,7 +38,7 @@
//and single GPU we should expect that we will have 2 primary 'main loop'
//threads, and 5 threads for heavy 'task' work.
void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue);
void partition_processing(TaskQueue<vtkm::cont::PartitionedDataSet>& queue);
int main(int argc, char** argv)
{
auto opts =
......@@ -48,9 +48,9 @@ int main(int argc, char** argv)
//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::MultiBlock> queue;
TaskQueue<vtkm::cont::PartitionedDataSet> queue;
std::thread io(io_generator, std::ref(queue), 6);
std::thread worker(multiblock_processing, std::ref(queue));
std::thread worker(partition_processing, std::ref(queue));
//Step N. Wait for the work to finish
io.join();
......@@ -59,7 +59,7 @@ int main(int argc, char** argv)
}
//=================================================================
void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue)
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
......@@ -67,42 +67,37 @@ void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue)
gradient.SetComputePointGradient(true);
while (queue.hasTasks())
{
//Step 2. grab the next multi-block skipping any that are empty
//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::MultiBlock mb = queue.pop();
if (mb.GetNumberOfBlocks() == 0)
vtkm::cont::PartitionedDataSet pds = queue.pop();
if (pds.GetNumberOfPartitions() == 0)
{
continue;
}
//Step 3. Get the first field name from the multi-block
std::string fieldName = mb.GetBlock(0).GetField(0).GetName();
//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::MultiBlock result = gradient.Execute(mb);
std::cout << "finished processing a multi-block" << std::endl;
vtkm::cont::PartitionedDataSet result = gradient.Execute(pds);
std::cout << "finished processing a partitioned dataset" << std::endl;
//Step 5. Verify each block has a "Gradients" field
for (auto&& block : result)
//Step 5. Verify each partition has a "Gradients" field
for (auto&& partition : result)
{
// std::cout << std::endl << std::endl << std::endl;
// std::cout << "block: " << std::endl;
// block.PrintSummary(std::cout);
try
{
const auto& field = block.GetField("Gradients", vtkm::cont::Field::Association::POINTS);
(void)field;
}
catch (const vtkm::cont::ErrorBadValue& error)
// 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 << error.GetMessage() << std::endl;
std::cerr << "Missing Gradient field on output partition." << std::endl;
break;
}
}
}
std::cout << "multiblock_processing finished" << std::endl;
std::cout << "partition_processing finished" << std::endl;
}
......@@ -13,6 +13,6 @@
#include "MultiDeviceGradient.h"
#include "MultiDeviceGradient.hxx"
template vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::MultiBlock&,
template vtkm::cont::PartitionedDataSet MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>&);
......@@ -18,7 +18,7 @@
using RuntimeTaskQueue = TaskQueue<std::function<void()>>;
/// \brief Construct a MultiDeviceGradient for a given multiblock dataset
/// \brief Construct a MultiDeviceGradient for a given partitioned dataset
///
/// The Policy used with MultiDeviceGradient must include the TBB and CUDA
/// backends.
......@@ -45,8 +45,8 @@ public:
/// Will submit each block to a work queue that the threads will
/// pull work from
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::MultiBlock PrepareForExecution(
const vtkm::cont::MultiBlock&,
VTKM_CONT vtkm::cont::PartitionedDataSet PrepareForExecution(
const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<DerivedPolicy>&);
private:
......@@ -56,8 +56,8 @@ private:
};
#ifndef vtk_m_examples_multibackend_MultiDeviceGradient_cxx
extern template vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::MultiBlock&,
extern template vtkm::cont::PartitionedDataSet MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>&);
#endif
......
......@@ -32,7 +32,7 @@ int determine_cuda_gpu_count()
return count;
}
void process_block_tbb(RuntimeTaskQueue& queue)
void process_partition_tbb(RuntimeTaskQueue& queue)
{
//Step 1. Set the device adapter to this thread to TBB.
//This makes sure that any vtkm::filters used by our
......@@ -56,11 +56,11 @@ void process_block_tbb(RuntimeTaskQueue& queue)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on tbb (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on tbb (" << std::this_thread::get_id() << ")" << std::endl;
}
}
void process_block_openMP(RuntimeTaskQueue& queue)
void process_partition_openMP(RuntimeTaskQueue& queue)
{
//Step 1. Set the device adapter to this thread to TBB.
//This makes sure that any vtkm::filters used by our
......@@ -84,11 +84,11 @@ void process_block_openMP(RuntimeTaskQueue& queue)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on tbb (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on tbb (" << std::this_thread::get_id() << ")" << std::endl;
}
}
void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
void process_partition_cuda(RuntimeTaskQueue& queue, int gpuId)
{
//Step 1. Set the device adapter to this thread to cuda.
//This makes sure that any vtkm::filters used by our
......@@ -113,7 +113,7 @@ void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on cuda (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on cuda (" << std::this_thread::get_id() << ")" << std::endl;
}
}
......@@ -149,10 +149,10 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
//The number of workers per GPU is purely arbitrary currently,
//but in general we want multiple of them so we can overlap compute
//and transfer
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
}
}
//Step 3. Launch a worker that will use openMP (if enabled).
......@@ -161,7 +161,7 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
else if (runOnOpenMP)
{
std::cout << "adding a openMP worker" << std::endl;
this->Workers.emplace_back(std::bind(process_block_openMP, std::ref(this->Queue)));
this->Workers.emplace_back(std::bind(process_partition_openMP, std::ref(this->Queue)));
}
//Step 4. Launch a worker that will use tbb (if enabled).
//The threads share a queue object so we need to explicitly pass it
......@@ -169,7 +169,7 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
else if (runOnTbb)
{
std::cout << "adding a tbb worker" << std::endl;
this->Workers.emplace_back(std::bind(process_block_tbb, std::ref(this->Queue)));
this->Workers.emplace_back(std::bind(process_partition_tbb, std::ref(this->Queue)));
}
}