Skip to content

Instantly share code, notes, and snippets.

@KyroChi
Created October 6, 2022 18:02
Show Gist options
  • Save KyroChi/6820ba6be6b652ff166bc0a08b12cb6f to your computer and use it in GitHub Desktop.
Save KyroChi/6820ba6be6b652ff166bc0a08b12cb6f to your computer and use it in GitHub Desktop.
Medium multithreading post: Multithreaded full version
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
typedef struct {
unsigned int n_rows;
unsigned int n_cols;
double* data;
} matrix;
matrix*
new_matrix (unsigned int n_rows, unsigned int n_cols)
{
matrix* mat = malloc( sizeof(mat) );
if ( !mat ) {
printf("Failed to malloc\n");
exit(1);
}
mat->n_rows = n_rows;
mat->n_cols = n_cols;
mat->data = calloc( n_rows * n_cols, sizeof(double) );
return mat;
}
void
free_matrix (matrix* A)
{
free(A->data);
free(A);
return;
}
unsigned int
get_index (matrix* A, unsigned int r, unsigned int c)
{
return A->n_cols * r + c;
}
void
set_matrix (matrix* A, unsigned int r, unsigned int c, unsigned int v)
{
unsigned int ind = get_index(A, r, c);
A->data[ind] = v;
return;
}
double
get_matrix (matrix* A, unsigned int r, unsigned int c)
{
unsigned int ind = get_index(A, r, c);
return A->data[ind];
}
double
matmul_subroutine (matrix* A, unsigned int row,
matrix* B, unsigned int col)
{
double sum = 0;
unsigned int ii;
for ( ii = 0; ii < A->n_cols; ii++ ) {
sum += get_matrix(A, row, ii)
* get_matrix(B, ii, col);
}
return sum;
}
matrix*
matmul (matrix* A, matrix* B)
{
matrix* AB = new_matrix(A->n_rows, B->n_cols);
double ab;
unsigned int ii, jj;
for ( ii = 0; ii < A->n_rows; ii++ ) {
for ( jj = 0; jj < B->n_cols; jj++ ) {
ab = matmul_subroutine(A, ii, B, jj);
set_matrix(AB, ii, jj, ab);
}
}
return AB;
}
void
print_matrixf (Matrix2D* A, unsigned int precision)
{
double num = 0;
printf("[");
unsigned int ii, jj;
for (ii = 0; ii < A->n_rows; ii += 1) {
if (ii == 0) {
printf("[ ");
} else {
printf(" [ ");
}
for (jj = 0; jj < A->n_cols - 1; jj += 1) {
num = index_matrix_2D(A, ii, jj);
printf("%.*f \t", precision, num);
}
num = index_matrix_2D(A, ii, jj);
printf("%.*f", precision, num);
if (ii < A->n_rows - 1) {
printf(" ],\n");
}
}
printf(" ]]\n");
return;
}
typedef struct {
matrix* A;
unsigned int row;
matrix* B;
unsigned int col;
matrix* AB;
} thread_params;
void*
matmul_subroutine_thread (void* params)
{
thread_params* t_params = (thread_params*) params;
double a = matmul_subroutine(t_params->A,
t_params->row,
t_params->B,
t_params->col);
set_matrix(t_params->AB, t_params->row, t_params->col, a);
return NULL;
}
matrix*
matmul_threaded (matrix* A, matrix*B)
{
matrix* AB = new_matrix(A->n_rows, B->n_cols);
double ab;
pthread_t* tids = malloc( sizeof(pthread_t)
* A->n_rows * B->n_cols);
thread_params** params = malloc( sizeof(thread_params*)
* A->n_rows * B->n_cols);
thread_params* args;
unsigned int ii, jj, ind;
for ( ii = 0; ii < A->n_rows; ii++ ) {
for ( jj = 0; jj < B->n_cols; jj++ ) {
ind = ii * B->n_cols + jj;
args = params[ind];
args = malloc( sizeof(thread_params) );
args->A = A;
args->row = ii;
args->B = B;
args->col = jj;
args->AB = AB;
pthread_create(&tids[ind], NULL,
&matmul_subroutine_thread,
args);
}
}
for ( ii = 0; ii < A->n_rows * B->n_cols; ii++ ) {
pthread_join(tids[ii], NULL);
}
return AB;
}
int
main (void)
{
struct timespec start, finish;
double elapsed;
unsigned int a_rows = 10;
unsigned int a_cols = 100;
unsigned int b_cols = 10;
matrix* A = new_matrix(a_rows, a_cols);
matrix* B = new_matrix(a_cols, b_cols);
clock_gettime(CLOCK_MONOTONIC, &start);
matrix* AB = matmul(A, B);
clock_gettime(CLOCK_MONOTONIC, &finish);
elapsed = (finish.tv_sec - start.tv_sec);
elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
printf("Linear took \t%.8f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &start);
AB = matmul_threaded(A, B);
clock_gettime(CLOCK_MONOTONIC, &finish);
elapsed = (finish.tv_sec - start.tv_sec);
elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
printf("Parallel took \t%.8f seconds\n", elapsed);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment