multiplication of matrix using multi-threading

Hi, Im starting with threads and im making a program that reads from 2 files which have the colum and line and the matrix, it reads fine from the file, the problem is linking the file array to the threads function im a bit lost :)

Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

/* struct to hold data to be passed to a thread
   this shows how multiple data items can be passed to a thread */
typedef struct matrix{
    int l;
    int c;
}matrix;

int mult[2][4] = {{0, 0, 0, 0},
                  {0, 0, 0, 0}};

void error_file(FILE *f, char* nomef, char* m);
void *thread_mult_matrix(void* param);
void *open_file(char* nomef, char* m);
void print(void);
int main(int argc, char* argv[])
{
    open_file("matrix1", "r");
    open_file("matrix2", "r");
//I OPEN THE FILES BUT NO DIRECT LINK TO THE ARRAY
    int i,j;
      for(i=0;i<2;i++)
        {
            for(j=0;j<4;j++)
            {
                matrix *data = (matrix*) malloc(sizeof(matrix));
                data->l = i;
                data->c = j;

                pthread_t tid; //thread ID

                pthread_create(&tid, NULL, thread_mult_matrix, data);
                pthread_join(tid, NULL);
            }
        }
    print();
}


void *thread_mult_matrix(void* param)
{
    matrix *data = param; // cast dunno if it needs one
    int n;
    int sum=0;
    for(n=0; n < 3; n++)
    {
        sum += array1[data->l][n] * array2[n][data->c]; //ERROR HERE MAYBE MISSING A POINTER? HOW CAN I LINK IT?
    }

    mult[data->l][data->c] = sum;
    pthread_exit(0);
}


void print(void)
{
    int i,j;
     printf("RESULT\n");
        for(i=0; i < 2; i++)
        {
            for(j=0; j < 4; j++)
            {
                printf("%d ",mult[i][j]);
            }
            printf("\n");
        }
}

void error_file(FILE *f, char* nomef, char* m)
{
    char resp;

    if(f != NULL && strcmp(m, "w")==0)
    {
        printf("Ficheiro %s ja existe.\n", nomef);
        printf("Quer criar um novo(s/n)?.");
        scanf("%c", &resp);
        if(resp == 's')
        {
            f = fopen(nomef, "w");
            }else{
            exit(1);
        }
    }
    if(f == NULL && (strcmp(m, "r") == 0 || strcmp(m, "a") == 0))
    {
        printf("Ficheiro %s nao existe.\n", nomef);
        exit(2);
    }
}

void* open_file(char* nomef, char* m)
{
    FILE* f;
    int **array1;
    int e,i,j;
    int aux1[2];
    f = fopen(nomef, "r");
    error_file(f, nomef, m); //tratamento de erros
    for(e=0; e < 2; e++)
        {
            fscanf(f,"%d \n", &aux1[e]); // guarda linha e coluna
        }
    printf("aux1[%d]= %d <-----LINE\n", 0, aux1[0]);
    printf("aux1[%d]= %d <-----COLUM\n", 1, aux1[1]);

    array1 = (int**)malloc(aux1[0]*sizeof(int*));
    for(i=0; i < aux1[0]; i++){
        array1[i] = (int*)malloc(aux1[1]*sizeof(int));
        for(j=0; j < aux1[1]; j++)
        {
            fscanf(f,"%d \n", &array1[i][j]);
        }
    }
    printf("Content da %s \n", nomef);
    for(i=0; i < aux1[0]; i++)
    {
        for(j=0; j < aux1[1]; j++)
        {
            printf("%d ",array1[i][j]);
        }
        printf("\n");
    }
}

Open in new window

VasconcelosAsked:
Who is Participating?
 
phoffricConnect With a Mentor Commented:
I'm leaving now to try to take advantage of the sun before 3 days of thunderstorms hit. I'll look at your post when I get back tonight. (Hoping that the power doesn't get knocked out again!)

A quick look and I see:
1) you do not create a dynamic results array. For example, a 3x2 and a 2x9 should yield a 3x9 - so your results matrix should be 3x9 in this dynamic scenario

2) Too many threads can cause problems in performance. Try working, say, on a row times a column instead of each cell.

3) Do you really need to malloc 2*4 = 8 times for the matrix?
0
 
