Why do I get different values in debug mode? - c

My program supposed to calculate the matrix product (multiplication) of 2 given matrices using multithreading - each thread calculates one column.
The problem is - when I run it from the terminal, I'm getting few zeros columns. I used debugger to see where the problem is - but at the debugger it works fine every time! I can't figure out where the problem is
How is it possible that I'm getting different values when debugging vs regular execution?
I tried some "simple solutions" from online searching:
reset the linux virtual machine
reset VSCode
and i don't getting any errors or memory leaks but i have no idea what to do further
my code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/stat.h>
#include <pthread.h>
int MATRIX_DIM=3; //default
int **RESULT_MAT;
struct calcCol{
int **matA;
int **matB;
int **matC;
int dim;
int i;
};
int ijMult(int **matA, int **matB,int dim, int i, int j);
void* colMatCalc(void* s);
void printMatrix(int **mat);
void getMatrix(int **mat);
void freeMatrices(int **matA, int **matB, int **matC);
void* printThreadId(void* arg){
int i = *(int*)arg;
printf("Thread id: %d \n", i);
pthread_exit(NULL);
}
int main(){
pthread_t tid[MATRIX_DIM];
int args[MATRIX_DIM];
pthread_attr_t attr;
pthread_attr_init(&attr);
printf("Enter enter MATRIX_DIM (number between 1 and 10) \n");
scanf("%d",&MATRIX_DIM);
if(MATRIX_DIM>10 || MATRIX_DIM<1)
MATRIX_DIM=3; //default value
//memory allocation for matrices
int **matA = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) matA[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
int **matB = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) matB[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
RESULT_MAT = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) RESULT_MAT[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
struct calcCol s;
s.matA = matA;
s.matB = matB;
s.matC=RESULT_MAT;
s.dim=MATRIX_DIM;
s.i=0;
printf("Enter elements of first matrix \n");
getMatrix(matA);
printf("Enter elements of second matrix \n");
getMatrix(matB);
for(int i=0 ; i<MATRIX_DIM ; i++)
{
args[i]=i;
s.i=i;
pthread_create(&tid[i], &attr, colMatCalc, &s);
}
for(int i=0 ; i<MATRIX_DIM ; i++)
{
if(pthread_join(tid[i], NULL)!=0)
{
perror("pthread_join faild.");
exit(EXIT_FAILURE);
}
printf("Thread %d is terminated.\n", *(int*)(&args[i]));
}
printf("All threads are terminated!\n");
printf("Product of the matrices: \n");
printMatrix(RESULT_MAT);
freeMatrices(matA, matB, RESULT_MAT);
return 0;
}
//calculating (i,j) of the result matrix
int ijMult(int **matA, int **matB, int dim, int i, int j)
{
int sum = 0;
for(int k = 0 ; k < MATRIX_DIM ; k++)
sum = sum + (matA[i][k]*matB[k][j]);
return sum;
}
//calculating the 'i' column of the result matrix
void* colMatCalc(void* arg)
{
struct calcCol s = *(struct calcCol*)arg;
for(int k = 0 ; k < s.dim ; k++)
s.matC[k][s.i] = ijMult(s.matA, s.matB,s.dim, k, s.i);
return 0;
}
void printMatrix(int **mat)
{
for(int i = 0 ; i < MATRIX_DIM ; i++)
{
for(int j = 0 ; j < MATRIX_DIM ; j++)
{
printf("%d \t", mat[i][j]);
}
printf("\n");
}
}
void getMatrix(int **mat)
{
for(int i=0 ; i<MATRIX_DIM ; i++)
{
for(int j=0 ; j<MATRIX_DIM ; j++)
{
scanf("%d",&mat[i][j]);
}
}
}
void freeMatrices(int **matA, int **matB, int **matC)
{
for(int i=0 ; i < MATRIX_DIM ; i++)
{
free(matA[i]);
free(matB[i]);
free(RESULT_MAT[i]);
}
free(matA);
free(matB);
free(RESULT_MAT);
}
I know i don't need to paste the entire code, but i really don't know where is the tricky part...cause again- when i'm in debug mode it works fine.
Input: 3 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6
7 8 9 Expected output 30 36 42 66 81 96
102 126 150
Actual output: same but with zeros column instead (different columns each time)
Thank you.

The problem is with variable s which is shared across all the threads, that is
s.i=i;
When you update s in the loop, every thread will be pointing to latest contents of s.
What you can do is have different instance to each thread as below.
for(int i=0 ; i<MATRIX_DIM ; i++)
{
struct calcCol *s = malloc(sizeof(*s));
s->matA = matA;
s->matB = matB;
s->matC=RESULT_MAT;
s->dim=MATRIX_DIM;
s->i=0;
args[i]=i;
s->i=i;
pthread_create(&tid[i], &attr, colMatCalc, s);
}
With that when you update the content of *s it won't affect other thread's execution.
Make sure you free it once thread is finished its execution.

Related

Control some code to be executed once in MPI

