views:

948

answers:

3

I'm trying to learn how to program parallel algorithms in C using POSIX threads. My environment is a Mac OS X 10.5.5 with gcc 4.

Compiling:

gcc -Wall -D_REENTRANT -lpthread source.c -o test.o

So, my problem is, if I compile this in a Ubuntu 9.04 box, it runs smoothly in thread order, on Mac looks like mutexes doesn't work and the threads don't wait to get the shared information.

Mac:

#1
#0
#2
#5
#3
#4

ubuntu

#0
#1
#2
#3
#4
#5

Any ideas?

Follow below the source code:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define NUM_THREADS 6
pthread_mutex_t mutexsum;
pthread_t threads[NUM_THREADS];
long Sum;

void *SumThreads(void *threadid){
    int tmp;
    int i,x[10],y[10];

    // Para cada x e y do vetor, jogamos o valor de i, só para meio didáticos
    for (i=0; i<10 ; i++){
     x[i] = i;
     y[i] = i;
    }


    tmp = Sum;
     for (i=0; i<10 ; i++){
         tmp += (x[i] * y[i]);
     }

       pthread_mutex_lock (&mutexsum);
       Sum += tmp;
       printf("Im thread #%ld sum until now is: %ld\n",threadid,Sum);
       pthread_mutex_unlock (&mutexsum);
       return 0;
}


int main(int argc, char *argv[]){
    int i;
    Sum = 0;

    pthread_mutex_init(&mutexsum, NULL);

    for(i=0; i<NUM_THREADS; i++){
     pthread_create(&threads[i], NULL, SumThreads, (void *)i);
    }

    pthread_exit(NULL);
}
A: 

To my recollection, the variable you have protected isn't actually being shared amongst the processes. It exists in its own context inside each of the threads. So, it's really just a matter of when each thread gets scheduled that determines what will print.

I don't think one simple mutex will allow you to guarantee correctness, if correctness is defined as printing 0, 1, 2, 3 ...

what your code is doing is creating multiple execution contexts, using the code in your sum function as its execution code. the variable you are protecting, unless declared as static, will be unique to each call of that function.

in the end, it is coincidence that you are getting one system to print out correctly, because you have no logical method of blocking threads until it is their proper turn.

San Jacinto
A: 

Hi

I don't do pthreads in C or any other language (but I do thread programming on high-performace computers) so this 'answer' might be useless to you;

-- What in your code requires the threads to pass the mutex in thread id order ? I see that the threads are created in id order, but what requires them to execute in that order /

-- If you do require your threads to execute in id order, why ? It seems a bit as if you are creating threads, then serialising them. To what end ?

-- When I program in threads and worry about execution order, I often try creating a very large number of threads and seeing what happens to the execution order.

As I say, ignore this if my lack of understanding of C and pthreads is too poor.

Regards

Mark

High Performance Mark
+4  A: 

There is nothing on your code that will make your threads running in ANY order. If in Ubuntu is running on some order, it might be because you are just lucky. Try running 1000 times in Ubuntu and see if you get the same results over and over again.

The thing is, that you can't control the way the scheduler will make your threads access the processor(s). So, when you iterate through the for loop is creating your threads, you can't assume that the first call to pthread_create will get to run first, or will get to lock the mutex you are creating first. It's up to the scheduler which it at the OS level, and you can't control it, unless you write your own kernel :-).

If you want a serial behavior why would you run your code in separate threads in the first place? If it is just for experimentation, then one solution I can think of using pthread_signal to wake a specific thread up and make it running... Then the woken up thread can wake up the second one and so on so forth.

Hope it helps.

Pablo Santa Cruz