Update comparison for virtual and multiplexer arrays

Previously the "dynamic" array was taken from a VariantArrayHandle.
However, the VariantArrayHandle will actually cast to a basic array, so
the comparison is not particularly fair. Change that to an
ArrayHandleVirtual so that it is actually calling through a virtual
method.

Also make 2 versions of the multiplexer test. The first version has an
array that is at the 1st index and the second is at the last index. This
tests whether the compiled code has to do lots of actual comparisons to
get to the last index.
This commit is contained in:
Kenneth Moreland 2019-07-19 22:23:54 -06:00
parent 5416cbeb7e
commit 866e1d7d5b
2 changed files with 181 additions and 54 deletions

@ -13,11 +13,11 @@
#include <vtkm/cont/ArrayHandle.h> #include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleMultiplexer.h> #include <vtkm/cont/ArrayHandleMultiplexer.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/CellSetStructured.h> #include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/ImplicitFunctionHandle.h> #include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Initialize.h> #include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Timer.h> #include <vtkm/cont/Timer.h>
#include <vtkm/cont/VariantArrayHandle.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h> #include <vtkm/worklet/DispatcherMapTopology.h>
@ -293,6 +293,40 @@ private:
const T2* Function2; const T2* Function2;
}; };
struct PassThroughFunctor
{
template <typename T>
VTKM_EXEC_CONT T operator()(const T& x) const
{
return x;
}
};
template <typename ArrayHandleType>
using ArrayHandlePassThrough =
vtkm::cont::ArrayHandleTransform<ArrayHandleType, PassThroughFunctor, PassThroughFunctor>;
template <typename ArrayHandleType>
using BMArrayHandleMultiplexer =
vtkm::ListTagApply<vtkm::ListTagAppend<vtkm::cont::internal::ArrayHandleMultiplexerDefaultArrays<
typename ArrayHandleType::ValueType>,
ArrayHandlePassThrough<ArrayHandleType>>,
vtkm::cont::ArrayHandleMultiplexer>;
template <typename ArrayHandleType>
BMArrayHandleMultiplexer<ArrayHandleType> make_ArrayHandleMultiplexer0(const ArrayHandleType& array)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
return BMArrayHandleMultiplexer<ArrayHandleType>(array);
}
template <typename ArrayHandleType>
BMArrayHandleMultiplexer<ArrayHandleType> make_ArrayHandleMultiplexerN(const ArrayHandleType& array)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
return BMArrayHandleMultiplexer<ArrayHandleType>(ArrayHandlePassThrough<ArrayHandleType>(array));
}
struct ValueTypes : vtkm::ListTagBase<vtkm::Float32, vtkm::Float64> struct ValueTypes : vtkm::ListTagBase<vtkm::Float32, vtkm::Float64>
{ {
}; };
@ -309,12 +343,6 @@ class BenchmarkFieldAlgorithms
using Timer = vtkm::cont::Timer; using Timer = vtkm::cont::Timer;
using ValueVariantHandle = vtkm::cont::VariantArrayHandleBase<ValueTypes>;
using InterpVariantHandle = vtkm::cont::VariantArrayHandleBase<InterpValueTypes>;
using EdgeIdVariantHandle = vtkm::cont::VariantArrayHandleBase<vtkm::TypeListTagId2>;
using ValueMultiplexerHandle = vtkm::cont::ArrayHandleMultiplexer<vtkm::FloatDefault>;
private: private:
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchBlackScholes struct BenchBlackScholes
@ -397,39 +425,66 @@ private:
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
ValueVariantHandle dstocks(this->StockPrice); return this->Run(vtkm::cont::make_ArrayHandleVirtual(this->StockPrice),
ValueVariantHandle dstrikes(this->OptionStrike); vtkm::cont::make_ArrayHandleVirtual(this->OptionStrike),
ValueVariantHandle doptions(this->OptionYears); vtkm::cont::make_ArrayHandleVirtual(this->OptionYears));
return this->Run(dstocks, dstrikes, doptions);
} }
virtual std::string Type() const { return std::string("Dynamic"); } virtual std::string Type() const { return std::string("Dynamic"); }
}; };
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchBlackScholesMultiplexer : public BenchBlackScholes<Value, DeviceAdapter> struct BenchBlackScholesMultiplexer0 : public BenchBlackScholes<Value, DeviceAdapter>
{ {
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
ValueMultiplexerHandle mstocks( return this->Run(make_ArrayHandleMultiplexer0(this->StockPrice),
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->StockPrice)); make_ArrayHandleMultiplexer0(this->OptionStrike),
ValueMultiplexerHandle mstrikes( make_ArrayHandleMultiplexer0(this->OptionYears));
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->OptionStrike));
ValueMultiplexerHandle moptions(
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->OptionYears));
return this->Run(mstocks, mstrikes, moptions);
} }
virtual std::string Type() const { return std::string("Multiplexer"); } virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexer0(this->StockPrice)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
};
template <typename Value, typename DeviceAdapter>
struct BenchBlackScholesMultiplexerN : public BenchBlackScholes<Value, DeviceAdapter>
{
VTKM_CONT
vtkm::Float64 operator()()
{
return this->Run(make_ArrayHandleMultiplexerN(this->StockPrice),
make_ArrayHandleMultiplexerN(this->OptionStrike),
make_ArrayHandleMultiplexerN(this->OptionYears));
}
virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexerN(this->StockPrice)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
}; };
VTKM_MAKE_BENCHMARK(BlackScholes, BenchBlackScholes); VTKM_MAKE_BENCHMARK(BlackScholes, BenchBlackScholes);
VTKM_MAKE_BENCHMARK(BlackScholesDynamic, BenchBlackScholesDynamic); VTKM_MAKE_BENCHMARK(BlackScholesDynamic, BenchBlackScholesDynamic);
VTKM_MAKE_BENCHMARK(BlackScholesMultiplexer, BenchBlackScholesMultiplexer); VTKM_MAKE_BENCHMARK(BlackScholesMultiplexer0, BenchBlackScholesMultiplexer0);
VTKM_MAKE_BENCHMARK(BlackScholesMultiplexerN, BenchBlackScholesMultiplexerN);
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchMath struct BenchMath
@ -490,13 +545,11 @@ private:
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
using MathTypes = vtkm::ListTagBase<vtkm::Vec<vtkm::Float32, 3>, vtkm::Vec<vtkm::Float64, 3>>;
vtkm::cont::ArrayHandle<Value> temp1; vtkm::cont::ArrayHandle<Value> temp1;
vtkm::cont::ArrayHandle<Value> temp2; vtkm::cont::ArrayHandle<Value> temp2;
vtkm::cont::VariantArrayHandleBase<MathTypes> dinput(this->InputHandle); auto dinput = vtkm::cont::make_ArrayHandleVirtual(this->InputHandle);
ValueVariantHandle dtemp1(temp1); auto dtemp1 = vtkm::cont::make_ArrayHandleVirtual(temp1);
ValueVariantHandle dtemp2(temp2); auto dtemp2 = vtkm::cont::make_ArrayHandleVirtual(temp2);
Timer timer{ DeviceAdapter() }; Timer timer{ DeviceAdapter() };
timer.Start(); timer.Start();
@ -514,7 +567,7 @@ private:
}; };
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchMathMultiplexer : public BenchMath<Value, DeviceAdapter> struct BenchMathMultiplexer0 : public BenchMath<Value, DeviceAdapter>
{ {
VTKM_CONT VTKM_CONT
@ -522,10 +575,9 @@ private:
{ {
vtkm::cont::ArrayHandle<Value> temp1; vtkm::cont::ArrayHandle<Value> temp1;
vtkm::cont::ArrayHandle<Value> temp2; vtkm::cont::ArrayHandle<Value> temp2;
vtkm::cont::ArrayHandleMultiplexer<vtkm::Vec<vtkm::FloatDefault, 3>> mInput( auto mInput = make_ArrayHandleMultiplexer0(this->InputHandle);
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<vtkm::FloatDefault, 3>>(this->InputHandle)); auto mTemp1 = make_ArrayHandleMultiplexer0(temp1);
ValueMultiplexerHandle mTemp1(vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(temp1)); auto mTemp2 = make_ArrayHandleMultiplexer0(temp2);
ValueMultiplexerHandle mTemp2(vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(temp2));
Timer timer{ DeviceAdapter() }; Timer timer{ DeviceAdapter() };
timer.Start(); timer.Start();
@ -539,12 +591,59 @@ private:
return timer.GetElapsedTime(); return timer.GetElapsedTime();
} }
virtual std::string Type() const { return std::string("Multiplexer"); } virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexer0(this->InputHandle)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
};
template <typename Value, typename DeviceAdapter>
struct BenchMathMultiplexerN : public BenchMath<Value, DeviceAdapter>
{
VTKM_CONT
vtkm::Float64 operator()()
{
vtkm::cont::ArrayHandle<Value> temp1;
vtkm::cont::ArrayHandle<Value> temp2;
auto mInput = make_ArrayHandleMultiplexerN(this->InputHandle);
auto mTemp1 = make_ArrayHandleMultiplexerN(temp1);
auto mTemp2 = make_ArrayHandleMultiplexerN(temp2);
Timer timer{ DeviceAdapter() };
timer.Start();
vtkm::worklet::Invoker invoke(DeviceAdapter{});
invoke(Mag{}, mInput, mTemp1);
invoke(Sin{}, mTemp1, mTemp2);
invoke(Square{}, mTemp2, mTemp1);
invoke(Cos{}, mTemp1, mTemp2);
return timer.GetElapsedTime();
}
virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexerN(this->InputHandle)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
}; };
VTKM_MAKE_BENCHMARK(Math, BenchMath); VTKM_MAKE_BENCHMARK(Math, BenchMath);
VTKM_MAKE_BENCHMARK(MathDynamic, BenchMathDynamic); VTKM_MAKE_BENCHMARK(MathDynamic, BenchMathDynamic);
VTKM_MAKE_BENCHMARK(MathMultiplexer, BenchMathMultiplexer); VTKM_MAKE_BENCHMARK(MathMultiplexer0, BenchMathMultiplexer0);
VTKM_MAKE_BENCHMARK(MathMultiplexerN, BenchMathMultiplexerN);
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchFusedMath struct BenchFusedMath
@ -603,35 +702,60 @@ private:
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
using MathTypes = vtkm::ListTagBase<vtkm::Vec<vtkm::Float32, 3>, vtkm::Vec<vtkm::Float64, 3>>; return this->Run(vtkm::cont::make_ArrayHandleVirtual(this->InputHandle));
vtkm::cont::VariantArrayHandleBase<MathTypes> dinput(this->InputHandle);
return this->Run(dinput);
} }
virtual std::string Type() const { return std::string("Dynamic"); } virtual std::string Type() const { return std::string("Dynamic"); }
}; };
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchFusedMathMultiplexer : public BenchFusedMath<Value, DeviceAdapter> struct BenchFusedMathMultiplexer0 : public BenchFusedMath<Value, DeviceAdapter>
{ {
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
vtkm::cont::ArrayHandleMultiplexer<vtkm::Vec<Value, 3>> mInput( return this->Run(make_ArrayHandleMultiplexer0(this->InputHandle));
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<Value, 3>>(this->InputHandle));
return this->Run(mInput);
} }
virtual std::string Type() const { return std::string("Multiplexer"); } virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexer0(this->InputHandle)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
};
template <typename Value, typename DeviceAdapter>
struct BenchFusedMathMultiplexerN : public BenchFusedMath<Value, DeviceAdapter>
{
VTKM_CONT
vtkm::Float64 operator()()
{
return this->Run(make_ArrayHandleMultiplexerN(this->InputHandle));
}
virtual std::string Type() const
{
std::stringstream desc;
desc << "Multiplexer-"
<< make_ArrayHandleMultiplexerN(this->InputHandle)
.GetStorage()
.GetArrayHandleVariant()
.GetIndex();
return desc.str();
}
}; };
VTKM_MAKE_BENCHMARK(FusedMath, BenchFusedMath); VTKM_MAKE_BENCHMARK(FusedMath, BenchFusedMath);
VTKM_MAKE_BENCHMARK(FusedMathDynamic, BenchFusedMathDynamic); VTKM_MAKE_BENCHMARK(FusedMathDynamic, BenchFusedMathDynamic);
VTKM_MAKE_BENCHMARK(FusedMathMultiplexer, BenchFusedMathMultiplexer); VTKM_MAKE_BENCHMARK(FusedMathMultiplexer0, BenchFusedMathMultiplexer0);
VTKM_MAKE_BENCHMARK(FusedMathMultiplexerN, BenchFusedMathMultiplexerN);
template <typename Value, typename DeviceAdapter> template <typename Value, typename DeviceAdapter>
struct BenchEdgeInterp struct BenchEdgeInterp
@ -718,9 +842,9 @@ private:
VTKM_CONT VTKM_CONT
vtkm::Float64 operator()() vtkm::Float64 operator()()
{ {
InterpVariantHandle dfield(this->FieldHandle); auto dfield = vtkm::cont::make_ArrayHandleVirtual(this->FieldHandle);
ValueVariantHandle dweight(this->WeightHandle); auto dweight = vtkm::cont::make_ArrayHandleVirtual(this->WeightHandle);
EdgeIdVariantHandle dedges(this->EdgePairHandle); auto dedges = vtkm::cont::make_ArrayHandleVirtual(this->EdgePairHandle);
vtkm::cont::ArrayHandle<Value> result; vtkm::cont::ArrayHandle<Value> result;
Timer timer{ DeviceAdapter() }; Timer timer{ DeviceAdapter() };
@ -940,7 +1064,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking BlackScholes\n"; std::cout << DIVIDER << "\nBenchmarking BlackScholes\n";
VTKM_RUN_BENCHMARK(BlackScholes, ValueTypes(), id); VTKM_RUN_BENCHMARK(BlackScholes, ValueTypes(), id);
VTKM_RUN_BENCHMARK(BlackScholesDynamic, ValueTypes(), id); VTKM_RUN_BENCHMARK(BlackScholesDynamic, ValueTypes(), id);
VTKM_RUN_BENCHMARK(BlackScholesMultiplexer, ValueTypes(), id); VTKM_RUN_BENCHMARK(BlackScholesMultiplexer0, ValueTypes(), id);
VTKM_RUN_BENCHMARK(BlackScholesMultiplexerN, ValueTypes(), id);
} }
if (benchmarks & MATH) if (benchmarks & MATH)
@ -948,7 +1073,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking Multiple Math Worklets\n"; std::cout << DIVIDER << "\nBenchmarking Multiple Math Worklets\n";
VTKM_RUN_BENCHMARK(Math, ValueTypes(), id); VTKM_RUN_BENCHMARK(Math, ValueTypes(), id);
VTKM_RUN_BENCHMARK(MathDynamic, ValueTypes(), id); VTKM_RUN_BENCHMARK(MathDynamic, ValueTypes(), id);
VTKM_RUN_BENCHMARK(MathMultiplexer, ValueTypes(), id); VTKM_RUN_BENCHMARK(MathMultiplexer0, ValueTypes(), id);
VTKM_RUN_BENCHMARK(MathMultiplexerN, ValueTypes(), id);
} }
if (benchmarks & FUSED_MATH) if (benchmarks & FUSED_MATH)
@ -956,7 +1082,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking Single Fused Math Worklet\n"; std::cout << DIVIDER << "\nBenchmarking Single Fused Math Worklet\n";
VTKM_RUN_BENCHMARK(FusedMath, ValueTypes(), id); VTKM_RUN_BENCHMARK(FusedMath, ValueTypes(), id);
VTKM_RUN_BENCHMARK(FusedMathDynamic, ValueTypes(), id); VTKM_RUN_BENCHMARK(FusedMathDynamic, ValueTypes(), id);
VTKM_RUN_BENCHMARK(FusedMathMultiplexer, ValueTypes(), id); VTKM_RUN_BENCHMARK(FusedMathMultiplexer0, ValueTypes(), id);
VTKM_RUN_BENCHMARK(FusedMathMultiplexerN, ValueTypes(), id);
} }
if (benchmarks & INTERPOLATE_FIELD) if (benchmarks & INTERPOLATE_FIELD)

@ -84,7 +84,7 @@ struct ListTagApplyImpl<brigand::list<Ts...>, Target>
/// ///
template <typename ListTag, template <typename...> class Target> template <typename ListTag, template <typename...> class Target>
using ListTagApply = using ListTagApply =
typename detail::ListTagApplyImpl<internal::ListTagAsBrigandList<ListTag>, Target>; typename detail::ListTagApplyImpl<internal::ListTagAsBrigandList<ListTag>, Target>::type;
/// A special tag for a list that represents holding all potential values /// A special tag for a list that represents holding all potential values
/// ///