COSC101 Lecture 09
Title: COSC330/530 - Lecture 9 COSC330/530 - Parallel and Distributed Computing Lecture 9 - Multithreaded Applications Dr. Mitchell Welch Reading Chapters 11 and 12 from Advanced Programming in the UNIX environment Assignment 2 Description Summary Multithreaded Chat (Quick Review) Multithreaded Matrix Multiplication Multithreaded Chat The program consists of two mains: server client Try them in separate windows choosing a port number >8000 . For example: Window 1:
[comp309@immortal Chat]$ ./server 8000
Server listening on port 8000
Connection has been made to immortal
Window 2:
[comp309@immortal Chat]$ ./client immortal 8000
Connection has been made to immortal
Can you figure out why I call them Chat? Multithreaded Chat The code is available in a standalone repo: There are two aspects to this program: Some networking with sockets. Reading and writing in separate threads. (Look in server.c and client.c) They form a typical server/client relationship: The server listens on a port for a connection from the client. The client makes a request to the server on this port. Multithreaded Chat When this happens the two processes obtain a two way connection channel, fd , a file descriptor of course, and spawn two threads: A reader thread to read from stdin and echo out to the fd. A writer thread to read from fd and echo out to the stdout. Note how I make arrays of function pointers. void * (*pmain[2])(void *) = {reader, writer};
Multithreaded Chat Note how the threads are created: for(i = 0; i < 2; i++)
if(pthread_create(&thread[i],NULL,pmain[i],&outfd) != 0){
fprintf(stderr, "Thread creation failed in client\n");
exit(1);
}
Note how nicely the two logical tasks of reading and writing are logically separate. To see the innards of these threads, look at chat.c Multithreaded Chat In this unit we will do several examples involving matrix multiplication! We do this for several reasons: They are useful out there in the real Mathematical world. They are very good examples of parallelizable algorithms. They can be parallelized in many interesting ways. First lets do a bit of revision. Multithreaded Matrix Multiplication A matrix is a rectangular collection of things: Remember its always rows by columns! The things will usually be numbers, but not always. Sometimes in this unit they will be other matrices. We'll see why later. Multithreaded Matrix Multiplication They are usually drawn thusly: source: http://upload.wikimedia.org/wikipedia/commons/b/bb/Matrix.svg Multithreaded Matrix Multiplication Ok so let: A be an m x p matrix, and B be an p x n matrix: Multithreaded Matrix Multiplication Then we can define the product C = A x B. C = A x B is the following m x n matrix: where Multithreaded Matrix Multiplication Multithreaded Matrix Multiplication source http://en.wikipedia.org/wiki/Matrix_%28mathematics%29 Multithreaded Matrix Multiplication Obviously an m x n matrix of things thing in C will be a two dimensional array of things. To do this nicely we'll make a typedef: typedef int matrix_t[m][n];
Of course this creates the usual problems, the rows start from one, while C arrays start from zero. But by the end of this unit, you'll all be polished C hackers! Multithreaded Matrix Multiplication Lets do a simple version of matrix multiplication. Since you are all becoming experts in this highly paid field. We begin with the work horse routine. It multiplies a row by a column and places the element in the resulting matrix. void mult(int size, int row, int column,
matrix_t MA, matrix_t MB, matrix_t MC){
int position;
MC[row][column] = 0;
for(position = 0; position < size; position++) {
MC[row][column] += (MA[row][position] * MB[position][column]) ;
}
}
Multithreaded Matrix Multiplication We'll start by doing a simple fixed calculation. Later we will want to use files like we have to with the ring example in the first project. We do the following steps: initialize the matrices; display them; multiply the suckers; display the answer; exit. Multithreaded Matrix Multiplication We'll attempt to illustrate good programming skills by developing a small library. #define ARRAY_SIZE 5
typedef int matrix_t[ARRAY_SIZE][ARRAY_SIZE];
void mult(int,int,int,matrix_t,matrix_t,matrix_t);
int one(int row, int column);
int identity(int row, int column);
int sum(int row, int column);
void matrix_init(int sz, matrix_t M, int (*init_fun)(int,int));
void matrix_printf(char* name, int sz, matrix_t M);
Multithreaded Matrix Multiplication We will also use this example to introduce you to function pointers We use these to make a generic matrix initialization procedure One that accepts as one of its arguments (a pointer) to a function f It then uses this function to initialize the matrix: Multithreaded Matrix Multiplication Review matrix_lib.c Multithreaded Matrix Multiplication A serial approach: #include
#include "matrix_lib.h"
static matrix_t MA,MB,MC;
int main(int argc, char **argv){
int row, column, size = ARRAY_SIZE;
/* initialize MA */
matrix_init(size, MA, identity);
/* initialize MB */
matrix_init(size, MB, sum);
/* display MA */
matrix_printf("A", size, MA);
/* display MB */
matrix_printf("B", size, MB);
/* multiply the suckers */
for(row = 0; row < size; row++) {
for (column = 0; column < size; column++) {
mult(size, row, column, MA, MB, MC); } }
/* display the result */
matrix_printf("C", size, MC);
exit(EXIT_SUCCESS);
}
Multithreaded Matrix Multiplication Compile and run matrix_serial.c and have a play: [mwelch8@turing Matrices]$ ./matrix_serial
Matrix: The A array is;
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Matrix: The B array is;
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Matrix: The C array is;
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Multithreaded Matrix Multiplication We'll start by considering multiplying a row by a column as an individual task. We'll discuss how sensible this is later in the unit. This example is mainly to demonstrate the use of threads. We shall create a thread for each row and each column. Now lets follow the step by step guide to thread creation. Multithreaded Matrix Multiplication A Step by Step guide to thread creation: Include the appropriate library: #include
Write the entry point to the thread: void * thread_entry(void *arg);
Create space for the thread's id: pthread_t my_thread;
Multithreaded Matrix Multiplication Create the data required by the thread: void *thread_arg = (void *);
Create the thread: pthread_create(&my_thread, NULL, thread_entry, thread_arg);
```
* Compile with gcc Use the flag `-pthread`
*when both linking and compiling.*
---
## Multithreaded Matrix Multiplication
* Include the appropriate library:
```cpp
#include
I think this may be the last time I remind you about this aspect ;) . Multithreaded Matrix Multiplication Write the main or entry point to the thread: void * thread_entry(void *arg);
In this case, since we need to pass in a lot of stuff, We must create a package to store it all in. typedef struct {
int id;
int size;
int Arow;
int Bcol;
matrix_t *MA, *MB, *MC;
} package_t;
Multithreaded Matrix Multiplication The entry point will then merely: Restore type information to its argument. Unpack the data, and then call the mult routine. void *mult_worker(void *arg){
package_t p = *((package_t *)arg);
mult(p.size, p.Arow, p.Bcol, *(p.MA), *(p.MB), *(p.MC));
return(NULL); }
Multithreaded Matrix Multiplication Create space for the thread's id: pthread_t my_thread;
In this case we are going to create quite a few threads! So a call to calloc is in order: pthread_t *threads =
(pthread_t *)calloc(size*size, sizeof(pthread_t));
Multithreaded Matrix Multiplication In this case we will first allocate the space, and Later initialize it (after we have initialized the matrices). package_t *thread_data =
(package_t *)calloc(size*size, sizeof(package_t));
Multithreaded Matrix Multiplication num_threads = 0;
for(row = 0; row < size; row++) {
for (column = 0; column < size; column++) {
thread_data[num_threads].id = num_threads;
thread_data[num_threads].size = size;
thread_data[num_threads].Arow = row;
thread_data[num_threads].Bcol = column;
(thread_data[num_threads]).MA = &MA;
(thread_data[num_threads]).MB = &MB;
(thread_data[num_threads]).MC = &MC;
num_threads++; }}
Multithreaded Matrix Multiplication Create the thread: pthread_create(&my_thread, NULL, thread_entry, thread_arg);
In this case we need to make a whole slew of the suckers. num_threads = 0;
for(row = 0; row < size; row++) {
for (column = 0; column < size; column++) {
pthread_create(&threads[num_threads],
NULL,
mult_worker,
(void *)&thread_data[num_threads]);
num_threads++; }}
Multithreaded Matrix Multiplication review matrix_threads.c There are a lot of extra print statements. These can be turned on at the flip of a switch: VERBOSE Multithreaded Matrix Multiplication Review matrix_threads_II.c Summary Multithreaded Chat (Quick Review) * Multithreaded Matrix Multiplication Questions? Reading Chapters 11 and 12 from Advanced Programming in the UNIX environment Assignment 2 Description