Time measurement + basic optimizations
This commit is contained in:
parent
d9f7e6ab5a
commit
8a48e00d17
10
Makefile
10
Makefile
@ -1,11 +1,13 @@
|
|||||||
CXX = g++
|
CXX = g++
|
||||||
CXXFLAGS = -Wall
|
CXXFLAGS = -Wall -O3
|
||||||
|
|
||||||
gol: main.o
|
gol: main.o Timing.o
|
||||||
$(CXX) $(CXXFLAGS) -o gol main.o
|
$(CXX) $(CXXFLAGS) -o gol main.o Timing.o
|
||||||
|
|
||||||
main.o: main.cpp
|
main.o: main.cpp Timing.h
|
||||||
$(CXX) $(CXXFLAGS) -c main.cpp
|
$(CXX) $(CXXFLAGS) -c main.cpp
|
||||||
|
|
||||||
|
Timing.o: Timing.h
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
-rm *.o gol
|
-rm *.o gol
|
||||||
|
163
Timing.cpp
Normal file
163
Timing.cpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "Timing.h"
|
||||||
|
|
||||||
|
Timing* Timing::mInstance = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton: Get instance.
|
||||||
|
*/
|
||||||
|
Timing* Timing::getInstance() {
|
||||||
|
if (mInstance == 0) {
|
||||||
|
mInstance = new Timing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start recording time with any name.
|
||||||
|
*/
|
||||||
|
void Timing::startRecord(const std::string& name) {
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto it = mRecordings.find(name);
|
||||||
|
if (it != mRecordings.end()) {
|
||||||
|
it->second = start;
|
||||||
|
} else {
|
||||||
|
mRecordings.insert(std::pair<std::string, std::chrono::high_resolution_clock::time_point>(name, start));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop recording time with any name.
|
||||||
|
*/
|
||||||
|
void Timing::stopRecord(const std::string& name) {
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto it = mRecordings.find(name);
|
||||||
|
if (it != mRecordings.end()) {
|
||||||
|
auto start = it->second;
|
||||||
|
auto result = end - start;
|
||||||
|
|
||||||
|
mResults.insert(std::pair<std::string, std::chrono::duration<double, std::milli> >(name, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print measured results human-readable.
|
||||||
|
* Set prettyPrint to true to display mm:ss.ms instead of ms.
|
||||||
|
*/
|
||||||
|
void Timing::print(const bool prettyPrint) const {
|
||||||
|
std::cout << "-----" << std::endl << "Results: " << std::endl << "-----" << std::endl;
|
||||||
|
|
||||||
|
auto it = mResults.begin();
|
||||||
|
while(it != mResults.end()) {
|
||||||
|
if (prettyPrint) {
|
||||||
|
std::cout << it->first << ": " << parseDate((int) it->second.count()) << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << it->first << ": " << it->second.count() << "ms" << std::endl;
|
||||||
|
}
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "-----" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse date from ms to mm:ss.ms.
|
||||||
|
*/
|
||||||
|
std::string Timing::parseDate(const int ms) const {
|
||||||
|
int minutes = (int) (ms / 1000 / 60);
|
||||||
|
int seconds = (int) ((ms % (1000 * 60)) / 1000);
|
||||||
|
int milliseconds = (int) (ms % 1000);
|
||||||
|
|
||||||
|
std::ostringstream stringStream;
|
||||||
|
if (seconds == 60) {
|
||||||
|
stringStream << minutes + 1 << ":00" << seconds << ".";
|
||||||
|
} else {
|
||||||
|
stringStream << minutes << ":" << (seconds < 10 ? "0" : "") << seconds << ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (milliseconds < 100) {
|
||||||
|
if (milliseconds < 10) {
|
||||||
|
stringStream << "00" << milliseconds;
|
||||||
|
} else {
|
||||||
|
stringStream << "0" << milliseconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stringStream << milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringStream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get results of setup, computation and finalization in form:
|
||||||
|
* mm:ss.ms;mm:ss.ms;mm.ss.ms
|
||||||
|
*/
|
||||||
|
std::string Timing::getResults() const {
|
||||||
|
std::ostringstream stringStream;
|
||||||
|
|
||||||
|
auto start = mResults.find("setup");
|
||||||
|
if (start != mResults.end()) {
|
||||||
|
stringStream << parseDate((int) start->second.count()) << ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto computation = mResults.find("computation");
|
||||||
|
if (computation != mResults.end()) {
|
||||||
|
stringStream << parseDate((int) computation->second.count()) << ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto finalization = mResults.find("finalization");
|
||||||
|
if (start != mResults.end()) {
|
||||||
|
stringStream << parseDate((int) finalization->second.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringStream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start recording the setup time.
|
||||||
|
*/
|
||||||
|
void Timing::startSetup() {
|
||||||
|
this->startRecord("setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop recording the setup time.
|
||||||
|
*/
|
||||||
|
void Timing::stopSetup() {
|
||||||
|
this->stopRecord("setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start recording the computation time.
|
||||||
|
*/
|
||||||
|
void Timing::startComputation() {
|
||||||
|
this->startRecord("computation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop recording the computation time.
|
||||||
|
*/
|
||||||
|
void Timing::stopComputation() {
|
||||||
|
this->stopRecord("computation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start recording the finalization time.
|
||||||
|
*/
|
||||||
|
void Timing::startFinalization() {
|
||||||
|
this->startRecord("finalization");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop recording the finalization time.
|
||||||
|
*/
|
||||||
|
void Timing::stopFinalization() {
|
||||||
|
this->stopRecord("finalization");
|
||||||
|
}
|
33
Timing.h
Normal file
33
Timing.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Measure high precision time intervals (using std::chrono).
|
||||||
|
* Author: Karl Hofer <hoferk@technikum-wien.at>
|
||||||
|
*/
|
||||||
|
class Timing {
|
||||||
|
public:
|
||||||
|
static Timing* getInstance();
|
||||||
|
|
||||||
|
void startSetup();
|
||||||
|
void stopSetup();
|
||||||
|
void startComputation();
|
||||||
|
void stopComputation();
|
||||||
|
void startFinalization();
|
||||||
|
void stopFinalization();
|
||||||
|
|
||||||
|
void startRecord(const std::string& name);
|
||||||
|
void stopRecord(const std::string& name);
|
||||||
|
void print(const bool prettyPrint = false) const;
|
||||||
|
std::string getResults() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Timing() {};
|
||||||
|
std::map<std::string, std::chrono::high_resolution_clock::time_point > mRecordings;
|
||||||
|
std::map<std::string, std::chrono::duration<double, std::milli> > mResults;
|
||||||
|
std::string parseDate(const int ms) const;
|
||||||
|
|
||||||
|
static Timing* mInstance;
|
||||||
|
};
|
60
main.cpp
60
main.cpp
@ -5,6 +5,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Timing.h"
|
||||||
|
|
||||||
#define LIVE_CELL 'x'
|
#define LIVE_CELL 'x'
|
||||||
#define DEAD_CELL '.'
|
#define DEAD_CELL '.'
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ struct World {
|
|||||||
char **data;
|
char **data;
|
||||||
|
|
||||||
char get_value(int x, int y) {
|
char get_value(int x, int y) {
|
||||||
|
// TODO: Way too much work to do all the time. Move this to special cases
|
||||||
if (x < 0) x += size_x;
|
if (x < 0) x += size_x;
|
||||||
if (y < 0) y += size_y;
|
if (y < 0) y += size_y;
|
||||||
if (x >= size_x) x -= size_x;
|
if (x >= size_x) x -= size_x;
|
||||||
@ -51,30 +54,27 @@ struct World {
|
|||||||
int size_y;
|
int size_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
void generation(World &world) {
|
void generation(World &world, int *neighbor_counts) {
|
||||||
// Set neighbor counts
|
int size_x = world.size_x;
|
||||||
int **neighbor_counts = new int*[world.size_y];
|
|
||||||
for (int y = 0; y < world.size_y; y++) {
|
|
||||||
neighbor_counts[y] = new int[world.size_x];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Set neighbor counts
|
||||||
for (int y = 0; y < world.size_y; y++) {
|
for (int y = 0; y < world.size_y; y++) {
|
||||||
for (int x = 0; x < world.size_x; x++) {
|
for (int x = 0; x < world.size_x; x++) {
|
||||||
// Get number of living neighbors
|
// Get number of living neighbors
|
||||||
int neighbors = 0;
|
int neighbors = 0;
|
||||||
|
|
||||||
for (int local_y = -1; local_y < 2; local_y++) {
|
if (world.get_value(x - 1, y - 1) == LIVE_CELL) neighbors++;
|
||||||
for (int local_x = -1; local_x < 2; local_x++) {
|
if (world.get_value(x, y - 1) == LIVE_CELL) neighbors++;
|
||||||
// Ignore self
|
if (world.get_value(x + 1, y - 1) == LIVE_CELL) neighbors++;
|
||||||
if (local_x == 0 && local_y == 0) continue;
|
|
||||||
|
|
||||||
if (world.get_value(x + local_x, y + local_y) == LIVE_CELL) {
|
if (world.get_value(x - 1, y) == LIVE_CELL) neighbors++;
|
||||||
neighbors++;
|
if (world.get_value(x + 1, y) == LIVE_CELL) neighbors++;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
neighbor_counts[y][x] = neighbors;
|
if (world.get_value(x - 1, y + 1) == LIVE_CELL) neighbors++;
|
||||||
|
if (world.get_value(x, y + 1) == LIVE_CELL) neighbors++;
|
||||||
|
if (world.get_value(x + 1, y + 1) == LIVE_CELL) neighbors++;
|
||||||
|
|
||||||
|
neighbor_counts[y * size_x + x] = neighbors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ void generation(World &world) {
|
|||||||
for (int y = 0; y < world.size_y; y++) {
|
for (int y = 0; y < world.size_y; y++) {
|
||||||
for (int x = 0; x < world.size_x; x++) {
|
for (int x = 0; x < world.size_x; x++) {
|
||||||
char this_cell = world.get_value(x, y);
|
char this_cell = world.get_value(x, y);
|
||||||
int neighbors = neighbor_counts[y][x];
|
int neighbors = neighbor_counts[y * size_x + x];
|
||||||
|
|
||||||
if (this_cell == DEAD_CELL) {
|
if (this_cell == DEAD_CELL) {
|
||||||
if (neighbors == 3) {
|
if (neighbors == 3) {
|
||||||
@ -102,9 +102,16 @@ void generation(World &world) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
Timing *timing = Timing::getInstance();
|
||||||
|
|
||||||
|
// Setup.
|
||||||
|
timing->startSetup();
|
||||||
|
|
||||||
// Read in the start state
|
// Read in the start state
|
||||||
|
std::string file_begin = "random250";
|
||||||
|
|
||||||
std::ifstream world_file;
|
std::ifstream world_file;
|
||||||
world_file.open("random250_in.gol");
|
world_file.open(file_begin + "_in.gol");
|
||||||
|
|
||||||
// Get x and y size
|
// Get x and y size
|
||||||
std::string x_str, y_str;
|
std::string x_str, y_str;
|
||||||
@ -128,14 +135,22 @@ int main() {
|
|||||||
|
|
||||||
world_file.close();
|
world_file.close();
|
||||||
|
|
||||||
|
timing->stopSetup();
|
||||||
|
timing->startComputation();
|
||||||
|
|
||||||
|
int *neighbor_counts = new int[world.size_y * world.size_x];
|
||||||
|
|
||||||
// Do some generations
|
// Do some generations
|
||||||
for (int i = 0; i < 250; i++) {
|
for (int i = 0; i < 250; i++) {
|
||||||
generation(world);
|
generation(world, neighbor_counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timing->stopComputation();
|
||||||
|
timing->startFinalization();
|
||||||
|
|
||||||
// Write the result
|
// Write the result
|
||||||
std::ofstream result_file;
|
std::ofstream result_file;
|
||||||
result_file.open("random250_out.gol");
|
result_file.open(file_begin + "_out.gol");
|
||||||
|
|
||||||
result_file << size_x << "," << size_y << '\n';
|
result_file << size_x << "," << size_y << '\n';
|
||||||
|
|
||||||
@ -151,6 +166,11 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_file.close();
|
result_file.close();
|
||||||
|
delete neighbor_counts;
|
||||||
|
|
||||||
|
timing->stopFinalization();
|
||||||
|
|
||||||
|
timing->print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user