From: Ivan Pizarro Date: Thu, 13 Dec 2018 22:33:48 +0000 (+0100) Subject: mem-cache: Sandbox Based Optimal Offset Implementation X-Git-Tag: v19.0.0.0~1084 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=365ed5b9160486c20db192c3df4f025523100d74;p=gem5.git mem-cache: Sandbox Based Optimal Offset Implementation Brown, N. T., & Sendag, R. Sandbox Based Optimal Offset Estimation. Change-Id: Ieb693b6b2c3d8bdfb6948389ca10e92c85454862 Reviewed-on: https://gem5-review.googlesource.com/c/15095 Reviewed-by: Nikos Nikoleris Reviewed-by: Daniel Carvalho Maintainer: Nikos Nikoleris --- diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index 31d748698..e29f121ca 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -363,3 +363,13 @@ class BOPPrefetcher(QueuedPrefetcher): delay_queue_cycles = Param.Cycles(60, "Cycles to delay a write in the left RR table from the delay \ queue") + +class SBOOEPrefetcher(QueuedPrefetcher): + type = 'SBOOEPrefetcher' + cxx_class = 'SBOOEPrefetcher' + cxx_header = "mem/cache/prefetch/sbooe.hh" + latency_buffer_size = Param.Int(32, "Entries in the latency buffer") + sequential_prefetchers = Param.Int(9, "Number of sequential prefetchers") + sandbox_entries = Param.Int(1024, "Size of the address buffer") + score_threshold_pct = Param.Percent(25, "Min. threshold to issue a \ + prefetch. The value is the percentage of sandbox entries to use") diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript index d87b694ed..c96ec4e34 100644 --- a/src/mem/cache/prefetch/SConscript +++ b/src/mem/cache/prefetch/SConscript @@ -38,6 +38,7 @@ Source('bop.cc') Source('delta_correlating_prediction_tables.cc') Source('irregular_stream_buffer.cc') Source('queued.cc') +Source('sbooe.cc') Source('signature_path.cc') Source('signature_path_v2.cc') Source('slim_ampm.cc') diff --git a/src/mem/cache/prefetch/sbooe.cc b/src/mem/cache/prefetch/sbooe.cc new file mode 100644 index 000000000..e1bba9302 --- /dev/null +++ b/src/mem/cache/prefetch/sbooe.cc @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2018 Metempsy Technology Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ivan Pizarro + */ + +#include "mem/cache/prefetch/sbooe.hh" + +#include "debug/HWPrefetch.hh" +#include "params/SBOOEPrefetcher.hh" + +SBOOEPrefetcher::SBOOEPrefetcher(const SBOOEPrefetcherParams *p) + : QueuedPrefetcher(p), + latencyBufferSize(p->latency_buffer_size), + sequentialPrefetchers(p->sequential_prefetchers), + scoreThreshold((p->sandbox_entries*p->score_threshold_pct)/100), + averageAccessLatency(0), latencyBufferSum(0), + bestSandbox(NULL), + accesses(0) +{ + if (!(p->score_threshold_pct >= 0 && p->score_threshold_pct <= 100)) { + fatal("%s: the score threshold should be between 0 and 100\n", name()); + } + + // Initialize a sandbox for every sequential prefetcher between + // -1 and the number of sequential prefetchers defined + for (int i = 0; i < sequentialPrefetchers; i++) { + sandboxes.push_back(Sandbox(p->sandbox_entries, i-1)); + } +} + +void +SBOOEPrefetcher::Sandbox::insert(Addr addr, Tick tick) +{ + entries[index].valid = true; + entries[index].line = addr + stride; + entries[index].expectedArrivalTick = tick; + + index++; + + if (index == entries.size()) { + index = 0; + } +} + +bool +SBOOEPrefetcher::access(Addr access_line) +{ + for (Sandbox &sb : sandboxes) { + // Search for the address in the FIFO queue + for (const SandboxEntry &entry: sb.entries) { + if (entry.valid && entry.line == access_line) { + sb.sandboxScore++; + if (entry.expectedArrivalTick > curTick()) { + sb.lateScore++; + } + } + } + + sb.insert(access_line, curTick() + averageAccessLatency); + + if (bestSandbox == NULL || sb.score() > bestSandbox->score()) { + bestSandbox = &sb; + } + } + + accesses++; + + return (accesses >= sandboxes.size()); +} + +void +SBOOEPrefetcher::notifyFill(const PacketPtr& pkt) +{ + // (1) Look for the address in the demands list + // (2) Calculate the elapsed cycles until it was filled (curTick) + // (3) Insert the latency into the latency buffer (FIFO) + // (4) Calculate the new average access latency + + auto it = demandAddresses.find(pkt->getAddr()); + + if (it != demandAddresses.end()) { + Tick elapsed_ticks = curTick() - it->second; + + latencyBuffer.push_back(elapsed_ticks); + latencyBufferSum += elapsed_ticks; + + if (latencyBuffer.size() > latencyBufferSize) { + latencyBufferSum -= latencyBuffer.front(); + latencyBuffer.pop_front(); + } + + averageAccessLatency = latencyBufferSum / latencyBuffer.size(); + + demandAddresses.erase(it); + } +} + +void +SBOOEPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, + std::vector &addresses) +{ + const Addr pfi_addr = pfi.getAddr(); + const Addr pfi_line = pfi_addr >> lBlkSize; + + auto it = demandAddresses.find(pfi_addr); + + if (it == demandAddresses.end()) { + demandAddresses.insert(std::pair(pfi_addr, curTick())); + } + + const bool evaluationFinished = access(pfi_line); + + if (evaluationFinished && bestSandbox->score() > scoreThreshold) { + Addr pref_line = pfi_line + bestSandbox->stride; + addresses.push_back(AddrPriority(pref_line << lBlkSize, 0)); + } +} + +SBOOEPrefetcher* +SBOOEPrefetcherParams::create() +{ + return new SBOOEPrefetcher(this); +} diff --git a/src/mem/cache/prefetch/sbooe.hh b/src/mem/cache/prefetch/sbooe.hh new file mode 100644 index 000000000..7fa5c35d3 --- /dev/null +++ b/src/mem/cache/prefetch/sbooe.hh @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2018 Metempsy Technology Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ivan Pizarro + */ + +/** + * Implementation of the 'Sandbox Based Optimal Offset Estimation' + * Reference: + * Brown, N. T., & Sendag, R. Sandbox Based Optimal Offset Estimation. +*/ + +#ifndef __MEM_CACHE_PREFETCH_SBOOE_HH__ +#define __MEM_CACHE_PREFETCH_SBOOE_HH__ + +#include +#include +#include + +#include "mem/cache/prefetch/queued.hh" +#include "mem/packet.hh" + +struct SBOOEPrefetcherParams; + +class SBOOEPrefetcher : public QueuedPrefetcher +{ + private: + + /** Prefetcher parameters */ + const int latencyBufferSize; + const int sequentialPrefetchers; + + /** Threshold used to issue prefetchers */ + const unsigned int scoreThreshold; + + /** + * Holds the current demand addresses and tick. This is later used to + * calculate the average latency buffer when the address is filled in + * the cache. + */ + std::unordered_map demandAddresses; + + /** + * The latency buffer holds the elapsed ticks between the demand and + * the fill in the cache for the latest N accesses which are used to + * calculate the average access latency which is later used to + * predict if a prefetcher would be filled on time if issued. + */ + std::deque latencyBuffer; + + /** Holds the current average access latency */ + Tick averageAccessLatency; + + /** Holds the current sum of the latency buffer latency */ + Tick latencyBufferSum; + + struct SandboxEntry { + /** Cache line predicted by the candidate prefetcher */ + Addr line; + /** Tick when the simulated prefetch is expected to be filled */ + Tick expectedArrivalTick; + /** To indicate if it was initialized */ + bool valid; + + SandboxEntry() + : valid(false) + {} + }; + + struct Sandbox { + /** FIFO queue. Max entries is 'sandboxEntries' */ + std::vector entries; + /** + * Accesses during the eval period that were present + * in the sandbox + */ + unsigned int sandboxScore; + /** Hits in the sandbox that wouldn't have been filled on time */ + unsigned int lateScore; + /** Index of the oldest entry in the FIFO */ + unsigned int index; + /** Sequential stride for this prefetcher */ + const int stride; + + Sandbox(unsigned int max_entries, int _stride) + : sandboxScore(0), lateScore(0), index(0), stride(_stride) + { + entries.resize(max_entries); + } + + /** + * Insert the line address being accessed to the cache into the + * FIFO queue of the sandbox. + * @param line Line address being accessed + * @param tick Tick in which the access is expected to be filled + */ + void insert(Addr line, Tick tick); + + /** Calculate the useful score + * @return Useful score of the sandbox. Sandbox score adjusted by + * by the late score + */ + unsigned int score() const { + return (sandboxScore - lateScore); + } + }; + + std::vector sandboxes; + + /** Current best sandbox */ + Sandbox * bestSandbox; + + /** Number of accesses notified to the prefetcher */ + unsigned int accesses; + + /** + * Process an access to the specified line address and update the + * sandbox counters counters. + * @param line Address of the line being accessed + * @return TRUE if the evaluation finished, FALSE otherwise + */ + bool access(Addr line); + + /** Update the latency buffer after a prefetch fill */ + void notifyFill(const PacketPtr& pkt) override; + + public: + SBOOEPrefetcher(const SBOOEPrefetcherParams *p); + + void calculatePrefetch(const PrefetchInfo &pfi, + std::vector &addresses) override; +}; + +#endif // __MEM_CACHE_PREFETCH_SBOOE_HH__