Pthread_join() Causing segment default error - c

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] ...

Related

Multithreading but first few threads are being skipped

It's been a few hours and i can't seem to understand the issue. Build this program to count from 1 - 10. The goal of this program is to use multithreading and dynamically split the array depending on how many threads it requested. Problem is the first 2 threads are being skipped and the last thread is doing most of th e process. I suspect it's the for loop that creates the threads.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef struct
{
int *array;
int batch;
int start;
int end;
} Parameter;
void *method(void *p)
{
Parameter *param = (Parameter *)p;
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
}
}
int main(int argc, char **argv)
{
// Getting the user input
int array_length = atoi(argv[1]);
int batches = atoi(argv[2]);
printf("User specified Array:%d\tBatch:%d\n", array_length, batches);
// Creating an array
int *array = (int *)calloc(array_length, sizeof(int));
// Fill it up with some data
for (int i = 0; i < array_length; i++)
{
array[i] = i;
}
// Determine the Batches
int batch_size = array_length / batches;
int remainder = array_length % batches;
printf("%d\n", batch_size);
printf("%d\n", remainder);
int start = 0;
int end = 0;
int index =0;
// List of parameters
Parameter *param = (Parameter *)calloc(batches, sizeof(Parameter));
pthread_t *threads = (pthread_t *)calloc(batches, sizeof(pthread_t));
// Loop through each batch.
for (int i = 0; i < batches; i++)
{
printf("\n\nBatch number -> %d\n", i);
end = start + batch_size;
if (remainder > 0)
{
remainder --;
end ++;
}
// Fill the parameters
param[i].array = array;
param[i].end = end;
param[i].start = start;
param[i].batch = i;
// Call the thread.
pthread_create(threads + index, NULL, method, (void *)&param[i]);
index++;
start = end;
}
for (int i = 0; i < batches; i++)
{
pthread_join(threads[i], NULL);
}
free(param);
free(threads);
free(array);
return 0;
}
Been playing with the index of the for loop(line 57) as i'm certain it's the cause of the issue. been getting some results but the main problem still persisted.
Code Works as intended. I'm a dumbas who didn't put the printf in the void function. like so:
void *method(void *p) {
Parameter *param = (Parameter *)p;
printf("\n\nBatch number -> %d\n", param->batch); //<-- moved from main method
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
} }
Thanks for pointing it out that the program works

How to send a matrix to a thread function?

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?

Multiple C threads not returning correct values

