Exercise 9

parent 7f295875
#Makefile
CXX = g++
CXXFLAGS = -std=c++11 -O0 -DNDEBUG
CXXFLAGS += -Wall -Wextra -Wpedantic
.PHONY: all
all: result/plot_a.pdf
result/plot_a.pdf: plot.py result/out.dat result
python plot.py result/out.dat
result/out.dat: cache result
./cache | tee result/out.dat
result:
mkdir result
cache: cache.cpp
.PHONY: clean
clean:
rm -rf result
rm -f cache
/* Programming Techniques for Scientific Simulations, ETH Zürich
*/
#include <vector>
#include <iostream>
#include <iomanip>
#include <chrono>
using array_t = int;
namespace timer = std::chrono;
int main() {
constexpr size_t elem_size = sizeof(array_t);
constexpr size_t MINSIZE = 2;
constexpr size_t MAXSIZE = 2*2*2 * 1024 * 1024; // 2^23
constexpr size_t MAXSTEP = 2*2 *1024; // 2^12
constexpr size_t NUMOPS = 10 * MAXSIZE;
array_t* arr = new array_t[MAXSIZE];
for(size_t N = MINSIZE; N < MAXSIZE; N *= 2) {
for(size_t step = 1; step <= std::min(MAXSTEP, N); step *= 2) {
const size_t num_steps = N / step;
const size_t num_sweeps = NUMOPS / num_steps;
timer::time_point<timer::high_resolution_clock> start , stop;
start = timer::high_resolution_clock::now();
// ------------------ TO DO ----------------------- //
stop = timer::high_resolution_clock::now();
const double time = static_cast<timer::duration<double> >(stop-start).count();
const double numops = num_steps * num_sweeps;
std::cout << std::setprecision(12)
<< std::setw(16) << N * elem_size // array size in bytes
<< std::setw(16) << step * elem_size // touched bytes
<< std::setw(16) << time
<< std::setw(16) << numops
<< std::endl;
}
}
delete[] arr;
return 0;
}
#!/usr/bin/env python
"""
Usage: ./plot.py data_file
"""
import sys
import os
import numpy as np
import matplotlib.pyplot as plt
if len(sys.argv) < 2:
sys.exit('Please provide a filename!')
RESULTS = np.sort(
np.loadtxt(
sys.argv[1],
dtype={
'names': ['size', 'step', 'time', 'nops'],
'formats': ['u4', 'u4', 'f8', 'u4']
}
),
order=['step', 'size']
)
STEPS = np.unique(RESULTS['step'])
STEP_SLICES = [RESULTS['step'] == s for s in STEPS]
plt.figure()
for s, s_slice in zip(STEPS, STEP_SLICES):
if s > 512:
break
plt.semilogx(
RESULTS['size'][s_slice],
1e9 * RESULTS['time'][s_slice] / RESULTS['nops'][s_slice],
label='{} bytes'.format(s),
basex=2
)
plt.title('Part a) Cache and Cacheline Size.')
plt.legend(title='Step Size')
plt.ylabel('time [ns]')
plt.xlabel('array size [bytes]')
plt.savefig(os.path.join('result', 'plot_a.pdf'), bbox_inches='tight')
plt.figure()
for s, s_slice in zip(STEPS, STEP_SLICES):
if s < 1024:
continue
plt.semilogx(
RESULTS['size'][s_slice] / s,
1e9 * RESULTS['time'][s_slice] / RESULTS['nops'][s_slice],
label='{} bytes'.format(s),
basex=2
)
plt.title('Part b) Associativity.')
plt.legend(title='Step Size')
plt.ylabel('time [ns]')
plt.xlabel('array size / step size')
plt.savefig(os.path.join('result', 'plot_b.pdf'), bbox_inches='tight')
#ifndef PENNA_VECTOR_H
#define PENNA_VECTOR_H
#include <vector>
template <class T>
class penna_vector : public std::vector<T> {
using base_t = std::vector<T>;
public:
using typename base_t::value_type;
using typename base_t::iterator;
using typename base_t::size_type;
using base_t::begin;
using base_t::end;
using base_t::back;
using base_t::pop_back;
penna_vector(size_type s=0, value_type x=value_type()) : base_t(s, x) {}
template <class IT>
penna_vector(IT first, IT last) : base_t(first, last) {}
template <class P>
void remove_if(P pred) {
iterator it = begin();
while(it != end()) {
if(pred(*it)) {
*it = back(); // copy the last to this location
pop_back(); // remove the last one
}
else
++it;
}
}
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment