2014-06-10 18:53:34 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2014-06-10 18:53:34 +00:00
|
|
|
// 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.
|
|
|
|
//============================================================================
|
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
#include <vtkm/cont/DeviceAdapterListTag.h>
|
2019-01-09 16:11:49 +00:00
|
|
|
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
2014-06-10 18:53:34 +00:00
|
|
|
#include <vtkm/cont/Timer.h>
|
|
|
|
|
|
|
|
#include <vtkm/cont/testing/Testing.h>
|
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
#include <chrono>
|
|
|
|
#include <thread>
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace
|
|
|
|
{
|
2014-06-10 18:53:34 +00:00
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
struct TimerTestDevices
|
|
|
|
: vtkm::ListTagAppend<VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG, vtkm::cont::DeviceAdapterTagAny>
|
2014-06-10 18:53:34 +00:00
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
};
|
2014-06-10 18:53:34 +00:00
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
constexpr long long waitTimeMilliseconds = 250;
|
2019-03-04 15:23:42 +00:00
|
|
|
constexpr vtkm::Float64 waitTimeSeconds = vtkm::Float64(waitTimeMilliseconds) / 1000;
|
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
struct Waiter
|
2019-02-28 20:36:07 +00:00
|
|
|
{
|
2019-03-15 17:50:17 +00:00
|
|
|
std::chrono::high_resolution_clock::time_point Start = std::chrono::high_resolution_clock::now();
|
|
|
|
long long ExpectedTimeMilliseconds = 0;
|
2019-03-04 15:23:42 +00:00
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
vtkm::Float64 Wait()
|
|
|
|
{
|
|
|
|
// Update when we want to wait to.
|
|
|
|
this->ExpectedTimeMilliseconds += waitTimeMilliseconds;
|
|
|
|
vtkm::Float64 expectedTimeSeconds = vtkm::Float64(this->ExpectedTimeMilliseconds) / 1000;
|
|
|
|
|
|
|
|
long long elapsedMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
std::chrono::high_resolution_clock::now() - this->Start)
|
|
|
|
.count();
|
|
|
|
|
|
|
|
long long millisecondsToSleep = this->ExpectedTimeMilliseconds - elapsedMilliseconds;
|
|
|
|
|
|
|
|
std::cout << " Sleeping for " << millisecondsToSleep << "ms (to " << expectedTimeSeconds
|
|
|
|
<< "s)" << std::endl;
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(millisecondsToSleep));
|
|
|
|
|
|
|
|
VTKM_TEST_ASSERT(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
std::chrono::high_resolution_clock::now() - this->Start)
|
|
|
|
.count() <
|
|
|
|
(this->ExpectedTimeMilliseconds + ((3 * waitTimeMilliseconds) / 4)),
|
|
|
|
"Internal test error: Sleep lasted longer than expected. System must be busy. "
|
|
|
|
"Might need to increase waitTimeMilliseconds.");
|
|
|
|
|
|
|
|
return expectedTimeSeconds;
|
|
|
|
}
|
|
|
|
};
|
2014-06-10 18:53:34 +00:00
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
bool CanTimeOnDevice(const vtkm::cont::Timer& timer, vtkm::cont::DeviceAdapterId device)
|
|
|
|
{
|
|
|
|
if (device == vtkm::cont::DeviceAdapterTagAny())
|
2019-01-09 16:11:49 +00:00
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
// The timer can run on any device. It should pick up something (unless perhaps there are no
|
|
|
|
// devices, which would only happen if you explicitly disable serial, which we don't).
|
|
|
|
return true;
|
2019-01-09 16:11:49 +00:00
|
|
|
}
|
2019-02-28 20:36:07 +00:00
|
|
|
else if ((timer.GetDevice() == vtkm::cont::DeviceAdapterTagAny()) ||
|
|
|
|
(timer.GetDevice() == device))
|
2019-01-09 16:11:49 +00:00
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
// Device is specified and it is a match for the timer's device.
|
2019-03-15 19:59:02 +00:00
|
|
|
return vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(device);
|
2019-01-09 16:11:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
// The requested device does not match the device of the timer.
|
|
|
|
return false;
|
2019-01-09 16:11:49 +00:00
|
|
|
}
|
2019-02-28 20:36:07 +00:00
|
|
|
}
|
2019-01-09 16:11:49 +00:00
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
struct CheckTimeForDeviceFunctor
|
|
|
|
{
|
|
|
|
void operator()(vtkm::cont::DeviceAdapterId device,
|
|
|
|
const vtkm::cont::Timer& timer,
|
|
|
|
vtkm::Float64 expectedTime) const
|
2019-01-09 16:11:49 +00:00
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
std::cout << " Checking time for device " << device.GetName() << std::endl;
|
|
|
|
if (CanTimeOnDevice(timer, device))
|
|
|
|
{
|
|
|
|
vtkm::Float64 elapsedTime = timer.GetElapsedTime(device);
|
|
|
|
VTKM_TEST_ASSERT(
|
|
|
|
elapsedTime > (expectedTime - 0.001), "Timer did not capture full wait. ", elapsedTime);
|
2019-03-04 15:23:42 +00:00
|
|
|
VTKM_TEST_ASSERT(elapsedTime < (expectedTime + waitTimeSeconds),
|
2019-02-28 20:36:07 +00:00
|
|
|
"Timer counted too far or system really busy. ",
|
|
|
|
elapsedTime);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << " Device not supported. Expect 0 back and possible error in log."
|
|
|
|
<< std::endl;
|
|
|
|
VTKM_TEST_ASSERT(timer.GetElapsedTime(device) == 0.0,
|
|
|
|
"Disabled timer should return nothing.");
|
|
|
|
}
|
2019-01-09 16:11:49 +00:00
|
|
|
}
|
2019-02-28 20:36:07 +00:00
|
|
|
};
|
2019-01-09 16:11:49 +00:00
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
void CheckTime(const vtkm::cont::Timer& timer, vtkm::Float64 expectedTime)
|
|
|
|
{
|
2019-03-04 15:23:42 +00:00
|
|
|
std::cout << " Check time for " << expectedTime << "s" << std::endl;
|
2019-02-28 20:36:07 +00:00
|
|
|
vtkm::ListForEach(CheckTimeForDeviceFunctor(), TimerTestDevices(), timer, expectedTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DoTimerCheck(vtkm::cont::Timer& timer)
|
|
|
|
{
|
|
|
|
std::cout << " Starting timer" << std::endl;
|
|
|
|
timer.Start();
|
|
|
|
VTKM_TEST_ASSERT(timer.Started(), "Timer fails to track started status");
|
|
|
|
VTKM_TEST_ASSERT(!timer.Stopped(), "Timer fails to track non stopped status");
|
2019-01-09 16:11:49 +00:00
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
Waiter waiter;
|
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
vtkm::Float64 expectedTime = 0.0;
|
|
|
|
CheckTime(timer, expectedTime);
|
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
expectedTime = waiter.Wait();
|
2019-01-09 16:11:49 +00:00
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
CheckTime(timer, expectedTime);
|
2019-01-09 16:11:49 +00:00
|
|
|
|
2019-02-28 20:36:07 +00:00
|
|
|
std::cout << " Make sure timer is still running" << std::endl;
|
|
|
|
VTKM_TEST_ASSERT(!timer.Stopped(), "Timer fails to track stopped status");
|
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
expectedTime = waiter.Wait();
|
2019-02-28 20:36:07 +00:00
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
CheckTime(timer, expectedTime);
|
2019-02-28 20:36:07 +00:00
|
|
|
|
|
|
|
std::cout << " Stop the timer" << std::endl;
|
2019-01-09 16:11:49 +00:00
|
|
|
timer.Stop();
|
|
|
|
VTKM_TEST_ASSERT(timer.Stopped(), "Timer fails to track stopped status");
|
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
CheckTime(timer, expectedTime);
|
2019-02-28 20:36:07 +00:00
|
|
|
|
2019-03-15 17:50:17 +00:00
|
|
|
waiter.Wait(); // Do not advanced expected time
|
2019-02-28 20:36:07 +00:00
|
|
|
|
2019-03-04 15:23:42 +00:00
|
|
|
std::cout << " Check that timer legitimately stopped" << std::endl;
|
|
|
|
CheckTime(timer, expectedTime);
|
2019-02-28 20:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct TimerCheckFunctor
|
|
|
|
{
|
|
|
|
void operator()(vtkm::cont::DeviceAdapterId device) const
|
|
|
|
{
|
|
|
|
if ((device != vtkm::cont::DeviceAdapterTagAny()) &&
|
2019-03-15 19:59:02 +00:00
|
|
|
!vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(device))
|
2019-02-28 20:36:07 +00:00
|
|
|
{
|
|
|
|
// A timer will not work if set on a device that is not supported. Just skip this test.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::cout << "Checking Timer on device " << device.GetName() << " set with constructor"
|
|
|
|
<< std::endl;
|
|
|
|
vtkm::cont::Timer timer(device);
|
|
|
|
DoTimerCheck(timer);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::cout << "Checking Timer on device " << device.GetName() << " reset" << std::endl;
|
|
|
|
vtkm::cont::Timer timer;
|
|
|
|
timer.Reset(device);
|
|
|
|
DoTimerCheck(timer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void DoTimerTest()
|
|
|
|
{
|
|
|
|
std::cout << "Check default timer" << std::endl;
|
|
|
|
vtkm::cont::Timer timer;
|
|
|
|
DoTimerCheck(timer);
|
|
|
|
|
|
|
|
vtkm::ListForEach(TimerCheckFunctor(), TimerTestDevices());
|
2014-06-10 18:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2019-01-01 22:19:02 +00:00
|
|
|
int UnitTestTimer(int argc, char* argv[])
|
2014-06-10 18:53:34 +00:00
|
|
|
{
|
2019-02-28 20:36:07 +00:00
|
|
|
return vtkm::cont::testing::Testing::Run(DoTimerTest, argc, argv);
|
2014-06-10 18:53:34 +00:00
|
|
|
}
|