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, "", \