I am trying to multiply two matrices using a different thread for each member of the resultant matrix. I have this code:
struct data{
int p;
int linie[20];
int coloana[20];
};
void *func(void *args){
struct data *st = (struct data *) args;
int c = 0;
for(int k = 0; k < st->p; k++){
c += st->linie[k] * st->coloana[k];
}
char *rez = (char*) malloc(5);
sprintf(rez, "%d", c);
return rez;
}
int main(int argc, char *argv[]){
int n = 2;
int m = 2;
int A[2][2] = {{1, 2},
{4, 5}};
int B[2][2] = {{7, 3},
{7, 5}};
int C[n][m];
char *res[n * m];
char *rez[n * m];
pthread_t threads[n * m];
int count = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
struct data st;
st.p = 2;
for(int x = 0; x < st.p; x++){
st.linie[x] = A[i][x];
st.coloana[x] = B[x][j];
}
pthread_create(&threads[count], NULL, func, &st);
count++;
}
}
for(int i = 0; i < n * m; i++){
pthread_join(threads[i], (void**) &rez[i]);
printf("%d ", atoi(rez[i]));
}
return 0;
}
But the correct result is never put into rez[i]. For example I get output "63 37 37 37".
The code works perfectly if I don't choose to wait for every thread to finish, i.e. I put that pthread_join right after pthread_create in the nested for loop. What should I do?
Thanks for reading!
Your first threading problem is here:
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
struct data st;
st.p = 2;
for(int x = 0; x < st.p; x++){
st.linie[x] = A[i][x];
st.coloana[x] = B[x][j];
}
pthread_create(&threads[count], NULL, func, &st);
count++;
}
}
All the threads get passed a pointer to the same variable, &st, which goes out of scope after each call to pthread_create(). You need to ensure that each thread gets its own variable, and that the variable lasts until the thread exits.
To fix this, for example, you could try:
struct data st[n * m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
st[count].p = 2;
for (int x = 0; x < st[count].p; x++)
{
st[count].linie[x] = A[i][x];
st[count].coloana[x] = B[x][j];
}
int rc = pthread_create(&threads[count], NULL, func, &st[count]);
if (rc != 0)
…report pthread creation error…
count++;
}
}
This gives each thread its own struct data to work on, and the structure outlasts the pthread_join() loop.
I'm not completely that it is a good scheme to make one copy of the relevant parts of the two arrays for each thread. It's not too painful at size 2x2, but at 20x20, it begins to be painful. The threads should be told which row and column to process, and should be given pointers to the source matrices, and so on. As long as no thread modifies the source matrices, there isn't a problem reading the data.
Updated answer which replaces the previous invalid code related to pthread_join() (as noted by oftigus in a comment) with this working code. There's a reason I normally test before I post!
On the whole, casts like (void **) should be avoided in the pthread_join() loop. One correct working way to handle this is:
for (int i = 0; i < n * m; i++)
{
void *vp;
int rc = pthread_join(threads[i], &vp);
if (rc == 0 && vp != NULL)
{
rez[i] = vp;
printf("(%s) %d ", rez[i], atoi(rez[i]));
free(rez[i]);
}
}
putchar('\n');
This passes a pointer to a void * variable to pthread_join(). If it finds the information for the requested thread, then pthread_join() makes that void * variable hold the value returned by the thread function. This can then be used as shown — note the error handling (though I note that the example in the POSIX specification for pthread_join()ignores the return value from pthread_join() with a (void) cast on the result).
I don't see where you use res or C.
The result I get is:
(21) 21 (13) 13 (63) 63 (37) 37
where the value in parentheses is a string and the value outside is converted by atoi(). That looks like the correct answer for multiplying A by B (in that order).
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct data
{
int p;
int linie[20];
int coloana[20];
};
static void *func(void *args)
{
struct data *st = (struct data *)args;
int c = 0;
for (int k = 0; k < st->p; k++)
{
c += st->linie[k] * st->coloana[k];
}
char *rez = (char *)malloc(5);
sprintf(rez, "%d", c);
return rez;
}
int main(void)
{
int n = 2;
int m = 2;
int A[2][2] = {{1, 2}, {4, 5}};
int B[2][2] = {{7, 3}, {7, 5}};
char *rez[n * m];
pthread_t threads[n * m];
int count = 0;
struct data st[n * m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
st[count].p = 2;
for (int x = 0; x < st[count].p; x++)
{
st[count].linie[x] = A[i][x];
st[count].coloana[x] = B[x][j];
}
int rc = pthread_create(&threads[count], NULL, func, &st[count]);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %d for cell C[%d][%d]\n", count, i, j);
exit(1);
}
count++;
}
}
for (int i = 0; i < n * m; i++)
{
void *vp;
int rc = pthread_join(threads[i], &vp);
if (rc == 0 && vp != NULL)
{
rez[i] = vp;
printf("(%s) %d ", rez[i], atoi(rez[i]));
free(rez[i]);
}
}
putchar('\n');
return 0;
}

Inner product space of arrays with posix threads

