I am trying to run a program I have written for multiplying to square NxN matrices. However, I am getting a segmentation fault error. I have working code for the program without threading. But I have been unsuccessful in adapting my code for multiple threads.
I am attempting to run the code on a raspberry pi 4. The debugger states that the following line is where I receive the error signal SIGSEGV:
args.A[i][j] = rand() % 100;
I have tried putting printf statements around the sections of code where I allocate memory, but they were never run, so I am assuming that seg faults happen before any of the code is actually ran. I did some research on the internet in regards to solving seg faults, and that is when I tried using the debugger, but I do not understand why it is having a problem with setting the matrix elements. Especially since my previous unthreaded program has the same line of code and runs without any errors. Feedback would be greatly appreciated. The following is my code:
/* Program must be passed exactly one integer that satisfies the following condition:
* N % n = 0, where N is the square matrices' dimensions and n is the number of threads.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define N 2000
typedef struct __myarg_t
{
FILE *Aptr, *Bptr, *Cptr; // Files containing the matrices
int **A, **B, **C, **T; // Matrices A , B, resultant and transpose of B
int rows; // Number of rows each thread computes
int cur; // Current thread number
} myarg_t;
void *mythread(void *arg)
{
myarg_t *m = (myarg_t *) arg;
int start = m->cur * m->rows;
int end = start m->rows;
// Matrix Multiplication for rows start:(end - 1)
for (int i = start; i < end; i )
{
for (int j = start; j < end; j )
{
int num = 0;
for (int k = 0; k < N; k )
{
num = m->A[i][k] * m->T[j][k];
}
m->C[i][j] = num;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "usage: main-first <#ofthreads>\n");
exit(1);
}
pthread_t *thread;
clock_t tic, toc;
myarg_t args;
int rc, n;
args.cur = 0;
args.rows = N/n;
n = atoi(argv[1]);
args.Aptr = fopen("A_multi.txt", "w");
args.Bptr = fopen("B_multi.txt", "w");
args.Cptr = fopen("C_multi.txt", "w");
args.A = (int**)malloc(N * sizeof(int*));
args.B = (int**)malloc(N * sizeof(int*));
args.C = (int**)malloc(N * sizeof(int*));
args.T = (int**)malloc(N * sizeof(int*));
thread = (pthread_t *)malloc(n * sizeof(pthread_t));
// Dynamically allocate memory for 2D Array
for (int i = 0; i < N; i )
{
args.A[i] = (int*)malloc(N * sizeof(int*));
args.B[i] = (int*)malloc(N * sizeof(int*));
args.C[i] = (int*)malloc(N * sizeof(int*));
args.T[i] = (int*)malloc(N * sizeof(int*));
}
// Assign values to the elements of the Matrices
for (int i = 0; i < N; i )
{
for (int j = 0; j < N; i )
{
args.A[i][j] = rand() % 100;
args.B[i][j] = rand() % 100;
args.T[j][i] = args.B[i][j];
}
}
tic = clock();
// Create threads
for (int i = 0; i < n; i )
{
rc = pthread_create(&thread[i], NULL, mythread, &args);
if (rc != 0)
{
printf("pthread_create failed with thread %d.\n", i);
exit(1);
}
}
// Wait for threads to complete
for (int i = 0; i < n; i )
{
rc = pthread_join(thread[i], NULL);
if (rc != 0)
{
printf("ptphread_join failed with thread %d.\n", i);
exit(1);
}
}
toc = clock();
printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
// Write matrices to their output files
for (int i = 0; i < N; i )
{
for (int j = 0; j < N; j )
{
fprintf(args.Aptr, "%d ", args.A[i][j]);
fprintf(args.Bptr, "%d ", args.B[i][j]);
fprintf(args.Cptr, "%d ", args.C[i][j]);
}
fprintf(args.Aptr, "\n");
fprintf(args.Bptr, "\n");
fprintf(args.Cptr, "\n");
}
// Deallocate memory
for (int i = 0; i < N; i )
{
free(args.A[i]);
free(args.B[i]);
free(args.C[i]);
free(args.T[i]);
}
free(args.A);
free(args.B);
free(args.C);
free(args.T);
fclose(args.Aptr);
fclose(args.Bptr);
fclose(args.Cptr);
return 0;
}
CodePudding user response:
- Change:
int rc, n;
...
args.rows = N/n;
n = atoi(argv[1]);
to:
int rc;
...
int n = atoi(argv[1]);
if(!n) {
// atoi() will return for "0" or error
}
args.rows = N/n;
- The 2nd loop after the "Assign values" comment probably increments the wrong variable
i
but should bej
. Otherwisei
will be2 * (N-1)
which will overflow the arraysA
,B
andT
which are of hasN
elements. This will cause your segfault.