blob: 2ff7f6958861c536149a40edbfc7d91df70a29b2 [file] [log] [blame]
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <memory>
#include <random>
#include <string>
// NOTE: the output does not make sense for now
// TODO: depending on in which directory the file end up these might need to be changed
#include "../demos/asm/measurereadlatency.h"
#include "../demos/instr.h"
#include "../demos/utils.h"
// Determines the latency of reading the first element that was read in random
// order. Elements are "step" size apart from each other (starting from zero) in
// a vector of size "sz", which is given as input. It reads each element of the
// vector and measures the time using MeasureReadLatency(). Later this number
// can be used to determine cache misses and hits
uint64_t FindReadingTime(std::vector<char> buf, int64_t sz, int step) {
// Generate a random order of accesses to eliminate the impact of hw
// prefetchers
std::vector<int64_t> accesses(sz);
for (int64_t i = 0; i < sz; i += step) {
accesses.push_back(i);
}
std::random_device rd;
std::mt19937 f(rd());
std::shuffle(accesses.begin(), accesses.end(), f);
for (int64_t i : accesses) {
ForceRead(&buf[i]);
}
// Read each element in the same random order and keep track of the slowest
// read.
uint64_t max_read_latency = 0;
for (int64_t i : accesses) {
max_read_latency += std::max(max_read_latency,
MeasureReadLatency(&buf[i]));
}
//return MeasureReadLatency(&buf[accesses[0]]);
return max_read_latency;
}
// analyzes a ranges of numbers to find the size of strides that fill a cache
// set and the next read of that stride causes a cache eviction
int cache_set_analysis() {
// size of the cache under analysis
static constexpr int64_t kCacheSize = 8 * 1024 * 1024;
static constexpr int64_t kStrideMaxSize = 2 *1024 * 1024;
static constexpr int64_t kStrideMinSize = 1024;
static constexpr int kIterations = 20;
std::cout << "writing timing results..." << std::endl;
FILE* f = fopen("cache_set_analysis.csv", "w");
if (!f) return 1;
for (int i = 0; i < kIterations; i++) {
for (int64_t step = kStrideMinSize; step <= kStrideMaxSize; step *= 2) {
// size of the buffer under analysis
int64_t sz = kCacheSize + step;
std::vector<char> buf(sz);
fprintf(f, "%d, %lu\n", step, FindReadingTime(buf, sz, step));
std::cout << ".";
std::flush(std::cout);
}
}
fclose(f);
return 0;
}
int main() {
int res = cache_set_analysis();
if (res == 0) {
std::cout << "Cache size analysis was successfully done" << std::endl;
} else {
std::cout << "Cache size analysis failed" << std::endl;
}
return 0;
}