I am trying to Multiply the matrix with use of threads. The code seems to be working. I just need to know how to specify the number of threads so that I can count how much time it's taking. I want to create a table of threads and time it's taking to compute the matrix.
I am dynamically allocating the matrix and filling it with random numbers.
I am creating threads to compute the resultant matrix.
C Program to multiply two matrix using pthreads without use of global variables
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
//Each thread computes single element in the resultant matrix
void *mult(void* arg)
{
int *data = (int *)arg;
int k = 0, i = 0;
int x = data[0];
for (i = 1; i <= x; i++)
k += data[i]*data[i+x];
int *p = (int*)malloc(sizeof(int));
*p = k;
//Used to terminate a thread and the return value is passed as a pointer
pthread_exit(p);
}
//Driver code
int main()
{
int i, j, k, row1, col1, row2, col2, r, sum;
printf("Enter the number of rows for matrix 1\n");
scanf("%d",&row1);
printf("Enter the number of columns for matrix 1 \n");
scanf("%d",&col1);
printf("Enter the number of rows for matrix 2 \n");
scanf("%d",&row2);
printf("Enter the number of columns for matrix 2\n");
scanf("%d",&col2);
int **a = (int **) malloc(row1 * sizeof(int *));
for(i=0;i<row1;i++)
a[i] = (int *) malloc(col1 * sizeof(int));
int **b = (int **) malloc(row2 * sizeof(int *));
for(i=0;i<row2;i++)
b[i] = (int *) malloc(col2 * sizeof(int));
for(i=0;i<row1;i++)
{
for(j=0;j<col1;j++)
{
a[i][j] = (rand()%9) + 1;
}
}
for(i=0;i<row2;i++)
{
for(j=0;j<col2;j++)
{
b[i][j] = (rand()%9) +1;
}
}
int N = row1*col2;
//declaring array of threads of size row1*col2
pthread_t *threads;
threads = (pthread_t*)malloc(N*sizeof(pthread_t));
int count = 0;
int* data = NULL;
for (i = 0; i < row1; i++)
for (j = 0; j < col2; j++)
{
//storing row and column elements in data
data = (int *)malloc((N)*sizeof(int));
data[0] = col1;
for (k = 0; k < col1; k++)
data[k+1] = a[i][k];
for (k = 0; k < row2; k++)
data[k+col1+1] = b[k][j];
//creating threads
pthread_create(&threads[count++], NULL,
mult, (void*)(data));
}
printf("RESULTANT MATRIX IS :- \n");
for (i = 0; i < N; i++)
{
void *k;
//Joining all threads and collecting return value
pthread_join(threads[i], &k);
int *p = (int *)k;
printf("%d ",*p);
if ((i + 1) % col2 == 0)
printf("\n");
}
return 0;
}
Related
I need to create a program that gets a dynamic matrix and changes it to one dimension, for example 4x4 matrix will give 16 arrays length, where each index has a odd or even number, matching the index itself. The threads needs to go over the matrix at the same time and copy the odd and even numbers to the correct places in the array. The main thread needs to wait for the rest of them to finish before printing the array and every value with its respective thread. It should come out like this
We managed to fix the segmentation fault that kept happening, but now we need to set it so that each thread runs right after the other but instead each thread runs 4 times and then it switches to a different one. How can I change it so it'll run as asked?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#define CORE 4
int N;
int odd = 1;
int even = 0;
typedef struct my_thread {
int** matrix;
int* resArray;
int threadId;
int strart_raw;
int strart_cal;
int end_raw;
int end_cal;
int counter;
} my_thread;
void* createArray(struct my_thread* thread);
void main() {
pthread_t th[CORE];
int s_r = 0, s_c, e_r, e_c;
int i, j, lines, columns, * intMatrix;
printf("Type the N for the N*N matrix:\t");
scanf("%d", &N);
int size = N * N;
int result_Array[N * N];
int retcode;
int interval = size / CORE;
int matrix_build_counter = 1;
intMatrix = (int*)malloc(N * N * sizeof(int));
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
intMatrix[i * N + j] = matrix_build_counter;
matrix_build_counter++;
}
}
printf("The matrix:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", intMatrix[i * N + j]);
}
printf("\n");
}
struct my_thread thred_obj_array[CORE];
for (int i = 0; i < CORE; i++) {
thred_obj_array[i].matrix = &intMatrix;
thred_obj_array[i].resArray = result_Array;
thred_obj_array[i].threadId = i;
thred_obj_array[i].strart_raw = (int)((i * N) / CORE);
thred_obj_array[i].end_raw = (int)(((interval * (i + 1)) / N));
thred_obj_array[i].strart_cal = ((interval * i)) % N;
thred_obj_array[i].end_cal = ((interval) * (i + 1));
thred_obj_array[i].counter = (int)floor((interval)*i);
}
for (int i = 0; i < CORE; i++) {
retcode = pthread_create(&th[i], NULL, createArray, &thred_obj_array[i]);
if (retcode != 0) {
printf("Create thread failed with error %d\n", retcode);
}
}
printf("done");
for (int i = 0; i < CORE; i++) {
pthread_join(th[i], NULL);
}
printf("the result array is: ");
for (int i = 0; i < N * N; i++) {
printf("%d ", result_Array[i]);
}
}
void* createArray(struct my_thread* thread) {
int j;
for (int i = thread->strart_raw; i < N; i = i * sizeof(int) * N) {
for (j = thread->strart_cal; j < N; j++) {
printf("I am thread: %d And my value is: %d , (%d,%d)\n", thread->threadId, (*thread->matrix + i * N)[j], i, j);
if (((*thread->matrix + i * N)[j]) % 2 == 0) {
thread->resArray[even] = (*thread->matrix + i * N)[j];
even += 2;
printf("-----%d ---even---\n", even);
}
else {
thread->resArray[odd] = (*thread->matrix + i * N)[j];
odd += 2;
printf("---%d ---odd--\n", odd);
}
(thread->counter)++;
if (thread->counter == thread->end_cal) {
return;
}
}
thread->strart_cal = 0;
}
}
I have to calculate the speed of operation for different threads but the matrix size has to be (1000X1 and 1X1000). I have to calculate this using 1,2,4,8,16,32,64,128,256 and 512 threads.
my program is returning same values for all the resultant matrix. Where do I make changes?
I am using random number generator to fill the matrices and dynamically allocating and freeing the matrices.
I first kept N = 512 but I was getting segmentation fault core dumped error so I increased the N. How can I use different number of threads to calculate the matrix?
For a 1000X1 and 1X1000 matrix the resulatant matrix is all 18 and gets segmentation fault core dump error.
For 100X1 and 1X100 all values are 3 and the same happens
to compile it you have to use -lpthreads and -fopenmp
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
// Each thread computes single element in the resultant matrix
void *mult(void *arg)
{
int *data = (int *)arg;
int k = 0, i = 0;
int x = data[0];
for (i = 1; i <= x; i++)
k += data[i] * data[i + x];
int *p = (int *)malloc(sizeof(int));
*p = k;
// Used to terminate a thread and the return value is passed as a pointer
pthread_exit(p);
}
// Driver code
int main()
{
int i, j, k, row1, col1, row2, col2, r, sum, no_of_threads;
printf("Enter the number of rows for matrix 1\n");
scanf("%d", &row1);
printf("Enter the number of columns for matrix 1 \n");
scanf("%d", &col1);
printf("Enter the number of rows for matrix 2 \n");
scanf("%d", &row2);
printf("Enter the number of columns for matrix 2\n");
scanf("%d", &col2);
int **a = (int **)malloc(row1 * sizeof(int *));
for (i = 0; i < row1; i++)
a[i] = (int *)malloc(col1 * sizeof(int));
int **b = (int **)malloc(row2 * sizeof(int *));
for (i = 0; i < row2; i++)
b[i] = (int *)malloc(col2 * sizeof(int));
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
a[i][j] = (rand() % 9) + 1;
}
}
for (i = 0; i < row2; i++)
{
for (j = 0; j < col2; j++)
{
b[i][j] = (rand() % 9) + 1;
}
}
int N = 1000;
// declaring array of threads of size row1*col2
pthread_t *threads;
threads = (pthread_t *)malloc(N * sizeof(pthread_t));
int count = 0;
int *data = NULL;
for (i = 0; i < row1; i++)
for (j = 0; j < col2; j++)
{
// storing row and column elements in data
data = (int *)malloc((N) * sizeof(int));
data[0] = col1;
for (k = 0; k < col1; k++)
data[k + 1] = a[i][k];
for (k = 0; k < row2; k++)
data[k + col1 + 1] = b[k][j];
}
// creating threads
for (int i = 0; i < 512; i++)
{
std:
pthread_create(&threads[i], NULL,
mult, (void *)(data));
}
printf("RESULTANT MATRIX IS :- \n");
for (i = 0; i < N; i++)
{
void *k;
// Joining all threads and collecting return value
pthread_join(threads[i], &k);
int *p = (int *)k;
printf("%d ", *p);
if ((i + 1) % col2 == 0)
printf("\n");
}
for (int i = 0; i < row1; i++)
{
free(a[i]);
}
for (int i = 0; i < row2; i++)
{
free(b[i]);
}
free(a);
free(b);
free(data);
return 0;
}
EDIT:
How do I send multiple arguments through threads as if I read the matrix in my main function, I am not able to pass the values of rows and columns to my mult function. If I read the matrix in mult function then the threads are not working. How do I get it to multiply?
Your approach is flawed:
the destination matrix is not allocated properly
you pass the same argument to all threads
the threads do not receive any information regarding where to store the result of the scalar product.
You should allocate an argument structure for each thread and pass the source arrays and destination location.
With the current approach, there are row1 * col2 scalar products to compute: if you want to use fixed number of threads, you should construct a list of tasks for each thread to process in order to distribute the word among the threads. It is rather easy to do it statically and since all single computations are equivalent in terms of complexity, dynamic distribution does not seem necessary.
Note however that you must wait for all threads to complete before examining and freeing the results. Freeing the arrays as the threads are potentially still accessing the data is among the many causes for undefined behavior in the posted code.
I need a function to bubble sort this randomly generated 2D array.
Also with rand() method I wanted it to generate numbers between (1, 1000000) but it doesnt give the required range, any suggestion to find out a solution?
int **matrix()
{
int **matrix;
int row, column;
long s, k;
int i,j,f,swap;
srand(time(NULL));
printf("Number of rows: ");
scanf("%d", &row);
printf("Number of column: ");
scanf("%d", &column);
matrix = (int **) calloc(row, sizeof(int));
for(i = 0; i < row; i++)
matrix[i] = (int *) calloc(column, sizeof(int));
for(s = 0; s < row; s++)
{
for(k = 0; k < column; k++)
{
matrix[s][k]=rand()%10000000;
}
}
for(s = 0; s < row; s++)
{
for(k = 0; k < column; k++)
printf("%4d \t\t", matrix[s][k]);
printf("\n");
}
for(i = 0; i < row; i++)
free((void *) matrix[i]);
free((void *) matrix);
return **matrix;
}
Sorting a 2D array with bubble sort is a little different that sorting a single dimensional array. This example may help with that part of your question.
Other issues:
Based on this section:
for(i = 0; i < row; i++)
matrix[i] = (int *) calloc(column, sizeof(int));
The line in the preceding section:
matrix = (int **) calloc(row, sizeof(int));
^
Should be allocating memory for int *
matrix = calloc(row, sizeof(int *));
^
(Note the cast for calloc() has also been removed. In C casting the return of [c][m][re]alloc is not recommended.)
Also with rand() method I wanted it to generate numbers between (1, 1000000) but it doesnt give the required range, any suggestion to find out a solution?
( With credit to this answer )
rand() expanded to provide a pseudo random distribution of 1000000 unique values:
unsigned long rand_ex(void);
int main(void){
srand(clock());
for(int i=0;i<100;i++)
{
printf("%10d: %10lu\n", i, rand_ex());
}
return 0;
}
unsigned long rand_ex(void)
{
unsigned long x;
x = rand();
x <<= 15;
x ^= rand();
x %= 1000001;
return x;
}
#include <stdio.h>
#include <pthread.h>
int arr[1000][1000];
int brr[1000][1000];
int h;
int f;
void *BMM(void *arg)
{
int* neo = (int*) arg;
int ne = *neo;
int sum = 0;
for(int i = 0; i < n; ++i)
{
sum += arr[x][i]*brr[x][f];
++f;
}
printf("%d\n", sum);
crr[x][h] = sum;
pthread_exit(NULL);
}
int main()
{
pthread_t* ar = malloc(3*sizeof(*ar));
printf("Enter the value of m and n\n");
scanf("%d %d",&m,&n);
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
scanf("%d",&arr[i][j]);
}
}
printf("Enter the value of p and q\n");
scanf("%d %d",&p,&q);
if(p != n)
{
printf("The matrix multiplication is not possible\n");
return 0;
}
int* id;
id = (int *)malloc(4*sizeof(int));
for(int i = 0; i < p; ++i)
{
for(int j = 0; j < q; ++j)
{
scanf("%d",&brr[i][j]);
}
}
for(x = 0; x < m; ++x)
{
for(z = 0; z < q; z+=4)
{
f = z;
h = z;
for(int k = 0; k < 3; ++k)
{
pthread_create(&ar[k],NULL,BMM,NULL);
}
for(int k = 0; k < 3; ++k)
{
pthread_join(ar[k],NULL);
}
}
}
for (int i = 0; i < m; ++i)
{
for(int j = 0; j < q; ++j)
{
printf("%d ",crr[i][j]);
}
printf("\n");
}
}
The above program is supposed to multiply two matrix by multiplying row one of matrix by all the columns of other matrix using 3 threads and then row two by all the other columns and so on and then store the respective values int another matrix but it is giving segmentation fault. Where am I going wrong?
I think your problem is here:
pthread_create(&ar[k],NULL,BMM,NULL);
^^^^
void *arg is NULL
and then:
void *BMM(void *arg)
{
int* neo = (int*) arg;
int ne = *neo; // Dereference NULL --> segmentation fault
Further this looks strange:
void *BMM(void *arg)
{
int* neo = (int*) arg;
int ne = *neo; // ne is never used !!
int sum = 0;
for(int i = 0; i < n; ++i) // Where does n come from ?
Perhaps it should be n instead of ne?
If n, x, f and h are global variables you are into trouble as all threads will work on the same variables. That would be real bad. Each thread needs it own variables.
BTW:
Always check the value returned by scanf - something like:
if (scanf("%d %d",&m,&n) != 2)
{
// Add error handling here
}
and
if (scanf("%d",&arr[i][j]) != 1)
{
// Add error handling here
}
#include <stdio.h>
#include <stdlib.h>
void multiplyMatrix (int **first, int **second, int **multiply);
int m, n, p, q, i, c, d, k, sum = 0;
int main()
{
int **first, **second, **multiply;
printf("Enter the number of rows and columns of first matrix\n");
scanf("%d%d", &m, &n);
first = (int **) malloc(m * sizeof(int *));
for(i = 0 ; i < n ; i++){
first[i]=(int *)malloc(m * sizeof(int *));
}
printf("Enter the elements of first matrix\n");
for (c = 0; c < m; c++)
for (d = 0; d < n; d++)
scanf("%d", &first[c][d]);
printf("Enter the number of rows and columns of second matrix\n");
scanf("%d%d", &p, &q);
second = (int **) malloc(p * sizeof(int *));
for(i = 0 ; i < q ; i++){
second[i]=(int *) malloc(p * sizeof(int *));
}
if (n != p)
printf("Matrices with entered orders can't be multiplied with each other.\n");
else
{
printf("Enter the elements of second matrix\n");
for (c = 0; c < p; c++)
for (d = 0; d < q; d++)
scanf("%d", &second[c][d]);
/*for (c = 0; c < m; c++) {
for (d = 0; d < q; d++) {
for (k = 0; k < p; k++) {
sum = sum + first[c][k]*second[k][d];
}
multiply[c][d] = sum;
sum = 0;
}
}*/
multiplyMatrix(first, second, multiply);
printf("Product of entered matrices:-\n");
for (c = 0; c < m; c++) {
for (d = 0; d < q; d++)
printf("%d\t", multiply[c][d]);
printf("\n");
}
}
return 0;
}
void multiplyMatrix (int **first, int **second, int **multiply)
{
for (c = 0; c < m; c++) {
for (d = 0; d < q; d++) {
for (k = 0; k < p; k++) {
sum = sum + first[c][k]*second[k][d];
}
multiply[c][d] = sum;
sum = 0;
}
}
}
The program i want to write should be like this: The program asks to the user to enter both the sizes and elements of 2 matrices (or you can call it 2d arrays). Then it will multiply those matrices and print the answer.
The problem i am getting: i used pointers and malloc functions to dynamically allocate the matrices. for the multiplication, i created a function called "multiplyMatrix" which i get a warning for one of the arguments of it in the decleration. here is the warning:
warning: 'multiply' may be used uninitialized in this function.
so there is some kind of a problem with initializing this argument. i feel like the answer is simple but at the same time i can't find the solution.
You have not allocated the memory to be used by the multiply matrix - hence it is being flagged as uninitialised.
You also need to review how you use your row and column values when allocating the first and second matrices, for example:
first = (int **) malloc(m * sizeof(int *));
for(i = 0 ; i < m ; i++){
first[i]=(int *)malloc(n * sizeof(int *));
}
(Incorporates comment made by wildplasser)
This will allow first to be accessed as first[row][col]
the variable multiply was declared in main(), however it is never set to point to anything. it needs to be created the same way as first and second, however it does not need to have its' values filled in.
Suggestions to improve your code:
Create a function to allocate memory for a matrix.
Create a function to read matrix data.
Create a function to deallocate memory of a matrix.
Avoid use of global variables. Pass the necessary arguments to a function.
Use those functions instead of duplicating code in main.
#include <stdio.h>
#include <stdlib.h>
int** createMatrix(int rows, int cols)
{
int i;
int** mat = malloc(sizeof(*mat)*rows);
for ( i = 0; i < rows; ++i )
mat[i] = malloc(sizeof(*mat[i])*cols);
return mat;
}
void readMatrix(int** mat, int rows, int cols)
{
int r;
int c;
for ( r = 0; r < rows; ++r )
for ( c = 0; c < cols; ++c )
scanf("%d", &mat[c][c]);
}
void deleteMatrix(int** mat, int rows)
{
int i;
for ( i = 0; i < rows; ++i )
free(mat[i]);
free(mat);
}
void multiplyMatrix (int **first, int **second, int **multiply,
int frows, int fcols, int scols)
{
int sum = 0;
int r;
int c;
int k;
for (r = 0; r < frows; r++) {
for (c = 0; c < scols; c++) {
sum = 0;
for (k = 0; k < fcols; k++) {
sum += first[r][k]*second[k][c];
}
multiply[r][c] = sum;
}
}
}
int main()
{
int m, n, p, q;
int r, c;
int **first, **second, **multiply;
printf("Enter the number of rows and columns of first matrix\n");
scanf("%d%d", &m, &n);
first = createMatrix(m, n);
printf("Enter the elements of first matrix\n");
readMatrix(first, m, n);
printf("Enter the number of rows and columns of second matrix\n");
scanf("%d%d", &p, &q);
if (n != p)
printf("Matrices with entered orders can't be multiplied with each other.\n");
else
{
second = createMatrix(p, q);
printf("Enter the elements of second matrix\n");
readMatrix(second, p, q);
multiply = createMatrix(m, q);
multiplyMatrix(first, second, multiply, m, n, q);
printf("Product of entered matrices:-\n");
for (r = 0; r < m; r++) {
for (c = 0; c < q; c++)
printf("%d\t", multiply[r][c]);
printf("\n");
}
deleteMatrix(multiply, m);
deleteMatrix(second, p);
}
deleteMatrix(first, m);
return 0;
}