I want to read as input a table A and B from a user , and make an inner product space from them (a1b1+a2b2+……+anbn) and save it in a local_sum and then share it to an total_sum variable. I am doing the bellow code , but there is a segment fault. For some reason table A & B can't pass to function MUL. Any help would be great, thank you!
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
int p;
int A[N],B[N];
int local_sum;
void *mul(void *arg)
{
int lines, start, end, i, j;
int id = *(int*)arg;
lines = N / p;
start = id * lines;
end = start + lines;
for (i = start; i < end; i++)
local_sum = A[i] * B[i] + local_sum;
return NULL;
}
int main (int argc, char *argv[])
{
int i;
pthread_t *tid;
if (argc != 2)
{
printf("Provide number of threads.\n");
exit(1);
}
p = atoi(argv[1]);
tid = (pthread_t *)malloc(p * sizeof(pthread_t));
if (tid == NULL)
{
printf("Could not allocate memory.\n");
exit(1);
}
printf("Give Table A\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
printf("Give Table B\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
for (i = 0; i < p; i++)
{
int *a;
a = malloc(sizeof(int));
*a = 0;
pthread_create(&tid[i], NULL, mul, a);
}
for (i = 0; i < p; i++)
pthread_join(tid[i], NULL);
printf("%d", local_sum);
return 0;
}
Let's see:
You want to have p threads, working on the vectors A and B.
You must be aware of that threads share the same memory, and might be interrupted at any time.
You've got p threads, all trying to write to one shared variable local_sum. This leads to unpredictable results since one thread overwrites the value another thread has written there before.
You can bypass this problem by ensuring exclusive access of one single thread to this variable by using a mutex or the like, or you could have one variable per thread, have each thread produce an intermediate result and after joining all threads, collapse all your intermediate results into the final one.
To do this, your main should look something like (assuming your compiler supports a recent C standard):
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
/* these are variables shared amongst all threads */
int p;
int A[N], B[N];
/* array with one slot per thread to receive the partial result of each thread */
int* partial_sum;
/* prototype of thread function, just to be independent of the place mul will be placed in the source file... */
void *mul(void *arg);
int main (int argc, char** argv)
{
pthread_t* tid;
p = atoi(argv[1]);
const size_t n_by_p = N/p;
if(n_by_p * p != N)
{
fprintf(stderr, "Number of threads must be an integral factor of N\n");
exit(EXIT_FAILURE) ;
}
tid = calloc(p, sizeof(pthread_t));
partial_sum = calloc(p, sizeof(int)) ;
printf("Give Table A\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&A[i]);
}
printf("Give Table B\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&B[i]);
}
for (size_t i =0; i < p; ++i)
{
/* clumsy way to pass a thread it's slot number, but works as a starter... */
int *a;
a = malloc(sizeof(int));
*a = i;
pthread_create(&tid[i], 0, mul, a);
}
for (size_t i = 0; i < p; ++i)
{
pthread_join(tid[i], 0);
}
free(tid);
tid = 0;
int total_sum = 0;
for (size_t i = 0; i < p; ++i)
{
total_sum += partial_sum[i] ;
}
free(partial_sum);
partial_sum = 0;
printf("%d",total_sum);
return EXIT_SUCCESS;
}
Your threaded method mul should now write to its particular partial_sum slot only :
void *mul(void *arg)
{
int slot_num = *(int*)arg;
free(arg);
arg = 0;
const size_t lines = N/p;
const size_t start = slot_num * lines;
const size_t end = start + lines;
partial_sum[slot_num] = 0;
for(size_t i = start; i < end; ++i)
{
partial_sum[slot_num] += A[i]*B[i];
}
return 0;
}
Beware: This code runs smoothly, only if N is some integral multiple of p.
If this condition is not met, due to truncation in N/p, not all elements of the vectors will be processed.
However, fixing these cases is not the core of this question IMHO.
I spared all kinds of error-checking, which you should add, should this code become part of some operational setup...
if (tid=NULL)
-->
if (tid==NULL)
and
for (i=start;i<end;i++)
I suppose we need
for (i=0;i<end-start;i++)

Function called by pthread_create breaks when a value is assigned to the struct passed to it

am brand new to C. I have a little program which is intended to solve find the dot product of a large 2d matrix with itself using pthread. Now when the function assigned to the pthread is called and the struct passed as a variable is accessed, the program breaks and stop working. I don't really know what am doing wrong. Here is the code:
This is the main function.
int main()
{
int rc;
int threadcount = 1;
char filename[100];
//patch to enable console printing in eclipse
setvbuf(stdout, NULL, _IONBF, 0);
do {
prompt_for_fileName(filename);
if (filename[0] == 'Q' || filename[0] == 'q') {
puts("Program ended");
return 0;
}
//read thread count
read_threadcount(&threadcount);
//initialize matrices
matrix_def matrix = initialize_matrix(filename);
//get the dimension of sub-matrices
int dfRow = (int) floor(matrix.NROWS / threadcount);
pthread_t threads[threadcount];
pthread_arg pthreadargs[threadcount];
for (int i = 0; i < threadcount; i++) {
int startRow = i * dfRow;
int endRow =
((i + 1) == threadcount) ?
matrix.NROWS : (startRow + dfRow) - 1; //we're subtracting one because its zero based.
//create a structure that we'll passed to the array.
pthread_arg arg = { matrix.NROWS, matrix.NCOLS, startRow, endRow,
0.0, NULL, NULL };
arg.data = matrix.data;
arg.result_set = create_result_memory(matrix.NCOLS);
fprintf(stderr, "before %p\n", arg.result_set);
//push arg into array.
pthreadargs[i] = arg;
rc = pthread_create(&threads[i], NULL, compute_dot_product,
(void *) &arg);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
puts("Completed processing.");
double totalTime = 0.0;
for (int z = 0; z < threadcount; z++) {
pthread_arg ar = pthreadargs[z];
printf("Thread %d took %g to process %d rows and %d columns.\n", z,
ar.execution_time, ar.endz - ar.start, ar.col);
totalTime += ar.execution_time;
}
printf(
"It took the total time of %g, to compute the dot product of the matrices.\n",
totalTime);
//free memory
free(matrix.data);
for (int k = 0; k < threadcount; k++) {
free(pthreadargs[k].data);
free(pthreadargs[k].result_set);
}
} while (filename[0] != 'Q' || filename[0] != 'q');
}
This is the function being called by the pthread
void * compute_dot_product(void * inputArgs) {
double startTime, endTime;
pthread_arg * args = inputArgs;
/*Compute the dimension of the result matrix*/
int col, row, start, endz;
col = args->col;
start = args->start;
endz = args->endz;
row = endz - start;
fprintf(stderr, "after %p\n", args->result_set);
//create a pointer to the two array
double **arr1 = args->data;
double **arr2 = arr1;
//begin the computation
int x;
startTime = seconds();
//calculate the dot product the two matrices.
for (x = 0; x < col; x++) {
double colProduct = 0.0;
for (int y = start; y < endz; y++) {
colProduct += arr1[y][x] * arr2[y][x];
}
//The code breaks here.
args->result_set[x] = colProduct;
}
endTime = seconds();
double diff = endTime - startTime;
args->execution_time = diff;
return (void *) 4;
}
This is my struct definitions
typedef struct
{
int NROWS; /*for m rows*/
int NCOLS; /*for n columns*/
double ** data;
} matrix_def;
typedef struct
{
double execution_time;
matrix_def matrix;
} compute_result;
typedef struct{
int row;
int col;
int start;
int endz;
double execution_time;
double **data;
double *result_set;
} pthread_arg;
Memory allocation of the 2D matrix.
/*dynamically allocate array based on the read size*/
matrix.data = (double **) malloc(sizeof(double *) * M);
if(matrix.data != NULL){
int x;
for(x = 0; x < M; x++){
matrix.data[x] = (double) malloc(sizeof(double) * N);
}
}else{
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
Initialize Matrix function
matrix_def initialize_matrix(char *argv)
{
int ret_code;
MM_typecode matcode;
FILE *f;
int M, N, nz;
int i;
matrix_def matrix;
if((f = fopen(argv, "r")) == NULL)
{
fprintf(stderr, "Reading file: '%s' failed", argv);
exit(1);
}
/*Read matrix banner*/
if(mm_read_banner(f, &matcode) != 0)
{
printf("Could not process Matrix Market banner. \n");
exit(1);
}
/*Check if the current matrix is supported.*/
if(mm_is_complex(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode))
{
printf("Sorry, this application does not support ");
printf("Market Matrix type: [%s]\n", mm_typecode_to_str(matcode));
exit(1);
}
/*find out size of the sparse matrix...*/
if((ret_code = mm_read_mtx_crd_size(f, &M, &N, &nz)) != 0)
exit(1);
/*Assign m, n sizes.*/
matrix.NROWS = M;
matrix.NCOLS = N;
/*dynamically allocate array based on the read size*/
matrix.data = (double **) malloc(sizeof(double *) * M);
if(matrix.data != NULL){
int x;
for(x = 0; x < M; x++){
matrix.data[x] = (double *) malloc(sizeof(double) * N);
}
}else{
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
/*Iterate through the created memory location and fill it with zeros*/
int a, b;
for(a = 0; a < M; a++){
for(b = 0; b < N; b++){
matrix.data[a][b] = 0;
}
}
/*Read the matrix*/
for(i = 0; i < nz; i++)
{
int I = 0, J = 0;
double val = 0;
fscanf(f, "%d %d %lg\n", &I, &J, &val);
//since the matrix market file starts off at
//1,1 we have to subtract 1 from the index
//to account for the array which starts off at
// 0,0
matrix.data[--I][--J] = val;
}
if(f != stdin)
fclose(f);
return matrix;
}
Any help will be appreciated, as am not very sure with the formula. Thanks
arg goes out of scope before the pthread is executed. Change your call to
rc = pthread_create(&threads[i], NULL, compute_dot_product, (void *) &pthreadargs[i]);
You will also need pthread_join before you exit, just in case the threads have not finished.
Edit
1) Replace your pthread_exit with
int rv;
for (i = 0; i < threadcount; ++i)
pthread_join(thread[i], &rv);
You would normally call pthread_exit inside a thread (like compute_dot_product) as an abnormal exit. This is a possible reason for your program breaking.
2) On your exit, I don't know how you have allocated your memory but this is a potential area where your code might be broken. If you have allocated your memory as
matrix.data = malloc(sizeof(double*) * matrix.NROWS);
matrix.data[0] = malloc(sizeof(double) * matrix.NROWS * matrix.NCOLS);
for (i = 1; i < matrix.NROWS; ++i)
matrix.data[i] = matrix.data[i - 1] + matrix.NCOLS;
Then you should free as
free(matrix.data[0]);
free(matrix.data);
If you have allocated each row individually, then free all the rows before freeing matrix.data.
3) Since matrix.data has been freed, pthreadargs[k].data should not be freed as it is pointing to the same area of memory that has already been freed.
The arg object defined here:
pthread_arg arg = { matrix.NROWS, matrix.NCOLS, startRow, endRow,
0.0, NULL, NULL };
goes out of scope while thread is still running. You need to prevent this from happening somehow, for example by allocating it on the heap instead.

Resources