Reputation: 692
I am writing a program for an assignment,which implements matrix multiplication between two given arrays,using threads.
I must give the number of threads i want to use as a command line argument and if the number of them is smaller than the number of lines of the first array,reuse some the same threads until the whole job is done.
I have managed to make it work but only using a thread for each row of the array. For example if a have a 5x5 multiplication and use less than 5 threads i take a segmentation fault,which makes sense.
My question is:How can i reuse a thread after this thread has finished its job? In the previous example i mean that if i want to use 2 threads for a 5x5 my program should work like this:
thread 1->line 1
thread 2->line 2
thread 2->line 3
thread 1->line 4
etc.
Upvotes: 4
Views: 4972
Reputation: 14730
You have several possibilities, but the main idea is that you must monitor threads to detect when they have finished their job, and have a way to know if there's still something left to do.
The first way that comes to mind is to have a dedicated thread to track all the running threads, and recycle them once they're finished. But in order to do that, you need a mechanism to let threads synchronize, which may be implemented using semaphores or mutex, or messages, but it could be cumbersome to code just for that purpose if you don't have a need for it already.
The second way is simply to ask them to recycle themselves, since they know when they are done. In many other languages, there's a mechanism called continuations, which let you exactly that, but since we're dealing with C, we need to do that by hand. Luckily, here the continuation is actually just one single task.
So the mechanism to call the continuation is actually just a function, which will first run the task to be executed by the thread, and then either:
Obviously, the first option would be easier, and in your case, you already know at setup time what has to be done, so your setup function could fill up a list of tasks and then launch as many threads as you want, and let them do the recycling themselves.
Here's a simple skeleton you could start with:
typedef struct {
/* task related data */
} task_t;
// basic list structure
typedef struct {
list_t *next;
void *data; // here app specific data
} list_t;
list_t task_list; // your task list
// a few operators to manipulate a list
// implementation must use a mutex to avoid race conditions
void list_push(list *l, void *data);
void *list_pop(list *l);
// thread function
void do_task(task_t *task){
while (task) {
run_task(task); // that would be the matrix related function
task = list_pop(&task_list);
}
// here a simple define for the number of threads
// you might want to check the number of available cores instead
#define MAX_THREAD_COUNT 4
int main() {
pthread_t threads[MAX_THREAD_COUNT];
setup_task_list(); // push all the work that must be done in the list
int i;
for (i = 0; i < MAX_THREAD_COUNT; i++) {
pthread_create(threads + i, NULL, do_task, list_pop(&task_list));
}
// here wait for all the threads, or detach them
}
This is a basic outline of what you could do, and should get you started.
There are several questions on SO dealing with C linked lists. The one here must be synchronized, should not block, and return NULL
when empty.
Upvotes: 3