I can't control how to make to execute some code once using mpi
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#define N 10
#define ITERS 1
// N and ITERS might be input arguments
double **A;
int times = 0;
void initialize (double **A)
{
int i,j;
for(i =0; i < N+2 ; i++){
for(j =0; j < N+2 ; j++){
if(i== 0 || j == 0 || i == (N+1) || j == (N +1) )
A[i][j] = 0.0;
else
A[i][j] = rand() % 10 + 1;
}
}
}
int main(int argc, char * argv[]){
int MyProc, size,tag=1;
char msg='A', msg_recpt;
MPI_Status status;
double **received_array;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &MyProc);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Process # %d started \n", MyProc);
MPI_Barrier(MPI_COMM_WORLD);
int i;
/******Make it once*******/
if(times == 0){
printf("One time\n");
A = malloc((N+2) * sizeof(double *));
for (i=0; i<N+2; i++) {
A[i] = malloc((N+2) * sizeof(double));
}
initialize(A);
times ++;
}
/*************/
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
I've tried with times variable as a flag but the make it once section it's executed once per process...everethig I've tried it's executed once per process ,I don't know what to try, I can't make it using the rank of teh process because I need the first procees to arrive executes the once section.

pthread_join() segfault

I made this little program to understand pthreads a bit more. I tried to compute the powers of 0-99 over 10 threads. It works fine without pthread_join or when I join only the first 4 threads. Joining anything above 4 segfaults the program. What is the reason my program segfaults when I am joining more than the first 4 threads.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#define NUM_THREADS 10
double *powr;
void *pows(void *arg){
int n = *((int*)arg)*10;
for(int i = n; i < n+10; i++){
powr[i] = pow(i, 2);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread_ID[NUM_THREADS];
void *exit_status[NUM_THREADS];
int rank[NUM_THREADS], j;
powr = (double *)malloc(NUM_THREADS*10);
for(j = 0; j < NUM_THREADS; j++){
rank[j] = j;
pthread_create(&thread_ID[j], NULL, pows, &rank[j]);
}
for(j = 0; j < NUM_THREADS; j++){
pthread_join(thread_ID[j], NULL);
}
for(j = 0; j < NUM_THREADS*10; j++){
printf("%.0lf ", powr[j]);
}
return 0;
}
after changing malloc(NUM_THREADS*10); to malloc(NUM_THREADS*10*sizeof(double)); it runs correctly.

multithreading - occasional segfault in matrix multiplication in c

I'm working on a small program of multithreaded matrix multiplication. My first job is to fill the entry of matrices with a random integer. I met some segment faults after I tried to pass a function pointer to pthread_create. And I think the problem is in function pthread_join.
But there are two issues in general.
The first one is the segment fault does not happen every time. Sometimes the code works, but most of the times it doesn't. So it really confuses me.
The other one is when the code is working, there are always several entries still not initialized, especially for matrix[0][0], it is never initialized. And I don't quite know where to debug that one.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define N 5
#define MAX 10
int A[N][N];
int B[N][N];
int C[N][N];
pthread_t pid[N][N];
typedef struct {
int row, col;
} Pos;
typedef void* (*thread_func)(void*);
void print_matrix(int M[][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%3d", M[i][j]);
if (j < N - 1) {
printf(", ");
}
}
printf("\n");
}
}
void join_threads(void) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pthread_join(pid[i][j], NULL);
}
}
}
void* fill_entry(void* arg) {
Pos* pos = (Pos*)arg;
A[pos->row][pos->col] = rand() % MAX;
B[pos->row][pos->col] = rand() % MAX;
return NULL;
}
void dispatch_jobs(thread_func job_func) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
}
}
}
int main(void) {
srand(time(NULL));
dispatch_jobs(&fill_entry);
join_threads();
printf("Matrix A:\n");
print_matrix(A);
printf("Matrix B:\n");
print_matrix(B);
return 0;
}
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
You are passing a pointer to a local variable to the threads. Once the thread tries to access the data, i.e. dereferences the pointer, the variable is long gone, reused, and contains garbage data.

Passing a parameter to a thread but get I get completely different results than anticipated

