Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] native threads not parallel?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Markus Mottl <mottl@m...>
Subject: Re: [Caml-list] native threads not parallel?
On Fri, 15 Jun 2001, Markus Mottl wrote:
> I have just been told that things work smoothly with dual-processor
> machines under Linux, and it also turned out due to more experimentation
> that the behaviour of native threads under Solaris is comparable to
> a lottery: when running very long, it seems that multiple threads are
> used. Sometimes. But sometimes you can also get bus errors. It's really
> unpredictable. Better don't bother with native threads under Solaris...

I couldn't resist and have done another test now. First, I have made
sure that multiple threads work under C. As Xavier has pointed out, this
requires setting the concurrency level to more than the default of 1.
Works fine (= in parallel).

Then I have written a small test program that tries to do the same under
OCaml - but no success...

Here are the the timings achieved by calling C via OCaml:

  Running sequentially:
  Wall clock time: 6.598713

  Running in parallel:
  Wall clock time: 6.601169


Here are the the timings achieved by using C only (clearly runs faster
with threads):

  Running sequentially
  Wall clock time: 6.995337

  Running in parallel
  Wall clock time: 3.910411

The only thing I can imagine is that OCaml somehow changes
scheduling so that the threads cannot run in parallel anymore, even if
"enter_blocking_section" is used. Is this possible? Or am I just making
some stupid mistake?

Regards,
Markus Mottl

P.S.:

The files I used in the test:

The C-only version:
---------------------------------------------------------------------------
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <pthread.h>

#define NUM_THREADS 2

double gtimeofday () {
  struct timeval t;
  gettimeofday(&t, NULL);
  return (t.tv_sec + t.tv_usec/1000000.0);
}

void init() {
  thr_setconcurrency(sysconf(_SC_NPROCESSORS_ONLN));
}

void calc_seq() {
  int i;
  for(i=0; i<=50000000; i++);
}

void * calc_par(void *threadid) {
  int i;
  for(i=0; i<=50000000; i++);
  pthread_exit(NULL);
}

void seq () {
  double t1, t2;

  printf("Running sequentially\n");

  t1 = gtimeofday();
    calc_seq(); calc_seq();
  t2 = gtimeofday();

  printf("Wall clock time: %f\n", (t2 - t1));
}

void par () {
  double t1, t2;
  pthread_t tids[NUM_THREADS];
  int rc, t, status;

  printf("Running in parallel\n");

  t1 = gtimeofday();
    for (t=0; t<NUM_THREADS; t++) {
      rc = pthread_create(&tids[t], NULL, calc_par, (void *) t);

      if (rc) {
        printf("pthread_create failed: return code: %d\n", rc);
        exit(-1);
      }
    }

    for (t=0; t<NUM_THREADS; t++) {
      rc = pthread_join(tids[t], (void **) &status);

      if (rc) {
        printf("pthread_join failed: return code: %d\n", rc);
        exit(-1);
      }
    }
  t2 = gtimeofday();

  printf("Wall clock time: %f\n", (t2 - t1));
}

int main(int argc) {
  init ();
  seq (); printf ("\n"); par ();
  pthread_exit(NULL);
}
---------------------------------------------------------------------------

The C-implementation for OCaml:
---------------------------------------------------------------------------
#include <stdio.h>
#include <pthread.h>

#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/memory.h>
#include <caml/fail.h>
#include <caml/callback.h>

value test_init () {
  thr_setconcurrency(sysconf(_SC_NPROCESSORS_ONLN));
  return Val_unit;
}

value test_calc () {
  int i;

  enter_blocking_section();

    for (i=0; i<50000000; i++);

  leave_blocking_section();

  return Val_unit;
}
---------------------------------------------------------------------------

The OCaml-file to be used with the C-file right above:
---------------------------------------------------------------------------
open Printf
open Unix

external init : unit -> unit = "test_init" "noalloc"
external calc : unit -> unit = "test_calc" "noalloc"

let _ = init ()

let seq () =
  printf "Running sequentially:\n";

  let t1 = gettimeofday () in
    calc (); calc ();
  let t2 = gettimeofday () in

  printf "Wall clock time: %f\n" (t2 -. t1)

let par () =
  printf "Running in parallel:\n";

  let t1 = gettimeofday () in
    let tids = List.map (Thread.create calc) [(); ()] in
    List.iter Thread.join tids;
  let t2 = gettimeofday () in

  printf "Wall clock time: %f\n" (t2 -. t1)

let _ = seq (); print_newline (); par ()
---------------------------------------------------------------------------

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr