gvsu/cs677/pa2/threaded.cc
josh e1666dd72b restored erroneously removed initializations of s & t
git-svn-id: svn://anubis/gvsu@171 45c1a28c-8058-47b2-ae61-ca45b979098e
2008-09-26 17:41:17 +00:00

192 lines
5.1 KiB
C++

/*
* Josh Holtrop
* 2008-10-01
* Grand Valley State University
* CS677
* Programming Assignment #2
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <pthread.h>
using namespace std;
#define eq(x, y) ( ( (x) == (y) ) || ( (x) == '?' ) || ( (y) == '?' ) )
void usage(char * prog);
void * calcSimMatrixThread(void * arg);
bool readFile(char * fileName, vector<char> & v);
pthread_barrier_t barrier;
int num_threads;
int * matrix;
vector<char> * s;
vector<char> * t;
/* Print basic usage information */
void usage(char * prog)
{
cout << "Usage: " << prog << " [-n <num_threads>] <file1> <file2>" << endl;
exit(42);
}
/*
* taskAllocate() will divide a set of total_tasks tasks into
* total_workers groups, as evenly as possible
* Parameters:
* total_tasks : IN : the total number of tasks to divide up
* total_workers : IN : the total number of workers to allocate tasks to (>0)
* this_id : IN : the id (base 0) of the task calling us for work
* first_task_id : OUT : the id (base 0) of the first task for this worker
* num : OUT : the number of tasks assigned to this worker
*/
inline void taskAllocate(int total_tasks, int total_workers, int this_id,
int * first_task_id, int * num)
{
int l_num;
int leftovers = total_tasks % total_workers; /* num of "leftover" tasks */
if (this_id < leftovers)
{
l_num = total_tasks / total_workers + 1; /* do one of the leftovers */
*first_task_id = l_num * this_id;
}
else
{
l_num = total_tasks / total_workers;
*first_task_id = l_num * this_id + leftovers;
}
*num = l_num;
}
int main(int argc, char * argv[])
{
vector<char> files[2];
num_threads = 1;
int file_to_read = 0;
for (int i = 1; i < argc; i++)
{
if ( ! strcmp("-n", argv[i]) )
{
if (i == argc - 1)
usage(argv[0]);
i++;
num_threads = atoi(argv[i]);
}
else
{
if (file_to_read < 2)
readFile(argv[i], files[file_to_read]);
else
usage(argv[0]);
file_to_read++;
}
}
if (file_to_read != 2)
usage(argv[0]);
s = &files[0];
t = &files[1];
pthread_t * threads = new pthread_t[num_threads];
matrix = new int[files[0].size() * files[1].size()];
pthread_barrier_init(&barrier, NULL, num_threads);
for (int i = 0; i < num_threads; i++)
{
int ret = pthread_create(&threads[i], NULL, &calcSimMatrixThread, (void *) i);
if (ret)
{
cerr << "Error " << ret << " when creating thread!" << endl;
return -4;
}
}
for (int i = 0; i < num_threads; i++)
{
pthread_join(threads[i], NULL);
}
pthread_barrier_destroy(&barrier);
delete[] matrix;
delete[] threads;
return 0;
}
/* Read a file into a vector of non-space characters */
bool readFile(char * fileName, vector<char> & v)
{
ifstream in(fileName);
if (!in.is_open())
return false;
while (!in.eof())
{
char chr;
in >> chr;
v.push_back(chr);
}
return true;
}
/* Compute portions of the similarity matrix between two character arrays */
void * calcSimMatrixThread(void * arg)
{
int id = (int) arg;
int s_size = s->size();
int t_size = t->size();
int (*F)[s_size][t_size] = (int (*) [s_size][t_size]) matrix;
int max_x = 0, max_y = 0, max_val = 0;
int first_task_id, num_tasks;
taskAllocate(t_size, num_threads, id, &first_task_id, &num_tasks);
for (int i = 0, idx = first_task_id; i < num_tasks; i++, idx++)
(*F)[0][idx] = 0; /* set first row to 0's */
taskAllocate(s_size, num_threads, id, &first_task_id, &num_tasks);
for (int i = 0, idx = first_task_id; i < num_tasks; i++, idx++)
(*F)[idx][0] = 0; /* set first column to 0's */
pthread_barrier_wait(&barrier);
for (int i = 1; i < s_size; i++)
{
for (int j = 1; j < t_size; j++)
{
/* Compute the value for the matrix */
(*F)[i][j] =
max(
max(
(*F)[i][j-1] - 2,
(*F)[i-1][j-1] +
(eq(s->at(i), t->at(j)) ? 1 : -1)
),
max(
(*F)[i-1][j] - 2,
0
)
);
/* See if we found a new maximum value */
if ((*F)[i][j] > max_val)
{
max_val = (*F)[i][j];
max_x = i;
max_y = j;
}
else if ((*F)[i][j] == max_val)
{
/* If we found a value the same as our current maximum
* value, see if it has a greater i+j value */
if ( (i + j) > (max_x + max_y) )
{
max_x = i;
max_y = j;
}
}
}
}
cout << "Maximum value is " << max_val << " at position ("
<< max_x << ", " << max_y << ")" << endl;
return NULL;
}