/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ #include #include #include #include #include #include #include #include #include #include #include #include #include // important ff.hpp before other ff includes #include #include "reader.hpp" #include "stencil.hpp" #include "timer.hpp" #include "writer.hpp" using namespace std; using namespace ff; char *getOption(char **begin, char **end, const std::string &option) { char **itr = std::find(begin, end, option); if (itr != end && ++itr != end) return *itr; return nullptr; } long long int fastflow(vector images, vector> neighborhood, int iterations, std::function)> f, int maxworkers) { Reader reader(images); Stencil stencil(f, neighborhood, iterations, maxworkers); Writer writer; ff::ff_Pipe<> pipe(reader, stencil, writer); UTimer timer; timer.start(); if (pipe.run_and_wait_end() < 0) { error("running pipeline\n"); return 1; } timer.stop(); long long int ret = timer.print("\tElapsed time: "); return ret; } long long int stdthreads(vector images, vector> neighborhood, int iterations, std::function)> f, int maxworkers) { long num_images = images.size(); Reader reader(images); Stencil *stencil = // pointer so that we can delete only once and not // when out of scope of the thread new Stencil(f, neighborhood, iterations, maxworkers); Writer writer; std::vector *> *> *tv = new std::vector *> *>(); std::vector *>> *in = new std::vector *>>(); std::vector *> *> *out = new std::vector *> *>(); std::vector *>> *tvw = new std::vector *>>(); for (int i = 0; i < num_images; ++i) { std::promise *> *p = new std::promise *>(); std::future *> f = p->get_future(); std::promise *> *o = new std::promise *>(); std::future *> l = o->get_future(); tv->push_back(p); in->push_back(f.share()); out->push_back(o); tvw->push_back(l.share()); } UTimer timer; timer.start(); std::thread readerT(reader, images, tv); std::thread stencilT(&Stencil::stdthread, stencil, in, out); std::thread writerT(writer, tvw); readerT.join(); stencilT.join(); writerT.join(); timer.stop(); long long int ret = timer.print("\tElapsed time: "); for (int i = 0; i < num_images; ++i) { delete ((*tv)[i]); delete ((*out)[i]); } delete tv; delete in; delete out; delete tvw; delete stencil; return ret; } long long int sequential(vector images, vector> neighborhood, int iterations, std::function)> f) { long num_images = images.size(); Reader reader(images); Stencil *stencil = // pointer so that we can delete only once and not // when out of scope of the thread new Stencil(f, neighborhood, iterations); Writer writer; std::vector *> *> *tv = new std::vector *> *>(); std::vector *>> *in = new std::vector *>>(); std::vector *> *> *out = new std::vector *> *>(); std::vector *>> *tvw = new std::vector *>>(); for (int i = 0; i < num_images; ++i) { std::promise *> *p = new std::promise *>(); std::future *> f = p->get_future(); std::promise *> *o = new std::promise *>(); std::future *> l = o->get_future(); tv->push_back(p); in->push_back(f.share()); out->push_back(o); tvw->push_back(l.share()); } UTimer timer; timer.start(); std::thread readerT(reader, images, tv); std::thread stencilT(&Stencil::sequential, stencil, in, out); std::thread writerT(writer, tvw); readerT.join(); stencilT.join(); writerT.join(); timer.stop(); long long int ret = timer.print("\tElapsed time: "); for (int i = 0; i < num_images; ++i) { delete ((*tv)[i]); delete ((*out)[i]); } delete tv; delete in; delete out; delete tvw; delete stencil; return ret; } char gameOfLife(vector in) { auto v = std::accumulate(in.begin() + 1, in.end(), 0); if (in[0] && v < 2) { return 0; } else if (in[0] && v > 3) { return 0; } else if (!in[0] && v != 3) { return 0; } return 1; } // ----------------------------------------------------------------------------- int main(int argc, char *argv[]) { int average_max = 5; int iter_for_num_workers = 128; vector images = { "../tests/empty2x2", "../tests/increasing4x6", "../tests/increasing300x200", "../tests/random400x2500", // "../tests/equation", // "../tests/equation2" }; vector> neig = {make_pair(-1, 1), make_pair(-1, 0), make_pair(-1, -1), make_pair(0, 1), make_pair(0, -1), make_pair(1, 1), make_pair(1, 0), make_pair(1, -1)}; ofstream csvfile; csvfile.open("performance.csv"); for (std::string image : images) { cout << endl << "\033[1;31mProcessing: \t" << image << "\033[0m" << endl; csvfile << ",Name,Size(B)\n"; csvfile << "Image," << image << ","; csvfile << std::filesystem::file_size(image) << "\n"; csvfile << "\n"; csvfile << "Number of iterations,1,2,4,8,16\n"; csvfile << "fastflow:,"; cout << "\033[1;31mFastflow\033[0m" << endl; for (int iterations : {1, 2, 4, 8, 16}) { vector results; for (int i = 0; i < average_max; ++i) { results.push_back( fastflow({image}, neig, iterations, &gameOfLife, 0)); } csvfile << std::accumulate(results.begin(), results.end(), 0) / average_max << ","; } csvfile << "\n"; csvfile << "stdthread:,"; cout << "\033[1;31mStdthread\033[0m" << endl; for (int iterations : {1, 2, 4, 8, 16}) { vector results; for (int i = 0; i < average_max; ++i) { results.push_back( stdthreads({image}, neig, iterations, &gameOfLife, 0)); } csvfile << std::accumulate(results.begin(), results.end(), 0) / average_max << ","; } csvfile << "\n"; // ------------------------------------------------------------------ // csvfile << "Number of Workers,sequential,fastflow,stdthreads,"; csvfile << "Iterations:," << iter_for_num_workers << "\n"; cout << "\033[1;31mDifferent number of workers\033[0m" << endl; int hardware_concurrency = std::thread::hardware_concurrency(); vector list_max_workers = vector(); for (int i = 1; i < hardware_concurrency; i*=2) { list_max_workers.push_back(i); } list_max_workers.push_back(hardware_concurrency); for (int max_workers : list_max_workers) { csvfile << max_workers << ","; if(max_workers == 1) { cout << "\033[1;31mSequential\033[0m" << endl; vector results; for (int i = 0; i < average_max; ++i) { results.push_back(sequential( {image}, neig, iter_for_num_workers, &gameOfLife)); } csvfile << std::accumulate(results.begin(), results.end(), 0) / average_max; } csvfile << ","; cout << "\033[1;31mFastflow with " << max_workers << " workers\033[0m" << endl; { vector results; for (int i = 0; i < average_max; ++i) { results.push_back(fastflow({image}, neig, iter_for_num_workers, &gameOfLife, max_workers)); } csvfile << std::accumulate(results.begin(), results.end(), 0) / average_max; } csvfile << ","; cout << "\033[1;31mStdthread with " << max_workers << " workers\033[0m" << endl; { vector results; for (int i = 0; i < average_max; ++i) { results.push_back(stdthreads({image}, neig, iter_for_num_workers, &gameOfLife, max_workers)); } csvfile << std::accumulate(results.begin(), results.end(), 0) / average_max; } csvfile << "\n"; } } csvfile.close(); return 0; }