phoffricCommented:
The quickest way to get this to build is to move line 98 to the top of the file and then add the array2 variable there as well.

As far as the functionality goes, I suggest that you write a single threaded program first (or post it if you already have one), and then you can test the multi-threaded version against it.

I noticed you are using one tid. See http://rdsrc.us/lzPxjE for a sample program that uses two tids. I noticed that in main that you call pthread_create 8 times. I this your intent? I also noticed that you then follow each call with pthread_join. Is it your intent to create a thread and then wait for it to complete before creating the next thread?
0
 
phoffricCommented:
I noticed that you are using array2, but you never set it. It looks to me that there is another question to be asked; namely, how to get the functionality to work in a single threaded model, and then in this question, you can try to use multi-threading.
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
phoffricCommented:
Here is a POSIX thread tutorial.
     http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

Notice that in pthread1.c, there are two threads created, and after creation, the main then waits for both of them to complete.

The rest of this tutorial is also very useful.
0
 
VasconcelosAuthor Commented:
Hi and thanks for the help so far :)
To answer some of your questions:
yes i want to create a thread for each calculation i make and had them to their exact coordinates on the matrix and wait for each one to terminate.
Im fairly new to threads so im not sure if im doing it right my problem is that i cant link the arrays do the multiplication function, i have a version of this that i dont use functions and put almost all the code inside the "main" and it works and why it works? but its a bit useless has it is imo.

#include <stdio.h>

#include <stdlib.h>
#include <pthread.h>

typedef struct matrix{
    int l;
    int c;
}matrix;

int mult[2][4] = {{0, 0, 0, 0},
                  {0, 0, 0, 0}};


void *thread_mult_matrix(void* param);


int main(int argc, char* argv[])
{
   int i, j, count = 0;
   matrix *data = param; 
   int n, sum=0;
   int aux1[2];
   int aux2[2];

   FILE *fp1;
   FILE *fp2;
   int i,j,k,e,r;
   int **array1;
   int **array2;
   fp1 = fopen ("matrix1","r");
   fp2 = fopen ("matrix2","r");
   if( fp1 == NULL || fp2 == NULL )
    {
        puts ( "cannot open file" ) ;
        exit(1);
    }
    for(e=0; e < 2; e++)
        {
            fscanf(fp1,"%d \n", &aux1[e]);
        }
    for(e=0; e < 2; e++)
        {
            fscanf(fp2,"%d \n", &aux2[e]);
        }
    printf("aux1[%d]= %d <-----LINHA\n", 0, aux1[0]);
    printf("aux1[%d]= %d <-----COLUNA\n", 1, aux1[1]);
    printf("aux2[%d]= %d <-----LINHA\n", 0, aux2[0]);
    printf("aux2[%d]= %d <-----COLUNA\n", 1, aux2[1]);

    array1 = (int**)malloc(aux1[0]*sizeof(int*));
    for(i=0; i < aux1[0]; i++){
        array1[i] = (int*)malloc(aux1[1]*sizeof(int));
        for(j=0; j < aux1[1]; j++)
        {
            fscanf(fp1,"%d \n", &array1[i][j]);
        }
    }
    printf("Matrix 1\n");
    for(i=0; i < aux1[0]; i++)
    {
        for(j=0; j < aux1[1]; j++)
        {
            printf("%d ",array1[i][j]);
        }
        printf("\n");
    }
    array2 = (int**)malloc(aux2[0]*sizeof(int*));
    for(i=0; i < aux2[0]; i++){
        array2[i] = (int*)malloc(aux2[1]*sizeof(int));
        for(j=0; j < aux2[1]; j++)
        {
            fscanf(fp2,"%d \n", &array2[i][j]);
        }
    }
    printf("Matrix 2 \n");
    for(i=0; i < aux2[0]; i++)
    {
        for(j=0; j < aux2[1]; j++)
        {
            printf("%d ",array2[i][j]);
        }
        printf("\n");
    }
         for(i=0;i<2;i++)
        {
            for(j=0;j<4;j++)
            {
                matrix *data = (matrix*) malloc(sizeof(matrix));
                data->l = i; 
                data->c = j;
                
                pthread_t tid; //thread ID
            
                pthread_create(&tid, NULL, thread_mult_matrix,data);
                pthread_join(tid, NULL);
            }
        }
        printf("RESULT\n");
        for(i=0; i < 2; i++)
        {
            for(j=0; j < 4; j++)
            {
                printf("%d ",mult[i][j]);
            }
            printf("\n");
        }
}


