Writing parallel programs using the commonly used pattern

  • Recall: a commonly used parallel programming pattern is:

       main( )
       {
           Prepare data1;
           Spawn N "worker" threads to process data1;
           Wait for all threads to complete processing
    
           Prepare data2;
           Spawn N "worker" threads to process data2;
           Wait for all threads to complete processing
    
           ....
       }
    

  • Graphical depiction of each step:

Writing parallel programs using the commonly used pattern

  • This parallel programming pattern is created as follows:

    void *worker(int *id)  // Not syntactically correct, but easier to code...
    {
       // Use *id  as int parameter (The official way is: void * and cast)
    }
    
    int main(int argc, char *argv[])
    {
        pthread_t tid[N];
        int arg[N];
    
        /* ------------------------------------
           Create the worker thread group
           ------------------------------------ */
        for ( int i = 0; i < N; i++ )
        {
            arg[i] = i;
    
            pthread_create(&tid[i], NULL, worker, &arg[i]);
        }
    
        /* ---------------------------------------
           Wait for the worker threads to finish
           --------------------------------------- */
        for ( int i = 0; i < N; i++ )
            pthread_join(tid[i], NULL);
    }
    

Using global variables to pass input to worker threads in multi-threaded programs

  • All worker threads in a multi-threaded program must coorperate to solve the problem:

    • The job is divided among all the worker threads

    • Each worker thread works on some part/portion of the input data

  • Commonly used organization to provide input data to worker threads:

    • The input data of the job is stored in global variables

      (Because global variables are accessible by all threads)