Skip to content

Commit

Permalink
Completing the test code for multithreading code without semaphores, …
Browse files Browse the repository at this point in the history
…mutexs or critical sections
  • Loading branch information
seancyw committed Feb 14, 2017
1 parent c6e3c04 commit 379fcca
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 14 deletions.
37 changes: 36 additions & 1 deletion Multithreading/PPM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void PPM::write(const std::string & fileName)
//Initialize the stream
std::ofstream output(fileName.c_str(), std::ios::out | std::ios::binary);

if (output.is_open) {
if (output.is_open()) {

output << "P6\n";
output << _width;
Expand Down Expand Up @@ -142,4 +142,39 @@ void PPM::initialize()
_width = 0;
_height = 0;
_maximumColumn = 255;
}

unsigned int PPM::getHeight() const
{
return _height;
}

unsigned int PPM::getWidth() const
{
return _width;
}

unsigned int PPM::getMaximumColumns() const
{
return _maximumColumn;
}

unsigned int PPM::getSize() const
{
return _size;
}

std::vector< unsigned char > PPM::getRValue() const
{
return _r;
}

std::vector< unsigned char > PPM::getGValue() const
{
return _g;
}

std::vector< unsigned char > PPM::getBValue() const
{
return _b;
}
9 changes: 9 additions & 0 deletions Multithreading/PPM.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ class PPM

//write PPM image to filename
void write(const std::string & fileName);

unsigned int getHeight() const;
unsigned int getWidth() const;
unsigned int getMaximumColumns() const;
unsigned int getSize() const;

std::vector< unsigned char > getRValue() const;
std::vector< unsigned char > getGValue() const;
std::vector< unsigned char > getBValue() const;

private:
bool isAllocated;
void initialize();
Expand Down
252 changes: 239 additions & 13 deletions Multithreading/main.cpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,254 @@
#include <iostream>
#include <thread>
#include <ctime>
#include <vector>
#include <string>
#include "PPM.h"

static const int totalThreads = 10;
//Program reference from https://github.com/sol-prog/threads/blob/master/image_processing/ppm_05.cpp

//function will be called from a thread
void callFromThread(int id)
//Split "mem" into "parts", e.g. if memory = 10 and parts = 4 you will have: 0,2,4,6,10
//if possible the function will split memory into equal chuncks, if not
//the last chunck will be slightly larger
std::vector<int> bounds(int parts, int memory)
{
std::cout << "Hello!" << id << std::endl;
std::vector<int> bnd;
int delta = memory / parts;
int remainder = memory % parts;

int n1 = 0;
int n2 = 0;

bnd.push_back(n1);

for (int i = 0; i < parts; ++i) {
n2 = n1 + delta;

if (i == parts - 1)
n2 += remainder;

bnd.push_back(n2);
n1 = n2;
}

return bnd;
}

//Test if a given position (x, y) is "inside" the limits 0..totalLine and 0..totalColumns
bool border(int x, int y, int totalLines, int totalColumns)
{
return (x >= 0 && x <= totalColumns && y >= 0 && y <= totalLines);
}

//Blur the pixel at (x, y) using information from the neighbour pixels
void process(PPM & image, PPM & image2, int x, int y)
{
int row, column, totalColumns, totalRows, id;
unsigned int r, g, b;
float r_sum, g_sum, b_sum;

//Filter used for bluring an image
float filter[] = {
0.10179640718562874, 0.11377245508982035, 0.10179640718562874,
0.11377245508982035, 0.1377245508982036, 0.11377245508982035,
0.10179640718562874, 0.11377245508982035, 0.10179640718562874
};

totalRows = image.getHeight();
totalColumns = image.getWidth();

//Apply filter
r_sum = 0;
g_sum = 0;
b_sum = 0;

//check North-West
row = y - 1;
column = x - 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[0];
g_sum += g * filter[0];
b_sum += b * filter[0];
}

//check North
row = y - 1;
column = x;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[1];
g_sum += g * filter[1];
b_sum += b * filter[1];
}

//check North-East
row = y - 1;
column = x + 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[2];
g_sum += g * filter[2];
b_sum += b * filter[2];
}

//check West
row = y;
column = x - 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[3];
g_sum += g * filter[3];
b_sum += b * filter[3];
}

//center
row = y;
column = x;
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[4];
g_sum += g * filter[4];
b_sum += b * filter[4];


//check East
row = y;
column = x + 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[5];
g_sum += g * filter[5];
b_sum += b * filter[5];
}
//check South-West
row = y + 1;
column = x - 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[6];
g_sum += g * filter[6];
b_sum += b * filter[6];
}
//check South
row = y + 1;
column = x;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[7];
g_sum += g * filter[7];
b_sum += b * filter[7];
}
//check South-East
row = y + 1;
column = x + 1;
if (border(row, column, totalRows, totalColumns)) {
id = row * image.getWidth() + column;

r = (unsigned int)image.getRValue()[id];
g = (unsigned int)image.getGValue()[id];
b = (unsigned int)image.getBValue()[id];

r_sum += r * filter[8];
g_sum += g * filter[8];
b_sum += b * filter[8];
}

//Save the modifed pixel value in image2
id = y * image.getWidth() + x;
image2.getRValue()[id] = (unsigned char)r_sum;
image2.getGValue()[id] = (unsigned char)g_sum;
image2.getBValue()[id] = (unsigned char)b_sum;

}

//Blur a chunck of an image
void tst(PPM & image, PPM & image2, int left, int right)
{
for (int i = left; i < right; ++i) {
int x = i / image.getWidth();
int y = i - x * image.getWidth();

process(image, image2, x, y);
}
}

int main()
{
//Initialize groups of threads
std::thread threads[totalThreads];
std::string fileName = std::string("someFile.ppm");

PPM image(fileName);
PPM image2(image.getWidth(), image.getHeight());

//Number of thread to use(image will be divided between threads)
int parts = 4;

std::vector<int> bnd = bounds(parts, image.getSize());

std::vector<std::thread> threads;

time_t start, end;
time(&start);

//Launch parts-1 threads
for (int i = 0; i < parts - 1; ++i) {
threads.push_back(std::thread(tst, std::ref(image), std::ref(image2), bnd[i], bnd[i + 1]));
}

//Use the main thread to do part of the work
for (int i = parts - 1; i < parts; ++i) {
tst(image, image2, bnd[i], bnd[i + 1]);
}

//Join parts-1 threads
for (auto & e : threads)
e.join();

//Launch groups of threads
for (int i = 0; i < totalThreads; ++i)
threads[i] = std::thread(callFromThread, i);
time(&end);

std::cout << "Lauched from the main\n";
std::cout << difftime(end, start) << " seconds" << std::endl;

//Join the thread with the main thread
for (int i = 0; i < totalThreads; ++i)
threads[i].join();
//Save the result
image2.write("test2.ppm");

std::cin.ignore();

Expand Down

0 comments on commit 379fcca

Please sign in to comment.