How to send a matrix to a thread function? - c

I have to create in C a program that is able to calculate the determinant of a random 3x3 matrix using the Sarrus method. I have to use one thread (Thread A) to compute blue diagonals, and a second thread (Thread B) to compute red ones. (See img https://i.stack.imgur.com/HQL1U.png )
My code is:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define m 3
#define n 3
typedef struct thread_params{
int *data_matrix;
int diag_result;
} thread_params;
void *diagA (void *params){
thread_params *pp = (thread_params *) params;
int **matrix_ptr = &pp->data_matrix;
int diag = 0;
diag = matrix_ptr[0][0] * matrix_ptr[1][1] * matrix_ptr[2][2] + matrix_ptr[0][1] * matrix_ptr[1][2] * matrix_ptr[2][0] + matrix_ptr[0][2] * matrix_ptr[1][0] * matrix_ptr[2][1];
pp->diag_result = diag;
return (void *) &pp->diag_result;
}
void *diagB (void *params){
thread_params *pp = (thread_params *) params;
int **matrix_ptr = &pp->data_matrix;
int diag = 0;
diag = matrix_ptr[2][0] * matrix_ptr[1][1] * matrix_ptr[0][2] + matrix_ptr[2][1] * matrix_ptr[1][2] * matrix_ptr[0][0] + matrix_ptr[2][2] * matrix_ptr[1][0] * matrix_ptr[0][1];
pp->diag_result = diag;
return (void *) &pp->diag_result;
}
int main(){
// Create matrix
int **matrix;
int row;
matrix = (int **) malloc(m * sizeof(int *));
for (row = 0; row < m; row++){
matrix[row] = (int *) malloc(n * sizeof(int));
}
// Matrix initialization
srand(time(NULL));
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
matrix[i][j] = rand() % 10;
printf("%d ", matrix[i][j]);
}printf("\n");
}
// Thread creation
pthread_t threadA_id;
pthread_t threadB_id;
int *threadA_returnValue;
int *threadB_returnValue;
thread_params threadA_args;
thread_params threadB_args;
threadA_args.data_matrix = &matrix[0][0];
threadA_args.diag_result = 0;
threadB_args.data_matrix = &matrix[0][0];
threadB_args.diag_result = 0;
pthread_create(&threadA_id, NULL, &diagA, &threadA_args);
pthread_create(&threadB_id, NULL, &diagB, &threadB_args);
pthread_join(threadA_id, (void **) &threadA_returnValue);
pthread_join(threadB_id, (void **) &threadB_returnValue);
// Print results
printf("%d - %d = %d\n", *threadA_returnValue, *threadB_returnValue, *threadA_returnValue - *threadB_returnValue);
return 0;
}
The main problem is that I don't know how to correctly send the random matrix as argument to the threads functions. I tried to utilize a struct with a pointer inside but in this way I'm able to sent to the thread function only the first row of my matrix and then, when I try to access the second row, a segmentation fault error is generated.
I think my error is caused by this type of assignation:
threadA_args.data_matrix = &matrix[0][0];
How can I solve this problem?

Related

Passing an array as thread's argument

I have some issues with my code. I need to pass an int array to a thread witch will calculate the ^2 of every int of the array.
My code:
#include <pthread.h> //etc.
#define SIZE 1024
static void * function_thread(void *arg){
int *loc = (int *)arg;
// i tried also int loc[SIZE] = (int *)arg; but won' compile ion' t know why
for (int i = 0; i < SIZE; i++) {
loc[i] = loc[i] * loc[i];
// tried also loc[i] = (*(int *)arg) * (*(int *)arg);
printf("loc[%d]^2 = %d\n",i, loc[i]);
}
return (void *)loc;
}
int main(int argc, char const *argv[]) {
int x[SIZE];
void (*res[SIZE]);
int y[SIZE];
for (int i = 0; i < SIZE; i++) {
x[i] = i;
}
pthread_t thread_1;
pthread_create(&thread_1,NULL,function_thread,x);
pthread_join(thread_1, &res);
for(int i = 0; i < SIZE; i++){
y[i] = res[i];
}
}
So i have few questions:
There is something wrong already in the thread function? is giving me loc[i] = 0 for each i.What's the problem?
why the initialization of *int loc[SIZE] = (int * )arg; doesnìt work?
I have seen that
int x;
int * result;
...
pthread_join(someThread, &result);
x = result + result;
this works.But why? isn't x and result types different?
Thanks you in advice and wish you a good day!