void *thread_mult_matrix(void* param)
{
    
    for(n=0; n < 3; n++)
    {
        sum += array1[data->l][n] * array2[n][data->c];
    }
    
    mult[data->l][data->c] = sum;

    pthread_exit(0);
}

Open in new window

0
 
phoffricCommented:
>> i have a version of this that i dont use functions and put almost all the code inside the "main" and it works and why it works?
Could you check the version that works. I got compiler errors with the code in http:#35454378

I'm not sure about your comment: "why it works?" Are you saying that you wrote code, and it works, but you do not know why it works?

If so, then where are you unclear?
0
 
VasconcelosAuthor Commented:
im so sorry my mistake the code i wanted to show was this one and it works :) i insert the file opening code inside the thread function pointer and it works i want to know how can i make the open file code on a separate function and make it work.
Another question i have is if im going in the right way :)

Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

typedef struct matrix{
    int l;
    int c;
}matrix;

int mult[2][4] = {{0, 0, 0, 0},
                  {0, 0, 0, 0}};


void *thread_mult_matrix(void* parametro);

int main(int argc, char* argv[])
{
    int i, j, count = 0;
         for(i=0;i<2;i++)
        {
            for(j=0;j<4;j++)
            {
                matrix *data = (matrix*) malloc(sizeof(matrix));
                data->l = i;
                data->c = j;
                //cria thread para passar o apontador da esturura data como parametro
                pthread_t tid; //thread ID
                //cria a thread
                pthread_create(&tid, NULL, thread_mult_matrix,data);
                pthread_join(tid, NULL);
            }
        }
        printf("RESULTADO\n");
        for(i=0; i < 2; i++)
        {
            for(j=0; j < 4; j++)
            {
                printf("%d ",mult[i][j]);
            }
            printf("\n");
        }
}


void *thread_mult_matrix(void* parametro){
   matrix *data = parametro; //estrutura que contem os dados
   int n, sum=0;
   int aux1[2];
   int aux2[2];
   FILE *fp1;
   FILE *fp2;
   int i,j,k,e,r;
   int **array1;
   int **array2;
   fp1 = fopen ("matrix1","r");
   fp2 = fopen ("matrix2","r");
   if( fp1 == NULL || fp2 == NULL )
    {
        puts ( "cannot open file" ) ;
        exit(1);
    }
    for(e=0; e < 2; e++)
        {
            fscanf(fp1,"%d \n", &aux1[e]);
        }
    for(e=0; e < 2; e++)
        {
            fscanf(fp2,"%d \n", &aux2[e]);
        }
    printf("aux1[%d]= %d <-----LINHA\n", 0, aux1[0]);
    printf("aux1[%d]= %d <-----COLUNA\n", 1, aux1[1]);
    printf("aux2[%d]= %d <-----LINHA\n", 0, aux2[0]);
    printf("aux2[%d]= %d <-----COLUNA\n", 1, aux2[1]);

    array1 = (int**)malloc(aux1[0]*sizeof(int*));
    for(i=0; i < aux1[0]; i++){
        array1[i] = (int*)malloc(aux1[1]*sizeof(int));
        for(j=0; j < aux1[1]; j++)
        {
            fscanf(fp1,"%d \n", &array1[i][j]);
        }
    }
    printf("Matrix 1\n");
    for(i=0; i < aux1[0]; i++)
    {
        for(j=0; j < aux1[1]; j++)
        {
            printf("%d ",array1[i][j]);
        }
        printf("\n");
    }
    array2 = (int**)malloc(aux2[0]*sizeof(int*));
    for(i=0; i < aux2[0]; i++){
        array2[i] = (int*)malloc(aux2[1]*sizeof(int));
        for(j=0; j < aux2[1]; j++)
        {
            fscanf(fp2,"%d \n", &array2[i][j]);
        }
    }
    printf("Matrix 2 \n");
    for(i=0; i < aux2[0]; i++)
    {
        for(j=0; j < aux2[1]; j++)
        {
            printf("%d ",array2[i][j]);
        }
        printf("\n");
    }
    //linha a multiplicar pela coluna
    for(n=0; n < 3; n++)
    {
        sum += array1[data->l][n] * array2[n][data->c];
    }
    //redireccionar a soma para as suas coordenadas
    mult[data->l][data->c] = sum;

    pthread_exit(0);
    }