I am completely new to C, so excuse me for my lack of knowledge. I am trying to make 4 threads that will each generate a number between 100-199 200-299 300-399 and 400-499 for each of the threads respectively. However when I pass my parameter interv which is a struct type with two int values, I get something completely different on the other side. For example when I send in 100 and 199, I get 0 instead of 199 and -13216 instead of 100. I am not sure where exactly the problem is, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 4
int sum; /* global variable shared by thread(s) */
pthread_mutex_t counter_lock = PTHREAD_MUTEX_INITIALIZER;
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
typedef struct interval {
int min;
int max;
} interval;
void *runner(struct interval *param); /* threads call this function */
/*
*
*/
int main(int argc, char *argv[]) {
pthread_t workers[NUM_THREADS];
interval *interv;
interv->max = 199;
interv->min = 100;
/* create the thread */
printf("min = %d max = %d \n",interv->min,interv->max);
for (int i = 0; i < NUM_THREADS; i++) {
printf("min = %d max = %d \n",interv->min,interv->max);
pthread_create(&workers[i],NULL,runner,&interv);
interv->min += 100;
interv->max += 100;
/* wait for the thread to exit */
pthread_join(&workers[i],NULL);
}
printf("sum = %d\n",sum);
return (0);
}
/* The thread will begin control in this function */
void *runner(struct interval *param) {
int n, array[100], list_sum, counter;
printf("min = %d max = %d \n",param->min,param->max);
for (int i; i < 100; i++) {
n = rand() % (param->max + 1 - param->min) + param->min;
array[i] = n;
list_sum += n;
}
qsort(array, 100, sizeof(int), cmpfunc);
for (int i; i < 100; i++) {
counter += 1;
if (counter == 10) {
counter = 0;
}
}
pthread_mutex_lock(&counter_lock);
sum += list_sum;
pthread_mutex_unlock(&counter_lock);
pthread_exit(0);
}
UPDATED:
So I did not get the result I expected when the program compiled, so I re-wrote most of my code. Although now, again, I am getting some strange behavior and I am not sure why.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 1
#define NUM_ELEMENTS 10
//Sum computed buy the background thread
int total = 0;
int counter = 0;
struct sum_runner_struct {
int min;
int max;
int array[NUM_ELEMENTS];
int answer;
};
//Thread function to generate a sum of 0 to N
void* runner(void* arg) {
struct sum_runner_struct *arg_struct = (struct sum_runner_struct*) arg;
int n, sum;
for (int i = 0; i<NUM_ELEMENTS; i++) {
n = rand()%(arg_struct->max + 1 - arg_struct->min) + arg_struct->min;
printf("%d ",n);
arg_struct->array[i] = n;
}
printf("\n");
for (int i = 0; i<NUM_ELEMENTS; i++) {
sum = sum + arg_struct->array[i];
printf("%d ", arg_struct->array[i]);
counter += 1;
if (counter == 10) {
printf("\n");
counter = 0;
}
}
printf("Sum: %d\n",sum);
arg_struct->answer = sum;
pthread_exit(0);
}
int main(int argc, char **argv) {
int INTERVALS[4][2] = {{100,199},{200,299},{300,399},{400,499}};
struct sum_runner_struct args[NUM_THREADS];
// Launch threads
pthread_t tids[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
args[i].min = INTERVALS[i][0];
args[i].max = INTERVALS[i][1];
//Create attributes
pthread_attr_t attr;
pthread_attr_init(&attr);
//Create Thread
pthread_create(&tids[i], &attr, runner, &args[i]);
}
//Wait until thread is done its work
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(tids[i], NULL);
printf("Sum of thread %d is %d\n", i, args[i].answer);
total += args[i].answer;
}
printf("Sum is %d\n", total);
}
Before you comment on my random number generator, I know that it is not the best solution as of now, but that is not my issue. My issue is when I add the numbers in the array for a thread I get a number that is bigger by 6 integers. I am not sure why this happens.
For example when I run the program with a single thread to generate 10 elements I would get something like this:
133 143 162 129 100 108 152 156 156 119
133 143 162 129 100 108 152 156 156 119
Sum: 1364
Sum of thread 0 is 1364
Sum is 1364
RUN SUCCESSFUL (total time: 57ms)
Note that I printed the array twice hence why there are two lines of the same array. As you can see (I think I added them up right) if you add the numbers in the array you would get 1358, not 1364. I am not sure what causes this.
Okay I found the issue, I am not sure exactly why, but when I initialize
int n, sum;
for some reason sum value is initialized to 6. Can anyone explain why this happens?

Cannot loop over all the matrix elements

I am trying to create a data structure to store a matrix and write a routine to generate a square matrix of random numbers.
Here is my code. I am strangely getting only 2 float numbers as output. I am doing all this to implement strassen matrix multiplication, which is why I added rs, re, cs, ce to struct.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct _matrix {
int rs;
int re;
int cs;
int ce;
float a[100][100];
}matrix;
void display(matrix m)
{
int i, j;
for (i=m.rs ; i<=m.re ; i++) {
for (j=m.cs ; j<=m.ce ; j++)
printf("%f", m.a[i][j]);
printf("\n");
}
printf("\n");
return;
}
matrix random_matrix(int n)
{
matrix random;
random.cs = random.rs = 0;
random.rs = random.re = n -1;
int i, j;
for(i=0; i < n; i++){
for(j = 0; j < n; j++)
random.a[i][j] = rand();
}
return random;
}
int main(void)
{
matrix m1 = random_matrix(3);
matrix m2 = random_matrix(3);
display(m1);
display(m2);
return 0;
}
I think, to fit the logic, in your code, in random_matrix() function,
random.rs = random.re = n -1;
should be
random.ce = random.re = n -1;
Otherwise, in display(), for (i=m.rs ; i<=m.re ; i++) does not make sense.
That said, to see the random number generator, you can call srand(time(NULL)); in main(), before the call to the matrix generation functions.

Resources