[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

multiplication of matrix using multi-threading

Posted on 2011-04-23
19
Medium Priority
?
608 Views
Last Modified: 2012-05-11
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

0
Comment
Question by:Vasconcelos
  • 11
  • 6
  • 2
19 Comments
 
LVL 32

Expert Comment

by:phoffric
ID: 35453937
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35453990
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35454280
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:Vasconcelos
ID: 35454378
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35454664
>> 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
 

Author Comment

by:Vasconcelos
ID: 35456155
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35456204
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35456210
>> 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
 

Author Comment

by:Vasconcelos
ID: 35456381
Its np have a good time :) what changes do i need to make so that i can make them run them in parallel?
0
 
LVL 32

Expert Comment

by:phoffric
ID: 35456573
>> 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
 
LVL 32

Expert Comment

by:phoffric
ID: 35456581
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
 

Author Comment

by:Vasconcelos
ID: 35456688
thank you very much ill work right on it :)
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 35458382
>  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
 
LVL 8

Expert Comment

by:ssnkumar
ID: 35458399
> 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
 
LVL 32

Expert Comment

by:phoffric
ID: 35464679
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
 

Author Comment

by:Vasconcelos
ID: 35470804
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
 
LVL 32

Accepted Solution

by:
phoffric earned 2000 total points
ID: 35470868
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
 
LVL 32

Expert Comment

by:phoffric
ID: 35480350
Do you want to modify and re-post per suggestions?
0
 

Author Closing Comment

by:Vasconcelos
ID: 35490539
thanks :)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.
Loops Section Overview

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question