From 8fe485de9590a6d49f3c261ce80efc1d0cc72d64 Mon Sep 17 00:00:00 2001
From: foreman
Date: Thu, 6 Aug 2015 10:19:59 -0400
Subject: [PATCH] P4 to Git Change 1177724 by jatang@jatang-opencl-hsa-stg1 on
2015/08/06 09:59:33
EPR #424562 - Add Averaging algorithm to Wave Limiter.
1. Extract the algorithms to a sub-class of the wave limiter class.
2. Add Averaging algorithm
This averaging algorithm typically improves performance of BasemarkCL wave simulation by 8% on Tonga/Fiji than the current smooth algorithm. This change has not enable the averaging algorithm yet. Follow-up changes should be made to intelligently select which algorithm to use.
Affected files ...
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.cpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.hpp#4 edit
---
rocclr/runtime/device/gpu/gpuwavelimiter.cpp | 138 +++++++++++++++----
rocclr/runtime/device/gpu/gpuwavelimiter.hpp | 63 ++++++---
2 files changed, 152 insertions(+), 49 deletions(-)
diff --git a/rocclr/runtime/device/gpu/gpuwavelimiter.cpp b/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
index db568d787a..d75005056c 100644
--- a/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
+++ b/rocclr/runtime/device/gpu/gpuwavelimiter.cpp
@@ -14,21 +14,10 @@ namespace gpu {
uint WaveLimiter::MaxWave;
uint WaveLimiter::WarmUpCount;
-uint WaveLimiter::AdaptCount;
uint WaveLimiter::RunCount;
-uint WaveLimiter::AbandonThresh;
-uint WaveLimiter::DscThresh;
-
-void WaveLimiter::clearData() {
- waves_ = MaxWave;
- countAll_ = 0;
- clear(measure_);
- clear(reference_);
- clear(trial_);
- clear(ratio_);
- discontinuous_ = false;
- dataCount_ = 0;
-}
+uint WLAlgorithmSmooth::AdaptCount;
+uint WLAlgorithmSmooth::AbandonThresh;
+uint WLAlgorithmSmooth::DscThresh;
WaveLimiter::WaveLimiter(
Kernel* owner,
@@ -42,21 +31,11 @@ WaveLimiter::WaveLimiter(
auto hwInfo = gpuDev->hwInfo();
setIfNotDefault(SIMDPerSH_, GPU_WAVE_LIMIT_CU_PER_SH,
attrib.numberOfCUsperShaderArray * hwInfo->simdPerCU_);
-
MaxWave = GPU_WAVE_LIMIT_MAX_WAVE;
WarmUpCount = GPU_WAVE_LIMIT_WARMUP;
- 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;
- 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() +
".txt");
@@ -79,7 +58,37 @@ uint WaveLimiter::getWavesPerSH(){
return waves_ * SIMDPerSH_;
}
-void WaveLimiter::updateData(ulong time) {
+WLAlgorithmSmooth::WLAlgorithmSmooth(Kernel* owner, uint seqNum, bool enable, bool enableDump):
+ WaveLimiter(owner, seqNum, enable, enableDump) {
+ AdaptCount = 2 * MaxWave + 1;
+ AbandonThresh = GPU_WAVE_LIMIT_ABANDON;
+ DscThresh = GPU_WAVE_LIMIT_DSC_THRESH;
+
+ dynRunCount_ = RunCount;
+ measure_.resize(MaxWave + 1);
+ reference_.resize(MaxWave + 1);
+ trial_.resize(MaxWave + 1);
+ ratio_.resize(MaxWave + 1);
+
+ clearData();
+}
+
+WLAlgorithmSmooth::~WLAlgorithmSmooth() {
+
+}
+
+void WLAlgorithmSmooth::clearData() {
+ waves_ = MaxWave;
+ countAll_ = 0;
+ clear(measure_);
+ clear(reference_);
+ clear(trial_);
+ clear(ratio_);
+ discontinuous_ = false;
+ dataCount_ = 0;
+}
+
+void WLAlgorithmSmooth::updateData(ulong time) {
auto count = dataCount_ - 1;
assert(count < 2 * MaxWave + 1);
assert(time > 0);
@@ -108,7 +117,7 @@ void WaveLimiter::updateData(ulong time) {
outputTrace();
}
-void WaveLimiter::outputTrace() {
+void WLAlgorithmSmooth::outputTrace() {
if (!traceStream_.is_open()) {
return;
}
@@ -122,7 +131,8 @@ void WaveLimiter::outputTrace() {
traceStream_ << "\n\n";
}
-void WaveLimiter::callback(ulong duration) {
+
+void WLAlgorithmSmooth::callback(ulong duration) {
dumper_.addData(duration, currWaves_, static_cast(state_));
if (!enable_) {
@@ -207,11 +217,79 @@ void WaveLimiter::DataDumper::addData(ulong time, uint wave, char state) {
state_.push_back(state);
}
+WLAlgorithmAvrg::WLAlgorithmAvrg(Kernel* owner, uint seqNum, bool enable, bool enableDump):
+ WaveLimiter(owner, seqNum, enable, enableDump) {
+
+ measure_.resize(MaxWave + 1);
+ clear(measure_);
+ countAll_ = 0;
+}
+
+WLAlgorithmAvrg::~WLAlgorithmAvrg() {
+
+}
+
+void WLAlgorithmAvrg::outputTrace() {
+ if (!traceStream_.is_open()) {
+ return;
+ }
+
+ traceStream_ << "[WaveLimiter] " << owner_->name() << " state=" << state_
+ << " currWaves=" << currWaves_ << " waves=" << waves_
+ << " bestWave=" << bestWave_ << '\n';
+ output(traceStream_, "\n measure = ", measure_);
+ traceStream_ << "\n\n";
+}
+
+
+void WLAlgorithmAvrg::callback(ulong duration) {
+ dumper_.addData(duration, currWaves_, static_cast(state_));
+
+ if (!enable_) {
+ return;
+ }
+
+ countAll_++;
+
+ switch (state_) {
+ case WARMUP:
+ state_ = ADAPT;
+ case ADAPT:
+ measure_[waves_] += duration;
+ if (countAll_ <= MaxWave * 5) {
+ waves_--;
+ if (waves_ == 0) {
+ waves_ = MaxWave;
+ }
+ }
+ else {
+ bestWave_ = MaxWave;
+ for (uint i=1; i(&owner_->dev());
+ auto attrib = gpuDev->getAttribs();
+ auto hwInfo = gpuDev->hwInfo();
+ unsigned simdPerSH = 0;
+ setIfNotDefault(simdPerSH, GPU_WAVE_LIMIT_CU_PER_SH,
+ attrib.numberOfCUsperShaderArray * hwInfo->simdPerCU_);
+ fixed_ = GPU_WAVES_PER_SIMD * simdPerSH;
}
WaveLimiterManager::~WaveLimiterManager() {
@@ -248,7 +326,7 @@ amd::ProfilingCallback* WaveLimiterManager::getProfilingCallback(
return loc->second;
}
- auto limiter = new WaveLimiter(owner_, limiters_.size(), enable_,
+ auto limiter = new WLAlgorithmSmooth(owner_, limiters_.size(), enable_,
enableDump_);
if (limiter == NULL) {
enable_ = false;
diff --git a/rocclr/runtime/device/gpu/gpuwavelimiter.hpp b/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
index 49c25adddf..b8f2d6ce6a 100644
--- a/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
+++ b/rocclr/runtime/device/gpu/gpuwavelimiter.hpp
@@ -27,7 +27,7 @@ public:
//! Get waves per shader array to be used for kernel execution.
uint getWavesPerSH();
-private:
+protected:
enum StateKind {
WARMUP, ADAPT, RUN
};
@@ -51,42 +51,26 @@ private:
};
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
uint waves_; // Waves per SIMD to be set
uint bestWave_; // Optimal waves per SIMD
uint countAll_; // Number of kernel executions
- uint dynRunCount_;
StateKind state_;
Kernel *owner_;
DataDumper dumper_;
std::ofstream traceStream_;
uint currWaves_; // Current waves per SIMD
- 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
//! Call back from Event::recordProfilingInfo to get execution time.
- virtual void callback(ulong duration);
-
- //! Update measurement data and optimal waves/simd with execution time.
- void updateData(ulong time);
+ virtual void callback(ulong duration)=0;
//! Output trace of measurement/adaptation.
- void outputTrace();
-
- //! Clear measurement data for the next adaptation.
- void clearData();
+ virtual void outputTrace()=0;
template void clear(T& A) {
for (auto &I : A) {
@@ -102,6 +86,47 @@ private:
}
};
+class WLAlgorithmSmooth: public WaveLimiter {
+public:
+ explicit WLAlgorithmSmooth(Kernel* owner, uint seqNum, bool enable, bool enableDump);
+ virtual ~WLAlgorithmSmooth();
+private:
+ std::vector reference_;
+ std::vector trial_;
+ std::vector ratio_;
+ bool discontinuous_; // Measured data is discontinuous
+ uint dynRunCount_;
+ uint dataCount_;
+
+ static uint AdaptCount; // Number of kernel executions for adapting
+ static uint AbandonThresh; // Threshold to abandon adaptation
+ static uint DscThresh; // Threshold for identifying discontinuities
+
+ //! Update measurement data and optimal waves/simd with execution time.
+ void updateData(ulong time);
+
+ //! Clear measurement data for the next adaptation.
+ void clearData();
+
+ //! Call back from Event::recordProfilingInfo to get execution time.
+ void callback(ulong duration);
+
+ //! Output trace of measurement/adaptation.
+ void outputTrace();
+};
+
+class WLAlgorithmAvrg: public WaveLimiter {
+public:
+ explicit WLAlgorithmAvrg(Kernel* owner, uint seqNum, bool enable, bool enableDump);
+ virtual ~WLAlgorithmAvrg();
+private:
+ //! Call back from Event::recordProfilingInfo to get execution time.
+ void callback(ulong duration);
+
+ //! Output trace of measurement/adaptation.
+ void outputTrace();
+};
+
// Create wave limiter for each virtual device for a kernel and manages the wave limiters.
class WaveLimiterManager {
public: