From 31ec44ded53e31fe8f6461ef07558660d228aa24 Mon Sep 17 00:00:00 2001
From: foreman
Date: Mon, 27 Apr 2015 12:21:03 -0400
Subject: [PATCH] P4 to Git Change 1144775 by yaxunl@yaxunl_stg_win50 on
2015/04/27 12:11:07
ECR #304775 - Wave limiter: Fix crash in CompuBenchCL video composition due to profiling data not collected correctly.
Gpuvirtual.cpp only collects profiling data when all events have profiling enabled. Fixed it by adding a member to indicate at least one event has profiling enabled and collect profiling data.
Improved adptation by changing waves/simd only when the last change has been enforced. Also detecting discontinuities in measured data and discard them.
Affected files ...
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuvirtual.cpp#359 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuvirtual.hpp#129 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.hpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/flags.hpp#230 edit
[ROCm/clr commit: b5a5c65e53dc41a805b7202f64c85b14c754abf9]
---
.../rocclr/runtime/device/gpu/gpuvirtual.cpp | 4 +-
.../rocclr/runtime/device/gpu/gpuvirtual.hpp | 1 +
.../runtime/device/gpu/gpuwavelimiter.cpp | 84 ++++++++++++++-----
.../runtime/device/gpu/gpuwavelimiter.hpp | 10 ++-
projects/clr/rocclr/runtime/utils/flags.hpp | 4 +-
5 files changed, 75 insertions(+), 28 deletions(-)
diff --git a/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.cpp b/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.cpp
index 5b2847218a..43c6e42e8d 100644
--- a/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.cpp
+++ b/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.cpp
@@ -403,6 +403,7 @@ VirtualGPU::VirtualGPU(
, schedParamIdx_(0)
, deviceQueueSize_(0)
, hsaQueueMem_(NULL)
+ , profileEnabled_(false)
{
memset(&cal_, 0, sizeof(CalVirtualDesc));
for (uint i = 0; i < AllEngines; ++i) {
@@ -2804,7 +2805,7 @@ VirtualGPU::awaitCompletion(CommandBatch* cb, const amd::Event* waitingEvent)
amd::Command* head = cb->head_;
// Make sure that profiling is enabled
- if (head->profilingInfo().enabled_) {
+ if (profileEnabled_) {
return profilingCollectResults(cb, waitingEvent);
}
// Mark the first command in the batch as running
@@ -3250,6 +3251,7 @@ VirtualGPU::profilingBegin(amd::Command& command, bool drmProfiling)
// Save the TimeStamp object in the current OCL event
command.setData(ts);
currTs_ = ts;
+ profileEnabled_ = true;
}
}
diff --git a/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.hpp b/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.hpp
index d3b5cbd457..131da243e6 100644
--- a/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.hpp
+++ b/projects/clr/rocclr/runtime/device/gpu/gpuvirtual.hpp
@@ -554,6 +554,7 @@ private:
uint deviceQueueSize_; //!< Device queue size
Memory* hsaQueueMem_; //!< Memory for the amd_queue_t object
+ bool profileEnabled_;//!< Profiling is enabled
};
/*@}*/} // namespace gpu
diff --git a/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.cpp b/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
index 88d0de3362..798a6b763b 100644
--- a/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
+++ b/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
@@ -7,6 +7,9 @@
#include "os/os.hpp"
#include "utils/flags.hpp"
+#include
+using namespace std;
+
namespace gpu {
uint WaveLimiter::MaxWave;
@@ -14,14 +17,18 @@ uint WaveLimiter::WarmUpCount;
uint WaveLimiter::AdaptCount;
uint WaveLimiter::RunCount;
uint WaveLimiter::AbandonThresh;
+uint WaveLimiter::DscThresh;
void WaveLimiter::clearData() {
waves_ = MaxWave;
countAll_ = 0;
- clear(counts_);
- clear(sum_);
- clear(average_);
+ clear(measure_);
+ clear(reference_);
+ clear(trial_);
clear(ratio_);
+ discontinuous_ = false;
+ waveSet_ = false;
+ dataCount_ = 0;
}
void WaveLimiter::enable() {
@@ -49,17 +56,17 @@ WaveLimiter::WaveLimiter(Kernel *owner) :
MaxWave = GPU_WAVE_LIMIT_MAX_WAVE;
WarmUpCount = GPU_WAVE_LIMIT_WARMUP;
- AdaptCount = GPU_WAVE_LIMIT_ADAPT * MaxWave;
+ AdaptCount = 2 * MaxWave + 1;
RunCount = GPU_WAVE_LIMIT_RUN * MaxWave;
AbandonThresh = GPU_WAVE_LIMIT_ABANDON;
+ DscThresh = GPU_WAVE_LIMIT_DSC_THRESH;
state_ = WARMUP;
dynRunCount_ = RunCount;
- auto size = MaxWave + 1;
- counts_.resize(size);
- sum_.resize(size);
- average_.resize(size);
- ratio_.resize(size);
+ measure_.resize(MaxWave + 1);
+ reference_.resize(MaxWave + 1);
+ trial_.resize(MaxWave + 1);
+ ratio_.resize(MaxWave + 1);
clearData();
if (!flagIsDefault(GPU_WAVE_LIMIT_TRACE)) {
traceStream_.open(std::string(GPU_WAVE_LIMIT_TRACE) + owner_->name() +
@@ -69,6 +76,7 @@ WaveLimiter::WaveLimiter(Kernel *owner) :
waves_ = GPU_WAVES_PER_SIMD;
bestWave_ = MaxWave;
enable_ = false;
+ waveSet_ = false;
}
WaveLimiter::~WaveLimiter() {
@@ -78,16 +86,34 @@ WaveLimiter::~WaveLimiter() {
}
uint WaveLimiter::getWavesPerSH() const {
+ waveSet_ = true;
return waves_ * SIMDPerSH_;
}
void WaveLimiter::updateData(ulong time) {
- sum_[waves_] += time;
- counts_[waves_]++;
- average_[waves_] = sum_[waves_] / counts_[waves_];
- ratio_[waves_] = average_[waves_] * 100 / average_[MaxWave];
- if (average_[bestWave_] > average_[waves_]) {
- bestWave_ = waves_;
+ auto count = dataCount_ - 1;
+ assert(count < 2 * MaxWave + 1);
+ assert(time > 0);
+ if (count % 2 == 0) {
+ assert(waves_ == MaxWave);
+ auto pos = count / 2;
+ measure_[pos] = time;
+ if (pos > 0) {
+ auto wave = MaxWave + 1 - pos;
+ if (abs(static_cast(measure_[pos - 1]) -
+ static_cast(measure_[pos])) * 100 / measure_[pos] >
+ DscThresh) {
+ discontinuous_ = true;
+ }
+ reference_[wave] = (time + measure_[pos - 1]) / 2;
+ ratio_[wave] = trial_[wave] * 100 / reference_[wave];
+ if (ratio_[bestWave_] > ratio_[wave] && !discontinuous_) {
+ bestWave_ = wave;
+ }
+ }
+ } else {
+ assert(waves_ == MaxWave - count / 2);
+ trial_[waves_] = time;
}
outputTrace();
}
@@ -99,9 +125,8 @@ void WaveLimiter::outputTrace() {
traceStream_ << "[WaveLimiter] " << owner_->name() << " state=" << state_
<< " waves=" << waves_ << " bestWave=" << bestWave_ << '\n';
- output(traceStream_, "\n counts = ", counts_);
- output(traceStream_, "\n sum = ", sum_);
- output(traceStream_, "\n average = ", average_);
+ output(traceStream_, "\n measure = ", measure_);
+ output(traceStream_, "\n reference = ", reference_);
output(traceStream_, "\n ratio = ", ratio_);
traceStream_ << "\n\n";
}
@@ -125,13 +150,26 @@ void WaveLimiter::callback(ulong duration) {
clearData();
return;
case ADAPT:
- updateData(duration);
- if (countAll_ < AdaptCount && ratio_[waves_] < AbandonThresh) {
- waves_ = MaxWave - (countAll_ % MaxWave);
- return;
+ assert(duration > 0);
+ if (waveSet_) {
+ dataCount_++;
+ updateData(duration);
+ waves_ = MaxWave + 1 - dataCount_ / 2;
+ if (dataCount_ == 1 || (dataCount_ < AdaptCount &&
+ !discontinuous_ && (dataCount_ % 2 == 0 ||
+ ratio_[waves_] < AbandonThresh))) {
+ if (dataCount_ % 2 == 1) {
+ --waves_;
+ } else {
+ waves_ = MaxWave;
+ }
+ waveSet_ = false;
+ return;
+ }
}
waves_ = bestWave_;
- if (countAll_ >= AdaptCount) {
+ waveSet_ = false;
+ if (dataCount_ >= AdaptCount) {
dynRunCount_ = RunCount;
} else {
dynRunCount_ = AdaptCount;
diff --git a/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.hpp b/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
index ca5f945e68..bc7816d25f 100644
--- a/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
+++ b/projects/clr/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
@@ -44,10 +44,11 @@ private:
std::vector state_;
};
- std::vector counts_;
- std::vector sum_;
- std::vector average_;
+ std::vector measure_;
+ std::vector reference_;
+ std::vector trial_;
std::vector ratio_;
+ bool discontinuous_; // Measured data is discontinuous
bool enable_;
uint SIMDPerSH_; // Number of SIMDs per SH
@@ -59,12 +60,15 @@ private:
Kernel *owner_;
DataDumper dumper_;
std::ofstream traceStream_;
+ mutable bool waveSet_;
+ uint dataCount_;
static uint MaxWave; // Maximum number of waves per SIMD
static uint WarmUpCount; // Number of kernel executions for warm up
static uint AdaptCount; // Number of kernel executions for adapting
static uint RunCount; // Number of kernel executions for normal run
static uint AbandonThresh; // Threshold to abandon adaptation
+ static uint DscThresh; // Threshold for identifying discontinuities
virtual void callback(ulong duration);
void updateData(ulong time);
diff --git a/projects/clr/rocclr/runtime/utils/flags.hpp b/projects/clr/rocclr/runtime/utils/flags.hpp
index ad5c163351..5cf5048099 100644
--- a/projects/clr/rocclr/runtime/utils/flags.hpp
+++ b/projects/clr/rocclr/runtime/utils/flags.hpp
@@ -188,10 +188,12 @@ release_on_stg(uint, GPU_WAVE_LIMIT_WARMUP, 100, \
"Set warming up kernel execution count for wave limiter") \
release_on_stg(uint, GPU_WAVE_LIMIT_ADAPT, 1, \
"Set adapting factor for wave limiter") \
-release_on_stg(uint, GPU_WAVE_LIMIT_RUN, 40, \
+release_on_stg(uint, GPU_WAVE_LIMIT_RUN, 20, \
"Set running factor for wave limiter") \
release_on_stg(uint, GPU_WAVE_LIMIT_ABANDON, 105, \
"Set abandon threshold for wave limiter") \
+release_on_stg(uint, GPU_WAVE_LIMIT_DSC_THRESH, 10, \
+ "Set threshold for rejecting discontinuous data") \
release_on_stg(cstring, GPU_WAVE_LIMIT_DUMP, "", \
"File path prefix for dumping wave limiter output") \
release_on_stg(cstring, GPU_WAVE_LIMIT_TRACE, "", \