Thread: Pthreads

  1. #1
    Registered User
    Join Date
    Dec 2012
    Posts
    1

    Pthreads

    Hello to the community!
    I have a problem about parallel C, I want to read a tga colored image, and convert it to grayscale, and subsequently, I want to convert the grayscale to a black&white.
    I have done it serially, and now I want to do this in a parallel way -with pthreads.
    I am working in a 4core laptop, I use ubuntu (through VMware) and gcc compiler.
    My code is the above:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <pthread.h>
    
    
    #define NUM_THREADS 4
    
    
    typedef struct
    {
        char  idlength;
        char  colourmaptype;
        char  datatypecode;
        short int colourmaporigin;
        short int colourmaplength;
        char  colourmapdepth;
        short int x_origin;
        short int y_origin;
        short width;
        short height;
        char  bitsperpixel;
        char  imagedescriptor;
    } HEADER;
    
    
    typedef struct
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
    } PIXEL;
    
    
    void CreateHeader(HEADER, FILE *);
    
    
    HEADER header;
    FILE *fp, *fp2;
    clock_t cl_diff[NUM_THREADS] = {0};
    
    
    void *Gray(void *id)
    {
        clock_t cl_mid1, cl_mid2;
        PIXEL pixel;
        float gray;
        int thread_id = *((int*)id);
        int i;
    printf("\n--START: THREAD %d--\n", thread_id);
    
    
        int apo = thread_id * header.width * header.height / NUM_THREADS;
        int ews = apo + header.width * header.height / NUM_THREADS;
    
    
        for (i = apo; i < ews; i++)
        {
            pixel.b = fgetc(fp);
            pixel.g = fgetc(fp);
            pixel.r = fgetc(fp);
    
    
            cl_mid1 = clock();
    
    
            gray = 0.114 * pixel.b + 0.587 * pixel.g + 0.299 * pixel.r;
    
    
            cl_mid2 = clock();
            cl_diff[thread_id] += cl_mid2 - cl_mid1;
    
    
            putc(gray,fp2);
            putc(gray,fp2);
            putc(gray,fp2);
    
    
        }
    printf("\n--END: THREAD %d--\n", thread_id);
    }
    
    
    main(int argc, char *argv[])
    {
        clock_t start = clock(), cl_totdiff;
        int i, j;
        char filename[25];
        char graystr[] = "_gray.tga";
        pthread_t thread[NUM_THREADS];
    
    
        if (argc != 2)
        {
            printf("\nGive tga image - bye--\n");
            exit(-1);
        }
    
    
        fp = fopen(argv[1],"r");
    
    
        // Header filling
        header.idlength = getc(fp);
        header.colourmaptype = getc(fp);
        header.datatypecode = getc(fp);
        fread(&header.colourmaporigin,2,1,fp);
        fread(&header.colourmaplength,2,1,fp);
        header.colourmapdepth = fgetc(fp);
        fread(&header.x_origin,2,1,fp);
        fread(&header.y_origin,2,1,fp);
        fread(&header.width,2,1,fp);
        fread(&header.height,2,1,fp);
        header.bitsperpixel = fgetc(fp);
        header.imagedescriptor = fgetc(fp);
    
    
        for (i = 0; argv[1][i] != '\0'; i++)
            filename[i] = argv[1][i];
        filename[i] = '\0';
    
    
        for (j = 0; j < 10; j++)
            filename[i-4+j] = graystr[j];
        
        fp2 = fopen(filename,"w");
    
    
        CreateHeader(header, fp2);
    
    
        for (i = 0; i < NUM_THREADS; i++)
        {
            pthread_create(&thread[i], NULL, Gray, &i);
    printf("\nthread:%d\n",i);
            //pthread_join(thread[i], NULL);
        }
    
    
        for (i = 0; i < NUM_THREADS; i++)
            pthread_join(thread[i], NULL);
    
    
        printf("\n---GRAYSCALE PIC: SUCCESS---\n");
    
    
        for (i = 0; i < NUM_THREADS; i++)
            cl_totdiff += cl_diff[i];
    
    
        printf("Time elapsed: %f sec\n", ((double)clock() - start) / CLOCKS_PER_SEC);
    
    
        fclose(fp);
        fclose(fp2);
    }
    
    
    void CreateHeader(HEADER header, FILE *ptr)
    {
        putc(0,ptr);
        putc(0,ptr);
        putc(2,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc(0,ptr);
        putc((header.width & 0x00FF),ptr);
        putc((header.width & 0xFF00) / 256,ptr);
        putc((header.height & 0x00FF),ptr);
        putc((header.height & 0xFF00) / 256,ptr);
        putc(24,ptr);
        putc(0,ptr);
    }
    I know that my problem is around pthread_join(), but I can't solve it. If I use pthread_join() immediately after pthread_create() (not a parallel way of course, but to check), I can see the threads (thread numbers: 0, 1, 2, 3) create and end one after another normally, until the picture is completed.
    But when I use the above way, with the many pthread_join() after the pthread_create(), I have problems, like thread numbers 0, 0, 1, 3, etc..

    I will deeply appreciate your help, as I have stuck in this many hours..

    -I have left the calculation of the procedure time for the time being, as I try to solve this..

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Note to mods: this is not a C programming problem. It probably belongs in a unix programming forum (although posix threads are more widely available than unix, that is where they are used most often).

    In any event.... I fail to see what the problem is, except in the OP's understanding of what is happening. The behaviour described is exactly what I would expect from the code as given.

    Using pthread_join() as you are forces the main thread to wait for the thread you've just launched. That is - roughly speaking - the purpose of pthread_join(). If pthread_join() is called immediately after creating the thread, the main thread waits for completion of each thread before continuing in the loop, so the net effect is the thread functions being completed one after the other.

    Without the calls of pthread_join(), the main() function continues in parallel with the threads, and the threads (once created) are able to preempt each other part-way through, and do so (more or less) randomly, depending on how the operating system scheduler works. There is no defined ordering of thread functions, and it is quite possible for thread B (or part of it) to be executed before any of thread A is executed, even if thread A was created first.

    If you want threads to be executed in order, you need to synchronise their execution. pthread_join() is one way, although - in your code - it is pointless as it effectively means one thread executes to completion before the next is launched. You might as wll simply call the thread functions in the specified order, and not bother with threads.

    Other means of synchronisation include use of mutexes or critical sections. Apart from creation of the mutex or critical section (which preferably occurs before the threads are created), it is also necessary to modify the thread functions to use it. Mutexes and critical sections are cooperative mechanisms - all thread functions that use a mutex have to play fair.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    The problem is that you pass the same "id" pointer to every thread (&i), and then modify the variable i while they are still running. You need to pass a different pointer to every thread, and you should not modify the pointed data until the threads have finished.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pthreads help
    By aydinh in forum C Programming
    Replies: 5
    Last Post: 03-02-2011, 09:31 AM
  2. Pthreads...
    By ropitch in forum C++ Programming
    Replies: 2
    Last Post: 07-14-2009, 05:07 AM
  3. pthreads for 64 bit m/c
    By vin_pll in forum C Programming
    Replies: 2
    Last Post: 02-22-2009, 10:25 PM
  4. C++ and pthreads ??
    By mynickmynick in forum C++ Programming
    Replies: 2
    Last Post: 08-25-2008, 04:16 AM