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/ArrayHandleMultiplexer.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/VariantArrayHandle.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
@ -293,6 +293,40 @@ private:
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>
{
};
@ -309,12 +343,6 @@ class BenchmarkFieldAlgorithms
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:
template <typename Value, typename DeviceAdapter>
struct BenchBlackScholes
@ -397,39 +425,66 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
ValueVariantHandle dstocks(this->StockPrice);
ValueVariantHandle dstrikes(this->OptionStrike);
ValueVariantHandle doptions(this->OptionYears);
return this->Run(dstocks, dstrikes, doptions);
return this->Run(vtkm::cont::make_ArrayHandleVirtual(this->StockPrice),
vtkm::cont::make_ArrayHandleVirtual(this->OptionStrike),
vtkm::cont::make_ArrayHandleVirtual(this->OptionYears));
}
virtual std::string Type() const { return std::string("Dynamic"); }
};
template <typename Value, typename DeviceAdapter>
struct BenchBlackScholesMultiplexer : public BenchBlackScholes<Value, DeviceAdapter>
struct BenchBlackScholesMultiplexer0 : public BenchBlackScholes<Value, DeviceAdapter>
{
VTKM_CONT
vtkm::Float64 operator()()
{
ValueMultiplexerHandle mstocks(
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->StockPrice));
ValueMultiplexerHandle mstrikes(
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->OptionStrike));
ValueMultiplexerHandle moptions(
vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(this->OptionYears));
return this->Run(mstocks, mstrikes, moptions);
return this->Run(make_ArrayHandleMultiplexer0(this->StockPrice),
make_ArrayHandleMultiplexer0(this->OptionStrike),
make_ArrayHandleMultiplexer0(this->OptionYears));
}
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(BlackScholesDynamic, BenchBlackScholesDynamic);
VTKM_MAKE_BENCHMARK(BlackScholesMultiplexer, BenchBlackScholesMultiplexer);
VTKM_MAKE_BENCHMARK(BlackScholesMultiplexer0, BenchBlackScholesMultiplexer0);
VTKM_MAKE_BENCHMARK(BlackScholesMultiplexerN, BenchBlackScholesMultiplexerN);
template <typename Value, typename DeviceAdapter>
struct BenchMath
@ -490,13 +545,11 @@ private:
VTKM_CONT
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> temp2;
vtkm::cont::VariantArrayHandleBase<MathTypes> dinput(this->InputHandle);
ValueVariantHandle dtemp1(temp1);
ValueVariantHandle dtemp2(temp2);
auto dinput = vtkm::cont::make_ArrayHandleVirtual(this->InputHandle);
auto dtemp1 = vtkm::cont::make_ArrayHandleVirtual(temp1);
auto dtemp2 = vtkm::cont::make_ArrayHandleVirtual(temp2);
Timer timer{ DeviceAdapter() };
timer.Start();
@ -514,7 +567,7 @@ private:
};
template <typename Value, typename DeviceAdapter>
struct BenchMathMultiplexer : public BenchMath<Value, DeviceAdapter>
struct BenchMathMultiplexer0 : public BenchMath<Value, DeviceAdapter>
{
VTKM_CONT
@ -522,10 +575,9 @@ private:
{
vtkm::cont::ArrayHandle<Value> temp1;
vtkm::cont::ArrayHandle<Value> temp2;
vtkm::cont::ArrayHandleMultiplexer<vtkm::Vec<vtkm::FloatDefault, 3>> mInput(
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<vtkm::FloatDefault, 3>>(this->InputHandle));
ValueMultiplexerHandle mTemp1(vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(temp1));
ValueMultiplexerHandle mTemp2(vtkm::cont::make_ArrayHandleCast<vtkm::FloatDefault>(temp2));
auto mInput = make_ArrayHandleMultiplexer0(this->InputHandle);
auto mTemp1 = make_ArrayHandleMultiplexer0(temp1);
auto mTemp2 = make_ArrayHandleMultiplexer0(temp2);
Timer timer{ DeviceAdapter() };
timer.Start();
@ -539,12 +591,59 @@ private:
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(MathDynamic, BenchMathDynamic);
VTKM_MAKE_BENCHMARK(MathMultiplexer, BenchMathMultiplexer);
VTKM_MAKE_BENCHMARK(MathMultiplexer0, BenchMathMultiplexer0);
VTKM_MAKE_BENCHMARK(MathMultiplexerN, BenchMathMultiplexerN);
template <typename Value, typename DeviceAdapter>
struct BenchFusedMath
@ -603,35 +702,60 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using MathTypes = vtkm::ListTagBase<vtkm::Vec<vtkm::Float32, 3>, vtkm::Vec<vtkm::Float64, 3>>;
vtkm::cont::VariantArrayHandleBase<MathTypes> dinput(this->InputHandle);
return this->Run(dinput);
return this->Run(vtkm::cont::make_ArrayHandleVirtual(this->InputHandle));
}
virtual std::string Type() const { return std::string("Dynamic"); }
};
template <typename Value, typename DeviceAdapter>
struct BenchFusedMathMultiplexer : public BenchFusedMath<Value, DeviceAdapter>
struct BenchFusedMathMultiplexer0 : public BenchFusedMath<Value, DeviceAdapter>
{
VTKM_CONT
vtkm::Float64 operator()()
{
vtkm::cont::ArrayHandleMultiplexer<vtkm::Vec<Value, 3>> mInput(
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<Value, 3>>(this->InputHandle));
return this->Run(mInput);
return this->Run(make_ArrayHandleMultiplexer0(this->InputHandle));
}
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(FusedMathDynamic, BenchFusedMathDynamic);
VTKM_MAKE_BENCHMARK(FusedMathMultiplexer, BenchFusedMathMultiplexer);
VTKM_MAKE_BENCHMARK(FusedMathMultiplexer0, BenchFusedMathMultiplexer0);
VTKM_MAKE_BENCHMARK(FusedMathMultiplexerN, BenchFusedMathMultiplexerN);
template <typename Value, typename DeviceAdapter>
struct BenchEdgeInterp
@ -718,9 +842,9 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
InterpVariantHandle dfield(this->FieldHandle);
ValueVariantHandle dweight(this->WeightHandle);
EdgeIdVariantHandle dedges(this->EdgePairHandle);
auto dfield = vtkm::cont::make_ArrayHandleVirtual(this->FieldHandle);
auto dweight = vtkm::cont::make_ArrayHandleVirtual(this->WeightHandle);
auto dedges = vtkm::cont::make_ArrayHandleVirtual(this->EdgePairHandle);
vtkm::cont::ArrayHandle<Value> result;
Timer timer{ DeviceAdapter() };
@ -940,7 +1064,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking BlackScholes\n";
VTKM_RUN_BENCHMARK(BlackScholes, 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)
@ -948,7 +1073,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking Multiple Math Worklets\n";
VTKM_RUN_BENCHMARK(Math, 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)
@ -956,7 +1082,8 @@ public:
std::cout << DIVIDER << "\nBenchmarking Single Fused Math Worklet\n";
VTKM_RUN_BENCHMARK(FusedMath, 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)

@ -84,7 +84,7 @@ struct ListTagApplyImpl<brigand::list<Ts...>, Target>
///
template <typename ListTag, template <typename...> class Target>
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
///