diff --git a/docs/changelog/fallback-log.md b/docs/changelog/fallback-log.md new file mode 100644 index 000000000..be6e6d065 --- /dev/null +++ b/docs/changelog/fallback-log.md @@ -0,0 +1,10 @@ +## Added log entry when a cast and call fallback is used + +Several places in VTK-m use the `CastAndCallForTypesWithFallback` method in +`UnknownArrayHandle`. The method works well for catching both common and +corner cases. However, there was no way to know if the efficient direct +method or the (supposedly) less likely fallback of copying data to a float +array was used. VTK-m now adds a log event, registered at the "INFO" level, +whenever data is copied to a fallback float array. This helps developers +monitor the eficiency of their code. + diff --git a/vtkm/cont/UnknownArrayHandle.h b/vtkm/cont/UnknownArrayHandle.h index 714a8f255..f36b02423 100644 --- a/vtkm/cont/UnknownArrayHandle.h +++ b/vtkm/cont/UnknownArrayHandle.h @@ -1207,6 +1207,9 @@ VTKM_CONT void UnknownArrayHandle::CastAndCallForTypesWithFloatFallback(Functor& if (!called) { // Copy to a float array and try again + VTKM_LOG_F(vtkm::cont::LogLevel::Info, + "Cast and call from %s failed. Copying to basic float array.", + this->GetArrayTypeName().c_str()); vtkm::cont::UnknownArrayHandle floatArray = this->NewInstanceFloatBasic(); floatArray.DeepCopyFrom(*this); vtkm::ListForEach(detail::UnknownArrayHandleTry{}, diff --git a/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx b/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx index fa66c6f2a..f411af3ad 100644 --- a/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx +++ b/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx @@ -295,6 +295,60 @@ void TryNewInstance(vtkm::cont::UnknownArrayHandle originalArray) floatArray.AsArrayHandle(staticFloatArray); } +template +struct CheckActualTypeFunctor +{ + template + void operator()(const vtkm::cont::ArrayHandle& array, bool& called) const + { + called = true; + VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size."); + auto portal = array.ReadPortal(); + for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i) + { + T retrieved = portal.Get(i); + ActualT expected = TestValue(i, ActualT{}); + VTKM_TEST_ASSERT(test_equal(retrieved, expected)); + } + } +}; + +template +void TryCastAndCallFallback() +{ + vtkm::cont::UnknownArrayHandle array = CreateArrayUnknown(T{}); + + using FallbackTypes = vtkm::List, + vtkm::Vec, 2>>; + bool called = false; + array.CastAndCallForTypesWithFloatFallback( + CheckActualTypeFunctor{}, called); + VTKM_TEST_ASSERT( + called, "The functor was never called (and apparently a bad value exception not thrown)."); +} + +void TryCastAndCallFallback() +{ + std::cout << " Scalar array." << std::endl; + TryCastAndCallFallback(); + + std::cout << " Equivalent scalar." << std::endl; + TryCastAndCallFallback(); + + std::cout << " Basic Vec." << std::endl; + TryCastAndCallFallback(); + + std::cout << " Vec of Vecs." << std::endl; + TryCastAndCallFallback>(); + + std::cout << " Vec of Vecs of Vecs." << std::endl; + TryCastAndCallFallback, 2>>(); +} + template void TryAsMultiplexer(vtkm::cont::UnknownArrayHandle sourceArray) { @@ -660,6 +714,9 @@ void TestUnknownArrayHandle() std::cout << "Try AsArrayHandle" << std::endl; TryAsArrayHandle(); + std::cout << "Try CastAndCall with fallback" << std::endl; + TryCastAndCallFallback(); + std::cout << "Try ExtractComponent" << std::endl; TryExtractComponent();