mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Add vtkm::exec::TaskBase, and rename WorkletInvokeFunctor to TaskSingular
Previously WorkletInvokeFunctor inherited from vtkm::exec::FunctorBase, which is also the base class for all users Worklets and for all functors based to DeviceAdapter::Schedule. This is done for a few reasons. The first is that we reduce the minimum size of user worklets. Previously the users worklet would hold a reference to the error message, and so would the wrapper class added when calling DeviceAdapter::Schedule. Now we only have the users worklet holding a reference. Second, by refactoring to have two base classes we can better improve the documentation on what responsibilities FunctorBase.h has, compared to TaskBase.
This commit is contained in:
parent
e9898cc5cf
commit
022c36fa4f
@ -36,7 +36,7 @@
|
||||
|
||||
#include <vtkm/exec/cuda/internal/WrappedOperators.h>
|
||||
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
|
||||
#include <vtkm/exec/internal/TaskSingular.h>
|
||||
|
||||
|
||||
|
||||
|
@ -33,6 +33,7 @@ set(headers
|
||||
ImplicitFunction.h
|
||||
Jacobian.h
|
||||
ParametricCoordinates.h
|
||||
TaskBase.h
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -24,12 +24,15 @@
|
||||
|
||||
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
||||
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
|
||||
/// Base class for all functors invoked in the execution environment from a
|
||||
/// call to vtkm::cont::DeviceAdapterAlgorithm::Schedule. Subclasses must
|
||||
/// implement operator() const with an index argument.
|
||||
|
||||
/// Base class for all user worklets invoked in the execution environment from a
|
||||
/// call to vtkm::cont::DeviceAdapterAlgorithm::Schedule.
|
||||
///
|
||||
/// This class contains a public method named RaiseError that can be called in
|
||||
/// the execution environment to signal a problem.
|
||||
@ -56,7 +59,6 @@ public:
|
||||
{
|
||||
this->ErrorMessage = buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
|
||||
};
|
||||
|
42
vtkm/exec/TaskBase.h
Normal file
42
vtkm/exec/TaskBase.h
Normal file
@ -0,0 +1,42 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2014 Sandia Corporation.
|
||||
// Copyright 2014 UT-Battelle, LLC.
|
||||
// Copyright 2014 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_exec_TaskBase_h
|
||||
#define vtk_m_exec_TaskBase_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
|
||||
|
||||
/// Base class for all classes that are used to marshal data from the invocation
|
||||
/// parameters to the user worklets when invoked in the execution environment.
|
||||
/// These classes are generally automatically created by
|
||||
/// vtkm::worklet::internal::DispatcherBase.
|
||||
class TaskBase
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::exec
|
||||
|
||||
#endif //vtk_m_exec_TaskBase_h
|
@ -21,7 +21,7 @@
|
||||
set(headers
|
||||
ErrorMessageBuffer.h
|
||||
ReduceByKeyLookup.h
|
||||
WorkletInvokeFunctor.h
|
||||
TaskSingular.h
|
||||
WorkletInvokeFunctorDetail.h
|
||||
)
|
||||
|
||||
|
@ -17,15 +17,16 @@
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_exec_internal_WorkletInvokeFunctor_h
|
||||
#define vtk_m_exec_internal_WorkletInvokeFunctor_h
|
||||
#ifndef vtk_m_exec_internal_TaskSingular_h
|
||||
#define vtk_m_exec_internal_TaskSingular_h
|
||||
|
||||
#include <vtkm/internal/Invocation.h>
|
||||
|
||||
#include <vtkm/exec/FunctorBase.h>
|
||||
#include <vtkm/exec/TaskBase.h>
|
||||
|
||||
#include <vtkm/exec/arg/Fetch.h>
|
||||
|
||||
//Todo: rename this header to TaskSingularDetail.h
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctorDetail.h>
|
||||
|
||||
namespace vtkm {
|
||||
@ -33,28 +34,26 @@ namespace exec {
|
||||
namespace internal {
|
||||
|
||||
template<typename WorkletType, typename InvocationType>
|
||||
class WorkletInvokeFunctor : public vtkm::exec::FunctorBase
|
||||
class TaskSingular : public vtkm::exec::TaskBase
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
WorkletInvokeFunctor(const WorkletType &worklet,
|
||||
TaskSingular(const WorkletType &worklet,
|
||||
const InvocationType &invocation,
|
||||
const vtkm::Id &globalIndexOffset=0)
|
||||
: Worklet(worklet), Invocation(invocation), GlobalIndexOffset(globalIndexOffset) { }
|
||||
|
||||
VTKM_CONT
|
||||
void SetErrorMessageBuffer(
|
||||
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
|
||||
{
|
||||
this->FunctorBase::SetErrorMessageBuffer(buffer);
|
||||
this->Worklet.SetErrorMessageBuffer(buffer);
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template<typename T>
|
||||
VTKM_EXEC
|
||||
void operator()(T index) const
|
||||
{
|
||||
//Todo: rename this function to DoTaskSingular
|
||||
detail::DoWorkletInvokeFunctor(this->Worklet,
|
||||
this->Invocation,
|
||||
this->Worklet.GetThreadIndices(index,
|
||||
@ -64,10 +63,8 @@ public:
|
||||
GlobalIndexOffset)
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
WorkletType Worklet;
|
||||
|
||||
// This is held by by value so that when we transfer the invocation object
|
||||
// over to CUDA it gets properly copied to the device. While we want to
|
||||
// hold by reference to reduce the number of copies, it is not possible
|
||||
@ -76,8 +73,9 @@ private:
|
||||
const vtkm::Id GlobalIndexOffset;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // vtkm::exec::internal
|
||||
|
||||
#endif //vtk_m_exec_internal_WorkletInvokeFunctor_h
|
||||
#endif //vtk_m_exec_internal_TaskSingular_h
|
@ -28,8 +28,8 @@
|
||||
#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
|
||||
#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
|
||||
|
||||
#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD)
|
||||
#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h
|
||||
#if !defined(vtk_m_exec_internal_TaskSingular_h) && !defined(VTKM_TEST_HEADER_BUILD)
|
||||
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h
|
||||
#endif
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
|
@ -40,8 +40,8 @@ $# Ignore the following comment. It is meant for the generated file.
|
||||
#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
|
||||
#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
|
||||
|
||||
#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD)
|
||||
#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h
|
||||
#if !defined(vtk_m_exec_internal_TaskSingular_h) && !defined(VTKM_TEST_HEADER_BUILD)
|
||||
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h
|
||||
#endif
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
set(unit_tests
|
||||
UnitTestErrorMessageBuffer.cxx
|
||||
UnitTestTaskSingular.cxx
|
||||
UnitTestWorkletInvokeFunctor.cxx
|
||||
)
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
||||
|
309
vtkm/exec/internal/testing/UnitTestTaskSingular.cxx
Normal file
309
vtkm/exec/internal/testing/UnitTestTaskSingular.cxx
Normal file
@ -0,0 +1,309 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2014 Sandia Corporation.
|
||||
// Copyright 2014 UT-Battelle, LLC.
|
||||
// Copyright 2014 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/exec/internal/TaskSingular.h>
|
||||
|
||||
#include <vtkm/exec/arg/BasicArg.h>
|
||||
#include <vtkm/exec/arg/ThreadIndicesBasic.h>
|
||||
#include <vtkm/exec/FunctorBase.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
#include <vtkm/internal/Invocation.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
namespace {
|
||||
|
||||
struct TestExecObject
|
||||
{
|
||||
VTKM_EXEC_CONT
|
||||
TestExecObject() : Value(NULL) { }
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
TestExecObject(vtkm::Id *value) : Value(value) { }
|
||||
|
||||
vtkm::Id *Value;
|
||||
};
|
||||
|
||||
struct MyOutputToInputMapPortal
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
struct MyVisitArrayPortal
|
||||
{
|
||||
typedef vtkm::IdComponent ValueType;
|
||||
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
|
||||
};
|
||||
|
||||
struct TestFetchTagInput { };
|
||||
struct TestFetchTagOutput { };
|
||||
|
||||
// Missing TransportTag, but we are not testing that so we can leave it out.
|
||||
struct TestControlSignatureTagInput
|
||||
{
|
||||
typedef TestFetchTagInput FetchTag;
|
||||
};
|
||||
struct TestControlSignatureTagOutput
|
||||
{
|
||||
typedef TestFetchTagOutput FetchTag;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace arg {
|
||||
|
||||
template<>
|
||||
struct Fetch<
|
||||
TestFetchTagInput,
|
||||
vtkm::exec::arg::AspectTagDefault,
|
||||
vtkm::exec::arg::ThreadIndicesBasic,
|
||||
TestExecObject>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC
|
||||
ValueType Load(const vtkm::exec::arg::ThreadIndicesBasic &indices,
|
||||
const TestExecObject &execObject) const {
|
||||
return *execObject.Value + 10*indices.GetInputIndex();
|
||||
}
|
||||
|
||||
VTKM_EXEC
|
||||
void Store(const vtkm::exec::arg::ThreadIndicesBasic &,
|
||||
const TestExecObject &,
|
||||
ValueType) const {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Fetch<
|
||||
TestFetchTagOutput,
|
||||
vtkm::exec::arg::AspectTagDefault,
|
||||
vtkm::exec::arg::ThreadIndicesBasic,
|
||||
TestExecObject>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC
|
||||
ValueType Load(const vtkm::exec::arg::ThreadIndicesBasic &,
|
||||
const TestExecObject &) const {
|
||||
// No-op
|
||||
return ValueType();
|
||||
}
|
||||
|
||||
VTKM_EXEC
|
||||
void Store(const vtkm::exec::arg::ThreadIndicesBasic &indices,
|
||||
const TestExecObject &execObject,
|
||||
ValueType value) const {
|
||||
*execObject.Value = value + 20*indices.GetOutputIndex();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // vtkm::exec::arg
|
||||
|
||||
namespace {
|
||||
|
||||
typedef void TestControlSignature(TestControlSignatureTagInput,
|
||||
TestControlSignatureTagOutput);
|
||||
typedef vtkm::internal::FunctionInterface<TestControlSignature>
|
||||
TestControlInterface;
|
||||
|
||||
typedef void TestExecutionSignature1(vtkm::exec::arg::BasicArg<1>,
|
||||
vtkm::exec::arg::BasicArg<2>);
|
||||
typedef vtkm::internal::FunctionInterface<TestExecutionSignature1>
|
||||
TestExecutionInterface1;
|
||||
|
||||
typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2(
|
||||
vtkm::exec::arg::BasicArg<1>);
|
||||
typedef vtkm::internal::FunctionInterface<TestExecutionSignature2>
|
||||
TestExecutionInterface2;
|
||||
|
||||
typedef vtkm::internal::FunctionInterface<void(TestExecObject, TestExecObject)>
|
||||
ExecutionParameterInterface;
|
||||
|
||||
typedef vtkm::internal::Invocation<
|
||||
ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface1,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal> InvocationType1;
|
||||
|
||||
typedef vtkm::internal::Invocation<
|
||||
ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal> InvocationType2;
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
{
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Id input, vtkm::Id &output) const
|
||||
{
|
||||
output = input + 100;
|
||||
}
|
||||
|
||||
VTKM_EXEC
|
||||
vtkm::Id operator()(vtkm::Id input) const
|
||||
{
|
||||
return input + 200;
|
||||
}
|
||||
|
||||
template<typename T, typename OutToInArrayType, typename VisitArrayType,
|
||||
typename InputDomainType, typename G>
|
||||
VTKM_EXEC
|
||||
vtkm::exec::arg::ThreadIndicesBasic
|
||||
GetThreadIndices(const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const InputDomainType &,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
|
||||
outToIn.Get(threadIndex),
|
||||
visit.Get(threadIndex),
|
||||
globalThreadIndexOffset );
|
||||
}
|
||||
};
|
||||
|
||||
#define ERROR_MESSAGE "Expected worklet error."
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
|
||||
{
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Id, vtkm::Id) const
|
||||
{
|
||||
this->RaiseError(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
template<typename T, typename OutToInArrayType, typename VisitArrayType,
|
||||
typename InputDomainType, typename G>
|
||||
VTKM_EXEC
|
||||
vtkm::exec::arg::ThreadIndicesBasic
|
||||
GetThreadIndices(const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const InputDomainType &,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
|
||||
outToIn.Get(threadIndex),
|
||||
visit.Get(threadIndex),
|
||||
globalThreadIndexOffset );
|
||||
}
|
||||
};
|
||||
|
||||
// Check behavior of InvocationToFetch helper class.
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,1>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,2>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType2,0>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
|
||||
void TestNormalFunctorInvoke()
|
||||
{
|
||||
std::cout << "Testing normal worklet invoke." << std::endl;
|
||||
|
||||
vtkm::Id inputTestValue;
|
||||
vtkm::Id outputTestValue;
|
||||
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
|
||||
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
|
||||
TestExecObject(&outputTestValue));
|
||||
|
||||
std::cout << " Try void return." << std::endl;
|
||||
inputTestValue = 5;
|
||||
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
typedef vtkm::exec::internal::TaskSingular<TestWorkletProxy,InvocationType1> TaskSingular1;
|
||||
TaskSingular1 taskInvokeWorklet1 =
|
||||
TaskSingular1(TestWorkletProxy(), InvocationType1(execObjects));
|
||||
taskInvokeWorklet1(1);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
|
||||
"Output value not set right.");
|
||||
|
||||
std::cout << " Try return value." << std::endl;
|
||||
inputTestValue = 6;
|
||||
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
typedef vtkm::exec::internal::TaskSingular<TestWorkletProxy,InvocationType2> TaskSingular2;
|
||||
TaskSingular2 taskInvokeWorklet2 =
|
||||
TaskSingular2(TestWorkletProxy(), InvocationType2(execObjects));
|
||||
taskInvokeWorklet2(2);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
|
||||
"Output value not set right.");
|
||||
}
|
||||
|
||||
void TestErrorFunctorInvoke()
|
||||
{
|
||||
std::cout << "Testing invoke with an error raised in the worklet." << std::endl;
|
||||
|
||||
vtkm::Id inputTestValue = 5;
|
||||
vtkm::Id outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
|
||||
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
|
||||
TestExecObject(&outputTestValue));
|
||||
|
||||
typedef vtkm::exec::internal::TaskSingular<TestWorkletErrorProxy,InvocationType1> TaskSingular1;
|
||||
TaskSingular1 taskInvokeWorklet1 =
|
||||
TaskSingular1(TestWorkletErrorProxy(), InvocationType1(execObjects));
|
||||
char message[1024];
|
||||
message[0] = '\0';
|
||||
vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024);
|
||||
taskInvokeWorklet1.SetErrorMessageBuffer(errorMessage);
|
||||
taskInvokeWorklet1(1);
|
||||
|
||||
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly.");
|
||||
VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE),
|
||||
"Got wrong error message.");
|
||||
}
|
||||
|
||||
void TestTaskSingular()
|
||||
{
|
||||
TestNormalFunctorInvoke();
|
||||
TestErrorFunctorInvoke();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestTaskSingular(int, char *[])
|
||||
{
|
||||
return vtkm::testing::Testing::Run(TestTaskSingular);
|
||||
}
|
@ -18,8 +18,9 @@
|
||||
// this software.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
|
||||
#include <vtkm/exec/internal/TaskSingular.h>
|
||||
|
||||
#include <vtkm/exec/FunctorBase.h>
|
||||
#include <vtkm/exec/arg/BasicArg.h>
|
||||
#include <vtkm/exec/arg/ThreadIndicesBasic.h>
|
||||
|
||||
@ -143,25 +144,6 @@ typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2(
|
||||
typedef vtkm::internal::FunctionInterface<TestExecutionSignature2>
|
||||
TestExecutionInterface2;
|
||||
|
||||
typedef vtkm::internal::FunctionInterface<void(TestExecObject, TestExecObject)>
|
||||
ExecutionParameterInterface;
|
||||
|
||||
typedef vtkm::internal::Invocation<
|
||||
ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface1,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal> InvocationType1;
|
||||
|
||||
typedef vtkm::internal::Invocation<
|
||||
ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal> InvocationType2;
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
{
|
||||
@ -177,7 +159,7 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
return input + 200;
|
||||
}
|
||||
|
||||
template<typename T, typename OutToInArrayType, typename VisitArrayType,
|
||||
template<typename T, typename OutToInArrayType, typename VisitArrayType,
|
||||
typename InputDomainType, typename G>
|
||||
VTKM_EXEC
|
||||
vtkm::exec::arg::ThreadIndicesBasic
|
||||
@ -194,48 +176,6 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
}
|
||||
};
|
||||
|
||||
#define ERROR_MESSAGE "Expected worklet error."
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
|
||||
{
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Id, vtkm::Id) const
|
||||
{
|
||||
this->RaiseError(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
template<typename T, typename OutToInArrayType, typename VisitArrayType,
|
||||
typename InputDomainType, typename G>
|
||||
VTKM_EXEC
|
||||
vtkm::exec::arg::ThreadIndicesBasic
|
||||
GetThreadIndices(const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const InputDomainType &,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
|
||||
outToIn.Get(threadIndex),
|
||||
visit.Get(threadIndex),
|
||||
globalThreadIndexOffset );
|
||||
}
|
||||
};
|
||||
|
||||
// Check behavior of InvocationToFetch helper class.
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,1>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,2>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
VTKM_STATIC_ASSERT(( std::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType2,0>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
|
||||
|
||||
template<typename Invocation>
|
||||
void CallDoWorkletInvokeFunctor(const Invocation &invocation, vtkm::Id index)
|
||||
{
|
||||
@ -287,68 +227,10 @@ void TestDoWorkletInvoke()
|
||||
"Output value not set right.");
|
||||
}
|
||||
|
||||
void TestNormalFunctorInvoke()
|
||||
{
|
||||
std::cout << "Testing normal worklet invoke." << std::endl;
|
||||
|
||||
vtkm::Id inputTestValue;
|
||||
vtkm::Id outputTestValue;
|
||||
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
|
||||
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
|
||||
TestExecObject(&outputTestValue));
|
||||
|
||||
std::cout << " Try void return." << std::endl;
|
||||
inputTestValue = 5;
|
||||
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType1> WorkletInvokeFunctor1;
|
||||
WorkletInvokeFunctor1 workletInvokeFunctor1 =
|
||||
WorkletInvokeFunctor1(TestWorkletProxy(), InvocationType1(execObjects));
|
||||
workletInvokeFunctor1(1);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
|
||||
"Output value not set right.");
|
||||
|
||||
std::cout << " Try return value." << std::endl;
|
||||
inputTestValue = 6;
|
||||
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType2> WorkletInvokeFunctor2;
|
||||
WorkletInvokeFunctor2 workletInvokeFunctor2 =
|
||||
WorkletInvokeFunctor2(TestWorkletProxy(), InvocationType2(execObjects));
|
||||
workletInvokeFunctor2(2);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
|
||||
"Output value not set right.");
|
||||
}
|
||||
|
||||
void TestErrorFunctorInvoke()
|
||||
{
|
||||
std::cout << "Testing invoke with an error raised in the worklet." << std::endl;
|
||||
|
||||
vtkm::Id inputTestValue = 5;
|
||||
vtkm::Id outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
|
||||
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
|
||||
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
|
||||
TestExecObject(&outputTestValue));
|
||||
|
||||
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletErrorProxy,InvocationType1> WorkletInvokeFunctor1;
|
||||
WorkletInvokeFunctor1 workletInvokeFunctor1 =
|
||||
WorkletInvokeFunctor1(TestWorkletErrorProxy(), InvocationType1(execObjects));
|
||||
char message[1024];
|
||||
message[0] = '\0';
|
||||
vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024);
|
||||
workletInvokeFunctor1.SetErrorMessageBuffer(errorMessage);
|
||||
workletInvokeFunctor1(1);
|
||||
|
||||
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly.");
|
||||
VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE),
|
||||
"Got wrong error message.");
|
||||
}
|
||||
|
||||
void TestWorkletInvokeFunctor()
|
||||
{
|
||||
TestDoWorkletInvoke();
|
||||
TestNormalFunctorInvoke();
|
||||
TestErrorFunctorInvoke();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -41,7 +41,7 @@ struct DispatcherStreamingMapFieldTransformFunctor
|
||||
VTKM_CONT
|
||||
DispatcherStreamingMapFieldTransformFunctor(
|
||||
vtkm::Id blockIndex, vtkm::Id blockSize, vtkm::Id curBlockSize, vtkm::Id fullSize)
|
||||
: BlockIndex(blockIndex), BlockSize(blockSize),
|
||||
: BlockIndex(blockIndex), BlockSize(blockSize),
|
||||
CurBlockSize(curBlockSize), FullSize(fullSize) { }
|
||||
|
||||
template<typename ParameterType, bool IsArrayHandle>
|
||||
@ -73,10 +73,10 @@ struct DispatcherStreamingMapFieldTransformFunctor
|
||||
{
|
||||
VTKM_CONT
|
||||
vtkm::cont::ArrayHandleStreaming<ArrayHandleType>
|
||||
operator()(const ArrayHandleType &array, vtkm::Id blockIndex,
|
||||
operator()(const ArrayHandleType &array, vtkm::Id blockIndex,
|
||||
vtkm::Id blockSize, vtkm::Id curBlockSize, vtkm::Id fullSize) const
|
||||
{
|
||||
vtkm::cont::ArrayHandleStreaming<ArrayHandleType> result =
|
||||
vtkm::cont::ArrayHandleStreaming<ArrayHandleType> result =
|
||||
vtkm::cont::ArrayHandleStreaming<ArrayHandleType>(
|
||||
array, blockIndex, blockSize, curBlockSize);
|
||||
if (blockIndex == 0) result.AllocateFullArray(fullSize);
|
||||
@ -100,7 +100,7 @@ struct DispatcherStreamingMapFieldTransformFunctor
|
||||
operator()(const ParameterType &invokeData,
|
||||
vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
return TransformImpl<ParameterType,
|
||||
return TransformImpl<ParameterType,
|
||||
vtkm::cont::internal::ArrayHandleCheck<ParameterType>::type::value>()
|
||||
(invokeData, this->BlockIndex, this->BlockSize, this->CurBlockSize, this->FullSize);
|
||||
}
|
||||
@ -115,7 +115,7 @@ struct DispatcherStreamingMapFieldTransferFunctor
|
||||
|
||||
template<typename ParameterType, vtkm::IdComponent Index>
|
||||
struct ReturnType {
|
||||
typedef ParameterType type;
|
||||
typedef ParameterType type;
|
||||
};
|
||||
|
||||
template<typename ParameterType, bool IsArrayHandle>
|
||||
@ -178,7 +178,7 @@ public:
|
||||
: Superclass(worklet), NumberOfBlocks(1) { }
|
||||
|
||||
VTKM_CONT
|
||||
void SetNumberOfBlocks(vtkm::Id numberOfBlocks)
|
||||
void SetNumberOfBlocks(vtkm::Id numberOfBlocks)
|
||||
{
|
||||
NumberOfBlocks = numberOfBlocks;
|
||||
}
|
||||
@ -216,7 +216,7 @@ public:
|
||||
vtkm::Id fullSize = inputDomain.GetNumberOfValues();
|
||||
vtkm::Id blockSize = fullSize / NumberOfBlocks;
|
||||
if (fullSize % NumberOfBlocks != 0) blockSize += 1;
|
||||
|
||||
|
||||
typedef detail::DispatcherStreamingMapFieldTransformFunctor<
|
||||
typename Invocation::ControlInterface, Device> TransformFunctorType;
|
||||
typedef detail::DispatcherStreamingMapFieldTransferFunctor<
|
||||
@ -227,7 +227,7 @@ public:
|
||||
{
|
||||
// Account for domain sizes not evenly divisable by the number of blocks
|
||||
vtkm::Id numberOfInstances = blockSize;
|
||||
if (block == NumberOfBlocks-1)
|
||||
if (block == NumberOfBlocks-1)
|
||||
numberOfInstances = fullSize - blockSize*block;
|
||||
vtkm::Id globalIndexOffset = blockSize*block;
|
||||
|
||||
@ -237,7 +237,7 @@ public:
|
||||
ReportedType newParams = invocation.Parameters.StaticTransformCont(
|
||||
TransformFunctorType(block, blockSize, numberOfInstances, fullSize));
|
||||
|
||||
typedef typename Invocation::template
|
||||
typedef typename Invocation::template
|
||||
ChangeParametersType<ReportedType>::type ChangedType;
|
||||
ChangedType changedParams = invocation.ChangeParameters(newParams);
|
||||
|
||||
@ -302,17 +302,15 @@ private:
|
||||
RangeType globalIndexOffset,
|
||||
DeviceAdapter) const
|
||||
{
|
||||
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
|
||||
// The WorkletInvokeFunctor class handles the magic of fetching values
|
||||
// for each instance and calling the worklet's function. So just create
|
||||
// a WorkletInvokeFunctor and schedule it with the device adapter.
|
||||
typedef vtkm::exec::internal::WorkletInvokeFunctor<WorkletType,Invocation>
|
||||
WorkletInvokeFunctorType;
|
||||
WorkletInvokeFunctorType workletFunctor =
|
||||
WorkletInvokeFunctorType(this->Worklet, invocation, globalIndexOffset);
|
||||
using TaskType = vtkm::exec::internal::TaskSingular<WorkletType,Invocation>;
|
||||
TaskType task = TaskType(this->Worklet, invocation, globalIndexOffset);
|
||||
|
||||
typedef vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter> Algorithm;
|
||||
|
||||
Algorithm::Schedule(workletFunctor, range);
|
||||
Algorithm::Schedule(task, range);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <vtkm/cont/internal/DynamicTransform.h>
|
||||
|
||||
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
|
||||
#include <vtkm/exec/internal/TaskSingular.h>
|
||||
|
||||
#include <vtkm/internal/IntegerSequence.h>
|
||||
#include <vtkm/internal/brigand.hpp>
|
||||
@ -531,10 +531,10 @@ private:
|
||||
RangeType range,
|
||||
DeviceAdapter) const
|
||||
{
|
||||
// The WorkletInvokeFunctor class handles the magic of fetching values
|
||||
// The TaskSingular class handles the magic of fetching values
|
||||
// for each instance and calling the worklet's function. So just create
|
||||
// a WorkletInvokeFunctor and schedule it with the device adapter.
|
||||
typedef vtkm::exec::internal::WorkletInvokeFunctor<WorkletType,Invocation>
|
||||
// a TaskSingular and schedule it with the device adapter.
|
||||
typedef vtkm::exec::internal::TaskSingular<WorkletType,Invocation>
|
||||
WorkletInvokeFunctorType;
|
||||
WorkletInvokeFunctorType workletFunctor =
|
||||
WorkletInvokeFunctorType(this->Worklet, invocation);
|
||||
|
Loading…
Reference in New Issue
Block a user