Dynamic Matrix Multiplication with Pthreads

I'm a beginner with Thread Programming and C in general and I'm trying to figure out how to do a simple Matrix Multiplication with Pthreads. I want to create a thread for every column and put the results in a Result Matrix. I'm trying to do it dynamicly, which means the user is allowed to use an input as a size to create two n x n matrices.
My code right now, excluding filling the matrix and reading the size n is the following:
#include <pthread.h>
#include <stdio.h>
#include<stdlib.h>
typedef struct Matrix {
int line, col, size;
double (*MA)[];
double (*MB)[];
double (*MC)[];
} Matrix;
void *multiply(void *arg) {
Matrix* work = (Matrix*) arg;
int s, z;
s = work->col;
z = work->line;
work->MC[0][0] = 0.0.//can't use MC, MB, MA here!!
return 0;
}
int main() {
Matrix* m;
//read size and set it to int size (miissing here, does work)
double MA[size][size], MB[size][size], MC[size][size];
int i, j;
//filling the matrices (missing here, does work)
pthread_t threads[size];
for (i = 0; i < size; i++) {
m = malloc(sizeof(Matrix*));
m->size = size;
m->col = i;
pthread_create(&threads[i], NULL, multiply, m);
}
for (i = 0; i < size; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
The problem is, that I cant use neither MA, MB nor NC(:= the result) in the multiply method with something like its shown in the code.
I just get the error "invalid use of array with unspecific bounds" even though I declared all three of them in the main method.
Do I understand anything wrong here or how can I fix that? I tried to adapt a example of my lecture where a thread for every element will be created.
Thanks in advance!
Just about the error:
work->MC[0][0] = 0.0.//can't use MC, MB, MA here!!
MC was declared as double (*MC)[] and you try to use it as a two dimensional array like you had declared it double MC[N]{M]. You can use a two (or more) dimensional array like you did if and only if the first dimension was fixed or if you alloc it row by row.
So your program could be:
#include <pthread.h>
#include <stdio.h>
#include<stdlib.h>
typedef struct Matrix {
int line, col, size;
double MA[][];
double MB[][];
double MC[][];
} Matrix;
void *multiply(void *arg) {
Matrix* work = (Matrix*) arg;
int s, z;
s = work->col;
z = work->line;
work->MC[0][0] = 0.0
return 0;
}
int main() {
Matrix* m;
//read size and set it to int size (miissing here, does work)
double MA[][], MB[][], MC[][];
int i, j;
pthread_t threads[size];
MA = (double **) malloc(size * sizeof(double *));
MB = (double **) malloc(size * sizeof(double *));
MC = (double **) malloc(size * sizeof(double *));
for(int i=0;i<size;++i){
MA[i] = (double *) malloc(size * sizeof(double));
MB[i] = (double *) malloc(size * sizeof(double));
MC[i] = (double *) malloc(size * sizeof(double));
}
for (i = 0; i < size; i++) {
m = malloc(sizeof(Matrix*));
m->MA = MA;
m->MB = MB;
m->MC = MC;
m->size = size;
m->col = i;
pthread_create(&threads[i], NULL, multiply, m);
}
for (i = 0; i < size; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
But you must TAKE CARE that the thread can access to the data concurrently and so you should use some locks if different threads can use and change same values.

Segmentation fault - C program using Pthreads and matrix

I have been working on this program that accomplishes this:
counts the number of occurrences of a specific integer value in a 2D array (matrix). Each position of the matrix must first be initialized to an integer value between 0 and
n. Once initialized, program will search and count the total number of occurrences of a specific value.
The program is run by taking in the parameters as command line arguments:
programName rows cols n c
rows – number of rows of the matrix
cols – number of columns of the matrix
n – the upper bound of the random values of the matrix, values can be 0–(n-1)
c – the value to search for in the matrix, note c must be between 0–(n-1)
After this, the program implements the search using 1 to 10 threads and displays the execution time and number of occurrences.
I seem to have all of this working how I wish, however the problem is that whenever I enter a value over 4 in the command line for rows, I keep getting the segment fault error.
I am at a loss as to what is causing this. Please help me understand what error in my coding may be contributing to this? Thank you.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#define NUM_THREADS 10
int **arr;
int rows, cols, n, c, totalOccurrence, done, numThreads;
int threadCounter[10];
void *matrixThread (void *threadid)
{
long tid;
tid = (long)threadid;
long lowBound = tid * (rows / numThreads);
long highBound = lowBound + (rows / numThreads);
int localcount = 0;
if (tid == numThreads - 1)
{
highBound = rows;
}
long i;
int ic;
for (i = lowBound; i < highBound; i++)
{
for (ic = 0; ic < cols; ic++)
{
if (arr[i][ic] == c)
{
localcount++;
}
}
}
threadCounter[tid] = localcount;
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
if (argc != 5)
{
printf("Error: Invalid number of arguments\n");
}
else
{
rows = strtol(argv[1], NULL, 10);
cols = strtol(argv[2], NULL, 10);
n = strtol(argv[3], NULL, 10);
c = strtol(argv[4], NULL, 10);
int r, cl;
arr = (int**)malloc(rows * sizeof(int));
for (r = 0; r < rows; r++)
{
arr[r] = malloc(cols * sizeof(int));
}
int randomNum;
srand(time(NULL));
for (r = 0; r < rows; r++)
{
for (cl = 0; cl < cols; cl++)
{
randomNum = rand() % n;
arr[r][cl] = randomNum;
}
}
long rc, t;
for (numThreads = 1; numThreads <= 10; numThreads++)
{
struct timeval start,end;
double elapsed_time;
gettimeofday(&start, NULL);
for (t = 0; t < numThreads; t++)
{
rc = pthread_create(&threads[t], NULL, matrixThread, (void *)t);
if (rc)
{
printf ("Error: Thread could not be created; return %d", rc);
exit(-1);
}
}
for (t = 0; t < numThreads; t++)
{
pthread_join(threads[t], NULL);
}
totalOccurrence = 0;
int q;
for (q = 0; q < numThreads; q++)
{
totalOccurrence += threadCounter[q];
}
gettimeofday(&end, NULL);
elapsed_time = (end.tv_sec + end.tv_usec/1000000.10000) - (start.tv_sec + start.tv_usec/1000000.10000);
printf("\nNumber of threads: %d " , numThreads);
printf("Total Occurrences of %d: %d " ,c, totalOccurrence);
printf("Elapsed time: %.8f\n" , elapsed_time);
totalOccurrence = 0;
}
}
pthread_exit(NULL);
}
Here is one problem:
arr = (int**)malloc(rows * sizeof(int));
should be:
arr = (int**)malloc(rows * sizeof(int *));
The allocation of the rows should be like this
arr = (int**)malloc(rows * sizeof(int*));
Because the sizeof datatypes can vary. But the sizeof a pointer will be constant in a particular machine architecture. In a 64 bit machine the sizeof a pointer will be 8 bytes. But sizeof int will be usually 4 bytes (gcc). So here you will be having allocated only 4 blocks. That why when you try to pass more than 4, it's crashing because there's an invalid memory read.
Also your program will cause memory leak, as you are not freeing the allocated memory. Use like this at the end.
for (r = 0; r < rows; r++)
{
free (arr[r]);
}
free (arr);

segmentation fault in 2D array assignment and thread call

I've wrote the following code to implement matrix multiplication but repeatedly i got segmentation fault error. It's seems to everything be OK. can anybody tell my what's the problem.
this is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int matrixSize;
double ** a, ** b, ** c;
typedef struct tparms {
int row;
int col;
}tparms_t;
double ** allocateMatrix() {
int i;
double *vals, **temp;
//allocate values
vals = (double *) malloc (matrixSize * matrixSize * sizeof(double));
// allocate vector of pointers
temp = (double **) malloc (matrixSize * sizeof(double*));
for(i=0; i < matrixSize; i++)
temp[i] = &(vals[i * matrixSize]);
return temp;
}
void* multiply (void* _arg){
tparms_t * arg = (tparms_t *) _arg;
int i;
double sum;
for (i=0; i<matrixSize; i++)
sum += a[arg->row][i] * b[i][arg->col];
c[arg->row][arg->col] = sum;
}
void main(int argc, char *argv[]) {
pthread_t *threads;
if (argc != 2) {
printf("Usage: %s <size>, where size is dimension of square matrix\n", argv[0]);
exit(1);
}
int matrixSize = atoi(argv[1]);
threads = (pthread_t *) malloc(matrixSize * matrixSize * sizeof(pthread_t));
a = allocateMatrix();
b = allocateMatrix();
c = allocateMatrix();
int i, j;
for (i=0; i<matrixSize; i++){
for (j=0; j<matrixSize; j++){
a[i][j] = i + j;
b[i][j] = i + j;
}
}
for (i=0; i<matrixSize; i++){
for (j=0; j<matrixSize; j++){
tparms_t * tt = (tparms_t *)malloc(sizeof(tparms_t));
tt->row = i;
tt->col = j;
pthread_create(&threads[i*matrixSize + j], NULL, multiply, (void*)tt);
}
}
// two for for arrays
for (i=0; i<matrixSize; i++){
for (j=0; j<matrixSize; j++){
//do something ...
pthread_join(threads[i*matrixSize+j], NULL);
}
}
// end of two fors
}
there is a struct to pass data to threads, allocation function to allocate arrays and in main function i decide to create a thread for each of matrix elements. then a join function to wait until all threads do their job and create the c matrix elements.
You have int matrixSize = atoi (argv[1] );. Remove int because that creates another local instance of matrixSize.

Pthread_join() Causing segment default error

What the following code trying to accomplish is just to compute the Matrix Multiplication of A and B to get matrix C. It uses nXn threads to compute each entry of C independently. So the code works on Cygwin, but not on linux. I keep getting segment default with the Pthread_join calls.
#define _REENTRANT // Make sure the library functions are MT (muti-thread) safe
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define BUFFER_SIZE 512
// Declare a structure data type that will be used to pass arguments to the worker threads
typedef struct args_for_thread_t{
int *rowA;
int rowIdx;
int *columnB;
int columnIdx;
int **matrixC;
} ARGS_FOR_THREAD;
/* Global Variables */
int numRows,numColumns;
/*Function Prototype*/
void *computeC(void *this_arg);
void printMatrix(int** matrix,int numRows,int numColumns);
int main(void){
const char filename[] = "input_data.txt";
FILE *file = fopen(filename,"r");
char *delims = " ";
int **matrixA,**matrixB,**matrixC;
int flagB = 0; //Indicate wether the program should process matrixB
int i,j;
if (file){
char line[BUFFER_SIZE];
int rowIdx = 0;
while (fgets(line,sizeof(line), file)){
char substr[BUFFER_SIZE], *result;
//fputs(line,stdout);
result = strtok(line, delims);
int columnIdx = 0;
//Once we reach a line break, we start the processing of matrix B
if (!strcmp(line,"\n")){
flagB = 1;
rowIdx = 0; //Reset the rowIdx
continue; //Skip the new line, and start to read data into matrix B
}
while (result != NULL){
if (!strcmp(result,"ROWS")){ //To retrieve the number of rows
result = strtok(NULL,delims);
numRows = atoi(result);
matrixA = (int **) malloc(numRows*sizeof(int*));
matrixB = (int **) malloc(numRows*sizeof(int*));
matrixC = (int **) malloc(numRows*sizeof(int*));
rowIdx = -1;
result = strtok(NULL,delims);
}
else if (!strcmp(result,"COLUMNS")){//To retrieve the number of Columns
result = strtok(NULL,delims);
numColumns = atoi(result);
for (i=0;i<numRows;i++){ //Malloc the columns
matrixA[i] = (int *) malloc(numColumns*sizeof(int));
matrixB[i] = (int *) malloc(numColumns*sizeof(int));
matrixC[i] = (int *) malloc(numColumns*sizeof(int));
}
rowIdx = -1;
result = strtok(NULL,delims);
}
else if (!flagB){ //Processing Matrix A
matrixA[rowIdx][columnIdx] = atoi(result);
columnIdx++;
result = strtok(NULL,delims);
}
else if (flagB){ //Processing Matrix B
matrixB[rowIdx][columnIdx] = atoi(result);
columnIdx++;
result = strtok(NULL,delims);
}
}
rowIdx++;
}
}
else{
printf("No Such File exists!\n");
}
//At this point, matrix A and matrix B are both ready for computation. We will start to compute the product of the two matrices
int num_threads = numRows*numColumns; //The toal number of worker threads
pthread_t *worker_thread = (pthread_t *) malloc(sizeof(pthread_t)*num_threads);
ARGS_FOR_THREAD *args_for_thread;
for(i = 0; i < numRows; i++){
for(j = 0; j < numColumns; j++){
args_for_thread = (ARGS_FOR_THREAD *)malloc(sizeof(ARGS_FOR_THREAD)); // Allocate memory for the structure that will be used to pack the arguments
args_for_thread-> rowA = matrixA[i];
//We need to allocate the corresponding column in B for multiplication
int k;
args_for_thread->columnB =(int *) malloc(sizeof(int)*numRows);
for (k=0;k<numRows;k++){
args_for_thread-> columnB[k] = matrixB[k][j];
}
//rowIdx and columnIdx gives the corresponding entry for matrix C
args_for_thread-> rowIdx = i;
args_for_thread-> columnIdx = j;
args_for_thread-> matrixC = matrixC;
if((pthread_create(&worker_thread[i], NULL, computeC, (void *)args_for_thread)) != 0){
printf("Cannot create thread \n");
exit(0);
}
}
}
// Wait for all the worker threads to finish
for(i = 0; i < num_threads; i++)
pthread_join(worker_thread[i], NULL);
//Print out the Final Matrix C
printMatrix(matrixC,numRows,numColumns);
//Clean up pointers
for(i = 0; i < numRows; i++){
free(matrixA[i]);
free(matrixB[i]);
free(matrixC[i]);
}
free(matrixA);
free(matrixB);
free(matrixC);
}
void printMatrix(int** matrix,int numRows, int numColumns){
int i,j;
for (i=0;i<numRows;i++){
for (j=0;j<numColumns;j++){
printf("%d ",matrix[i][j]);
if (j==numColumns-1){
printf("\n");
}
}
}
}
/* Function that will be executed by all the worker threads. It will compute the i,j entry for column C */
void *computeC(void *this_arg){
ARGS_FOR_THREAD *arg = (ARGS_FOR_THREAD *) this_arg;
int rowIdx = arg->rowIdx;
int columnIdx = arg->columnIdx;
int *rowA = arg->rowA;
int *columnB = arg->columnB;
int **matrixC = arg->matrixC;
int i;
int sum = 0;
for (i=0;i<numRows;i++){ //Compute entry for matrix C. Since A,B are nxn square matrix, we can use either numRows or numColumns as the size
sum += rowA[i]*columnB[i];
}
matrixC[rowIdx][columnIdx] = sum;
free((void *) arg); // Free up the structure
pthread_exit(NULL);
}
What is the issue here? Thank you.
Here:
pthread_create(&worker_thread[i] ...
You create i * j threads, yet you only provide worker_threads[i] hence your program keeps using the same pthread_t variables. It later fails when you try to join the threads with undefined pthread_t values.
Replace by:
pthread_create(&worker_thread[i*numColumns+j] ...

Resources