diff --git a/.gitignore b/.gitignore index 889ee8c..07c90ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Project specific +tests/out_* +build/ + # General .DS_Store .AppleDouble diff --git a/main.cpp b/main.cpp index e4d8860..e9acbfc 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include #include #include #include @@ -24,13 +25,6 @@ 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, @@ -176,15 +170,19 @@ char gameOfLife(vector in) { // ----------------------------------------------------------------------------- int main(int argc, char *argv[]) { int average_max = 5; - int iter_for_num_workers = 128; - vector images = { + int iter_for_num_workers_images1 = 128; + vector images1 = { "../tests/empty2x2", "../tests/increasing4x6", "../tests/increasing300x200", - "../tests/random400x2500", - // "../tests/equation", - // "../tests/equation2" + "../tests/random400x2500" + }; + + int iter_for_num_workers_images2 = 8; + vector images2 = { + "../tests/equation", + "../tests/equation2" }; vector> neig = {make_pair(-1, 1), make_pair(-1, 0), @@ -195,7 +193,7 @@ int main(int argc, char *argv[]) { ofstream csvfile; csvfile.open("performance.csv"); - for (std::string image : images) { + for (std::string image : images1) { cout << endl << "\033[1;31mProcessing: \t" << image << "\033[0m" << endl; @@ -204,39 +202,37 @@ int main(int argc, char *argv[]) { csvfile << std::filesystem::file_size(image) << "\n"; csvfile << "\n"; - csvfile << "Number of iterations,1,2,4,8,16\n"; + csvfile << "Number of iterations,1,2,4,8,16,32\n"; csvfile << "fastflow:,"; cout << "\033[1;31mFastflow\033[0m" << endl; - for (int iterations : {1, 2, 4, 8, 16}) { + for (int iterations : {1, 2, 4, 8, 16, 32}) { 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 << *std::min_element(results.begin(), results.end()) << ","; } csvfile << "\n"; csvfile << "stdthread:,"; cout << "\033[1;31mStdthread\033[0m" << endl; - for (int iterations : {1, 2, 4, 8, 16}) { + for (int iterations : {1, 2, 4, 8, 16, 32}) { 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 << *std::min_element(results.begin(), results.end()) << ","; } csvfile << "\n"; // ------------------------------------------------------------------ // csvfile << "Number of Workers,sequential,fastflow,stdthreads,"; - csvfile << "Iterations:," << iter_for_num_workers << "\n"; + csvfile << "Iterations:," << iter_for_num_workers_images1 << "\n"; cout << "\033[1;31mDifferent number of workers\033[0m" << endl; int hardware_concurrency = std::thread::hardware_concurrency(); @@ -255,10 +251,9 @@ int main(int argc, char *argv[]) { vector results; for (int i = 0; i < average_max; ++i) { results.push_back(sequential( - {image}, neig, iter_for_num_workers, &gameOfLife)); + {image}, neig, iter_for_num_workers_images1, &gameOfLife)); } - csvfile << std::accumulate(results.begin(), results.end(), 0) / - average_max; + csvfile << *std::min_element(results.begin(), results.end()); } csvfile << ","; @@ -268,11 +263,10 @@ int main(int argc, char *argv[]) { vector results; for (int i = 0; i < average_max; ++i) { results.push_back(fastflow({image}, neig, - iter_for_num_workers, + iter_for_num_workers_images1, &gameOfLife, max_workers)); } - csvfile << std::accumulate(results.begin(), results.end(), 0) / - average_max; + csvfile << *std::min_element(results.begin(), results.end()); } csvfile << ","; @@ -282,11 +276,102 @@ int main(int argc, char *argv[]) { vector results; for (int i = 0; i < average_max; ++i) { results.push_back(stdthreads({image}, neig, - iter_for_num_workers, + iter_for_num_workers_images1, &gameOfLife, max_workers)); } - csvfile << std::accumulate(results.begin(), results.end(), 0) / - average_max; + csvfile << *std::min_element(results.begin(), results.end()); + } + csvfile << "\n"; + } + } + + for (std::string image : images2) { + 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\n"; + csvfile << "fastflow:,"; + + cout << "\033[1;31mFastflow\033[0m" << endl; + for (int iterations : {1, 2, 4, 8}) { + vector results; + for (int i = 0; i < average_max; ++i) { + results.push_back( + fastflow({image}, neig, iterations, &gameOfLife, 0)); + } + csvfile << *std::min_element(results.begin(), results.end()) + << ","; + } + csvfile << "\n"; + + csvfile << "stdthread:,"; + cout << "\033[1;31mStdthread\033[0m" << endl; + for (int iterations : {1, 2, 4, 8}) { + vector results; + for (int i = 0; i < average_max; ++i) { + results.push_back( + stdthreads({image}, neig, iterations, &gameOfLife, 0)); + } + csvfile << *std::min_element(results.begin(), results.end()) + << ","; + } + csvfile << "\n"; + + // ------------------------------------------------------------------ // + csvfile << "Number of Workers,sequential,fastflow,stdthreads,"; + csvfile << "Iterations:," << iter_for_num_workers_images2 << "\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_images2, &gameOfLife)); + } + csvfile << *std::min_element(results.begin(), results.end()); + } + 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_images2, + &gameOfLife, max_workers)); + } + csvfile << *std::min_element(results.begin(), results.end()); + } + 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_images2, + &gameOfLife, max_workers)); + } + csvfile << *std::min_element(results.begin(), results.end()); } csvfile << "\n"; } diff --git a/stencil.hpp b/stencil.hpp index 0a8f8ce..56033da 100644 --- a/stencil.hpp +++ b/stencil.hpp @@ -138,7 +138,7 @@ void Stencil::stdthread( for (auto result : *ResultsVector) { Task *task = result.get(); int niter = Iterations; - int delta = (task->Rows * task->Cols) / MaxThreads; + int delta = task->Rows / MaxThreads; std::vector> *arena = new std::vector>(0); *arena = *(task->VectorData); // copy all from VectorData @@ -146,9 +146,30 @@ void Stencil::stdthread( while (niter > 0) { for (int l = 0; l < MaxThreads - 1; ++l) { thread_pool.addJob([&, l, delta] { - for (int k = l * delta; k < (l + 1) * delta; ++k) { - int x = k / task->Cols; - int y = k % task->Cols; + for (int x = l * delta; x < (l+1) * delta; ++x) { + for (int y = 0; y < task->Cols; ++y) { + if (x < Borders[1] || x >= task->Rows - Borders[3] || + y < Borders[0] || y >= task->Cols - Borders[2]) { + continue; + } + std::vector n; + n.resize(Neighborhood.size()); + std::transform( + Neighborhood.begin(), Neighborhood.end(), + n.begin(), + [&task, x, y](std::pair e) { + return (*task->VectorData)[x + e.second] + [y + e.first]; + }); + (*arena)[x][y] = Convolution(n); + } + } + }); + } + thread_pool.addJob([&, delta, MaxThreads] { + for (int x = (MaxThreads - 1) * delta; + x < task->Rows; ++x) { + for (int y = 0; y < task->Cols; ++y) { if (x < Borders[1] || x >= task->Rows - Borders[3] || y < Borders[0] || y >= task->Cols - Borders[2]) { continue; @@ -158,31 +179,11 @@ void Stencil::stdthread( std::transform( Neighborhood.begin(), Neighborhood.end(), n.begin(), [&task, x, y](std::pair e) { - return (*task->VectorData)[x + e.second] - [y + e.first]; + return ( + *task->VectorData)[x + e.second][y + e.first]; }); (*arena)[x][y] = Convolution(n); } - }); - } - thread_pool.addJob([&, delta, MaxThreads] { - for (int k = (MaxThreads - 1) * delta; - k < task->Cols * task->Rows; ++k) { - int x = k / task->Cols; - int y = k % task->Cols; - if (x < Borders[1] || x >= task->Rows - Borders[3] || - y < Borders[0] || y >= task->Cols - Borders[2]) { - continue; - } - std::vector n; - n.resize(Neighborhood.size()); - std::transform( - Neighborhood.begin(), Neighborhood.end(), n.begin(), - [&task, x, y](std::pair e) { - return ( - *task->VectorData)[x + e.second][y + e.first]; - }); - (*arena)[x][y] = Convolution(n); } }); thread_pool.waitEnd(); @@ -250,13 +251,12 @@ template Task *Stencil::svc_helper(Task *task) { while (niter > 0) { parallel_for( - 0, task->Rows * task->Cols, - [&](const int k) { - int x = k / task->Cols; - int y = k % task->Cols; + 0, task->Rows, + [&](const int x) { + for (int y = 0; y < task->Cols; ++y) { if (x < Borders[1] || x >= task->Rows - Borders[3] || y < Borders[0] || y >= task->Cols - Borders[2]) { - return; + continue; } std::vector n; n.resize(Neighborhood.size()); @@ -266,6 +266,7 @@ template Task *Stencil::svc_helper(Task *task) { return (*task->VectorData)[x + e.second][y + e.first]; }); (*arena)[x][y] = Convolution(n); + } }, MaxWorkers); std::swap(task->VectorData, arena);