0

I am an experienced C programmer who has never used threads or parallelism before. I've been reading about it, but I do not see an example of what I want.

I use the gcc C compiler on Mac and linux. I want to replace an important procedure X in my system with a new procedure X2 that will start up two methods, as two threads to be run on two different processors whenever the machine has multiple CPUs (most do these days).

These two methods may share a few global variables, but they will not write to any memory locations other than their own stacks. They will each call many other procedures in the system. I do not envision any other parallel processing.

As soon as either thread finishes, that's it! That's the answer. X2 should immediately kill the other thread and return the answer to whoever called X2.

Maybe I'm naive but I would think this is a well known use of threads. Example code please!

rfermat
  • 1
  • 2
  • 1
    'I would think this is a well known use of threads' - not really, no. Two threads are running towards a point where either could produce an acceptable result. Seems to me that one thread is redundant? Can you suggest a use-case? – Martin James Feb 10 '14 at 21:45
  • @rfermat *"X2 should immediately kill the other thread."* It isn't a good idea. Create a termination policy instead and make sure that your threads obey to these rules. See [C++ kill method without constantly checking flags](http://stackoverflow.com/a/12942324/341970) or [Cancelling a thread using pthread_cancel : good practice or bad](http://stackoverflow.com/q/4760687/341970) – Ali Feb 10 '14 at 22:14
  • Read a [pthread tutorial](https://computing.llnl.gov/tutorials/pthreads/); you'll need some synchronization... – Basile Starynkevitch Feb 10 '14 at 23:14
  • 1
    Why not just let the other thread finish? Are these super long computations where one thread may produce the result much faster than the other and you don't want to waste the other threads cycles? How often do you anticipate doing this "divide and conquer" search for a solution? Those types of details would probably help tune the answers. Because... it depends :) – Travis Griggs Feb 10 '14 at 23:17
  • > Are these super long computations where one thread may produce the result much faster than the other... Exactly. If you want to know, I am computing the GCD of large sparse multivariate polynomials. I have often seen one method finish in, say, two seconds, while a more reliable method takes 3 minutes, and the "old standby" takes 3 hours. However, on other problems the first method fails completely. – rfermat Feb 11 '14 at 18:33

1 Answers1

0

I propose to try the following program. It uses two Linux processes to run two procedures, created by a parent process. As soon as one child finishes, the parent gets notified and terminates the other. Studying the documentation for the system calls appearing in the include section is of course necessary to understand the code.

// fork
#include <unistd.h>

// wait, kill
#include <sys/types.h>

// wait
#include <sys/wait.h>

// kill
#include <signal.h>

// exit
#include <stdlib.h>

//printf
#include <stdio.h>

void proc( int id)
{
  int seed= id;
  int count= rand_r( &seed) % 10;
  printf( "\nprocess[%d]: taking %d steps.", id, count);
  int i;
  for ( i= 1; i <= count; ++i) {
    printf( "\nprocess[%d]: step #%d", id, i);
    sleep( 1);
  }
  printf( "\nprocess[%d]:\tfinished.", id);
  exit( 1);
}

int main( int argc, char* argv[])
{
  // create 1st child process
  pid_t p1= fork();
  if ( 0 == p1)
    proc( 1); // child does not return

  // create 2nd child process
  pid_t p2= fork();
  if ( 0 == p2)
    proc( 2); // child does not return

  // this is the parent process
  // wait for a child to terminate
  pid_t p_terminated= wait( NULL); 

  // declare result
  // terminate the other child
  if ( p1 == p_terminated) {
    puts( "\nparent:  \tprocess[1] finished first.");
    kill( p2, SIGKILL);
  }

  if ( p2 == p_terminated) {
    puts( "\nparent:  \tprocess[2] finished first.");
    kill( p1, SIGKILL);
  }
}

On my machine, the program produces the following output:

process[1]: taking 3 steps.

process[2]: taking 7 steps.
process[1]: step #1
process[2]: step #1
process[1]: step #2
process[2]: step #2
process[1]: step #3
process[2]: step #3
process[1]:     finished.
parent:         process[1] finished first.

It is possible for the two processes to finish at the same time so that they both print their "finished" message, but even in this case the parent declares one of them to be the first, and terminates the other.

xxa
  • 1,258
  • 9
  • 20