Open in new window

0
 
phoffricCommented:
Hi Vasconcelos,
I just saw your post. I have to go now, and have some catching up to do. But, I will try to get back to you tonight or tomorrow afternoon. Is that OK with you?
   Paul
0
 
phoffricCommented:
>> am I going in the right way.
I think you should elaborate on the requirements so that I can answer that better. Normally, we do not use multi-threading where one thread runs while all the others wait. The idea is that more than one thread can run in parallel.
0
 
VasconcelosAuthor Commented:
Its np have a good time :) what changes do i need to make so that i can make them run them in parallel?
0
 
phoffricCommented:
>> what changes do i need to make so that i can make them run them in parallel?
To give you a brief answer would lead to many problems. This is a difficult topic. So start by reading and trying out the sample programs in the above tutorial link. The ddd GUI debugger allows you to easily set breakpoints on the different threads, so start using ddd.

Here are other tutorials that I found. You should read them carefully and try all the examples to begin to understand the difficulties in writing correct multi-threaded programs:

     http://www.cs.cf.ac.uk/Dave/C/node29.html#SECTION002900000000000000000

     https://computing.llnl.gov/tutorials/pthreads/

     http://msdn.microsoft.com/en-us/magazine/cc163744.aspx

and again:
     http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html



0
 
phoffricCommented:
I forgot to include this tutorial:
      http://randu.org/tutorials/threads/

For using the ddd debugger for examining threads, read:
     http://www.gnu.org/software/ddd/manual/html_mono/ddd.html#Threads
     
If you do not have ddd, this tells you how to get it:
     http://www.gnu.org/software/ddd/#Getting
0
 
VasconcelosAuthor Commented:
thank you very much ill work right on it :)
0
 
ssnkumarCommented:
>  i want to know how can i make the open file code on a separate function and make it work.
Yes, you can do this.
You write another function for reading the files. Make array1 and array2 as global variables.
Use pthread_create() and execute this function and call pthread_join().

After this, your for() loop should execute and do the other threads.
0
 
ssnkumarCommented:
> Another question i have is if im going in the right way :)
This question is regarding the logic you are following, right?
You can find this out, without even compiling/executing your code.
Just assign some values to yourself and hand-simulate your code.
Put down every step into writing and see how the value of each variable changes.
Finally, if you are able to get the result you are looking for, then most-probably your code is working.
After this, you compile the code and remove the compilation errors.
Test the code with different values.
0
 
phoffricCommented:
Before addressing your OP question, I have comments on http:#35456155
Check that the dimensions of the two matrices are compatible for multiplication; if not give error message and exit
The mult 2d array should be dynamically created after you know the dimensions of matrix1 and matrix2.
In your consecutive threads, you are doing some things over again
   open/close files
   malloc/free memory
Steps that produce identical results should be done once in the running of your program.
Is this your goal, and is that the purpose of this question because you are having trouble doing this?
0
 
VasconcelosAuthor Commented:
yes its my goal to make it has much dinamic has i can :)
what do you think of this threads code now?
also, can i do a malloc for this "pthread_t tid[2][4]"? if yes how?
thanks in advance.
int i,j;
   pthread_t tid[2][4]; //how to replace this for a dinamic thread wich i can put any row or colum 
         for(i=0;i<2;i++)
        {
            for(j=0;j<4;j++)
            {
                matrix *data = (matrix*) malloc(sizeof(matrix));

                    if (data!=NULL) {

                        data->l = i; 
                        data->c = j;

          
                        pthread_create(&tid[i][j], NULL, thread_mult_matrix,data);

                }else{
                    free(data);
                }
            }
        }

        for(i=0; i < 2; i++)
        {
            for(j=0; j < 4; j++)
            {
                pthread_join(tid[i][j], NULL);
            }
        }

Open in new window

0
 
phoffricCommented:
Do you want to modify and re-post per suggestions?
0
 
VasconcelosAuthor Commented:
thanks :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.