I want to create a C program that calculates the multiplication of two N*N matrices by using threads.
I started this code by referring to Matrix Multiplication using multiple threads but instead of creating N * N threads for each cell of the resulting matrix, I want to create N threads to do the multiplication concurrently where each row of the result matrix will be computed by a different thread.
My code looks like this so far:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#define N 2
struct v {
int i; //Row
int j; //Column
};
int A[N][N] = {{ 1, 2 }, { 3, 4 }};//Matrix 1
int B[N][N] = {{ 2, 3 }, { 4, 5 }};//Matrix 2
int C[N][N]; //Resulting Matrix
static void *fnc(void *arg) {
struct v *data = (struct v *)arg;
int l;
for (l = 0; l < N; l++) {
int i = ((struct v *)data[l]).i; //Row No
int j = ((struct v *)data[l]).j; //Column No
int accumulator = 0;
int d, sum = 0;
for (d = 0; d < N; d++) {
sum = sum + A[i][d] * B[d][j];
}
C[i][j] = sum;
sum = 0;
}
return;
}
int main() {
pthread_t threads[N];
int i, k;
for (i = 0; i < N; i++) {
struct v *data[N];
for (k = 0; k < N; k++) {
data[k] = (struct v *)malloc(sizeof(struct v));
data[k].i = i; //assign the row of C for thread to calculate
data[k].j = k; //assign the column of C for thread to calculate
}
//In this example it creates 2 threads with passing data.
//Data consists of row and column pairs for each thread, that will be calcuting the pairs.
//Consider first iteration of this loop:
//Thread 1 is created and data consists of (0,0) and (0,1) which are the targeted calculation cells for thread 1.
//In the second iteration: Thread 2 will have (1,0) and (1,1) pairs in its data.
pthread_create(&threads[i], NULL, fnc, data);
}
for (i = 0; i < N; i++)
pthread_join(threads[i], NULL);
for (i = 0; i < N; i++)
for (k = 0; k < N; k++)
printf("%d\t", C[i][k]);
return 0;
}
When I compile with
gcc thread.c -lpthread -lrt
I receive this Error:
thread.c: In function ‘fnc’:
thread.c:24:24: error: cannot convert to a pointer type
int i=((struct v*)data[l]).i;//Row No
^
thread.c:24:35: error: request for member ‘i’ in something not a structure or union
int i=((struct v*)data[l]).i;//Row No
^
thread.c:25:24: error: cannot convert to a pointer type
int j=((struct v*)data[l]).j;//Column No
^
thread.c:25:35: error: request for member ‘j’ in something not a structure or union
int j=((struct v*)data[l]).j;//Column No
^
thread.c: In function ‘main’:
thread.c:48:20: error: request for member ‘i’ in something not a structure or union
data[k].i = i; //assign the row of C for thread to calculate
^
thread.c:49:20: error: request for member ‘j’ in something not a structure or union
data[k].j = k; //assign the column of C for thread to calculate
I believe the logic behind the code is correct and this sure looks like a simple argument passing problem. I put the whole code because I will be happy if I receive your comments about the problem and also a possible better solution for the desired job.
Here it is a working solution was posted by @Michi. Your problem was that you were passing a pointer with the same address into a pthread_create
also you had some issues with memory allocation. You had to allocate memory for two dimensional array, and pass into the pthread_create
.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#define N 3
#define n 3
struct v
{
size_t i;
size_t j;
};
double A[N][N] = {{1.0, 2.0, 4.0}, {3.0, 4.0, 5.0}, {4.0, 5.0, 7.0}};
double B[N][N] = {{2.0, 3.0, 9.0}, {4.0, 5.0, 7.0}, {2.0, 3.0, 9.0}};
double C[N][N];
static void * multiplication(void *arg){
struct v *data = (struct v *)arg;
size_t l;
for(l=0; l < N; l++)
{
size_t i=(data[l]).i;
size_t j=(data[l]).j;
double sum=0;
size_t d;
for (d = 0; d < N; d++)
{
sum = sum + A[i][d]*B[d][j];
}
C[i][j] = sum;
sum = 0;
}
return 0;
}
int main(void)
{
pthread_t threads[n];
size_t i, k;
struct v **data;
data = (struct v **)malloc(n * sizeof(struct v*));
for(i = 0; i < n; i++)
{
data[i] = (struct v *)malloc(n * sizeof(struct v));
for(k = 0; k < n; k++)
{
data[i][k].i = i;
data[i][k].j = k;
}
pthread_create(&threads[i], NULL, multiplication, data[i]);
}
for(i = 0; i < n; i++)
{
pthread_join(threads[i], NULL);
}
for (i = 0; i < N; i++)
{
for (k = 0; k < N; k++)
{
printf("%lf\t", C[i][k]);
}
printf("\n");
free(data[i]);
}
free(data);
return 0;
}
Hi i have implemented the 3*3 matrix multiplication using 3*3 thread.The code can be modified for N*N.The code is self explanatory.
*header*/
#include <pthread.h>
#include <stdio.h>
#include<stdlib.h>
/*macro*/
#define NUM_THREADS 9
/*I have defined the structure here to pass the multiple arguments
when creating threads*/
/*structure declaration*/
struct thread_data
{
int element1[3];//passing the element of one matrix
int element2[3];//passing the element of other matrix
int sum;//storing the result of multiplication
}thread_data_array[NUM_THREADS];
/**
* @brief finds matrix multiplication function
* param [in] : accepts the thread arguments
*
* @return void pointer
*/
void *multiplication(void *threadarg)
{
int i;
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;/*type cast the
void pointer to the struct thread*/
//pointer
my_data->sum=0;
for(i=0;i<3;i++){/*multiply and add each element
of 1st matrix to 2nd matrix*/
my_data->sum=my_data->sum
+((my_data->element1[i])*(my_data->element2[i]));
}
}
/*main*/
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
int t;
int matrix_b[3][3]={{156,223,345},{456,5678,656},{712,811,922}};
//to store the matrix
int matrix_a[3][3]={{123,278,335},{437,547,656},{734,832,944}};
int ans[9];
int i,j,count,z,k,l,q;
t=i=j=z=count=k=q=l=0;
/*
suppose the matrices are
1 2 3 1 2 3
4 5 6 1 2 3
7 8 9 1 2 3
so to perform the multiplication
row 1 2 3 will be multiplied too column
111 222 333 respectively.
so 123 shold be stored in 3 spreate threads
and 111 222 333 should be stored in 3 seprate threads
123 111 should be in common thread
123 222 should be in common thread
123 333 should be in common thread
in this way below logic i have
writtten.
It is hard to understand at first glance..
so enjoy!!!!!!
*/
while(z<3){
for(count=0;count<3;count++){/*store the each row of
first matrix 3 times in 3 seprate threads*/
for(j=0;j<3;j++)
thread_data_array[t].element1[j]
= matrix_a[i][j];
t++;
}
/*store the each column of the second matrix in the spreate threads*/
for(k=0;k<3;k++){
for(l=0;l<3;l++)
thread_data_array[q].element2[l]
= matrix_b[l][k];
q++;
}
i++;
z++;
}
/*we have total 9 element in resultant matrix,so to create it we should
create 9 threads*/
for(t=0; t<NUM_THREADS; t++){
rc =pthread_create (&threads[t], NULL, multiplication,
(void *) &thread_data_array[t]);
/*we are passing the function pointer and
the pointer to structure as the argument,since we want to pass multiple argumen
ts we are passing the structure poi
nter as the arguments.*/
if (rc){//if rc is not 0,error is there
printf("ERROR; return code from () is %d\n", rc);
exit(-1);
}
}
/*
NAME
pthread_join - join with a terminated thread
SYNOPSIS
#include <pthread.h>
int pthread_join(pthread_t thread_here, void **retval);
Compile and link with -pthread.
DESCRIPTION
The pthread_join() function waits for the thread specified by thread_here
to terminate. If that thread has already terminated, then
pthread_join() returns immediately. The thread specified by thread
must be joinable.
*/
for (i = 0; i < 9; i++)/*to wait for all the threads to complete*/
pthread_join(threads[i], NULL);
printf("%d %d %d\n",thread_data_array[0].sum,thread_data_array[1].sum,thread_data_array[2].sum);
printf("%d %d %d\n",thread_data_array[3].sum,thread_data_array[4].sum,thread_data_array[5].sum);
printf("%d %d %d\n",thread_data_array[6].sum,thread_data_array[7].sum,thread_data_array[8].sum);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With