[gambit-list] Native threading with C++?

Marc Feeley feeley at iro.umontreal.ca
Fri Apr 20 19:48:37 EDT 2012


On 2012-03-28, at 9:26 AM, Marc Feeley wrote:

> On 2012-03-28, at 8:59 AM, Mikael wrote:
> 
>> Dear Marc, I'm curious,
>> 
>> Den 22 mars 2012 14:46 skrev Marc Feeley <feeley at iro.umontreal.ca>:
>> 
>> That's not currently possible because the Scheme global variables, and some global state of the Gambit VM, are implemented using global C/C++ structures.  What is needed (and something that is on my TODO) is to allow instances of this state to be created dynamically (essentially a constructor for the Gambit VM).  That way several instances of Gambit can coexist in the same OS process.
>> 
>> Unfortunately, this will slow down accesses to global variables, because an indirection will be needed.
>> 
>> So with this several-gambit-vm:s-coexisting-in-the-same-os-process option, each read and write to a global var will require one more indirection and that's it?
> 
> The "indirection" might be more than a pointer indirection.  The point is that each instance of the VM will have its own set of global variables.  I think it can be implemented with a single indirection by declaring that all the VMs have the same set of global variables (but each instance of a global variable has its own value).  But I haven't implemented this yet.
> 
>> Does access to Gambit runtime procedures like |list| and |open-string| qualify as this?
> 
> Yes.  Even if it is very likely that all the instances contain the same value.
> 
>> You mean one indirection i.e. just following one pointer once right? If so I suppose this gives a max approx 0.5% performance decrease for typical code - if so, for when this functionality is needed, it's really worth it.
> 
> Only by benchmarking this will I be able to tell if it is 0.5% or 5%.  It could be 50% for some programs constantly accessing global variables.

I now have some data.  For an experiment, I have modified gambit.h and a few runtime files to allow multiple instances of global variables.  In the current Gambit, a Scheme global variable is basically a C global variable.  In my experiment, each Scheme global variable is assigned an index which is used to access an array of global variables within the "processor state" structure (which can be instantiated multiple times).  The array of global variables is either "inline", at the end of the processor state structure, or is accessed using a pointer in the processor state structure (which means there is an extra level of indirection, but it makes it easier to grow the array when needed).

I compiled with each implementation of the global variables this program

(declare
 (standard-bindings)
 (extended-bindings)
 (fixnum)
 (not safe)
)

(define res 0)

(define (fib n)
  (if (fx< n 2)
      (set! res n)
      (begin
        (fib (fx- n 1))
        (let ((tmp res))
          (fib (fx- n 2))
          (set! res (+ res tmp))))))

(time (fib 40))

which is good-old fibonacci, but written in a style which accesses global variables frequently.  I also measured the execution of a more realistic large program, the Gambit compiler itself compiling lib/_io.scm, with each global variable implementation method.

The execution time in seconds (and the relative time) are

                                         fib          compiler
 standard Gambit                    2.473  (1.00)    5.393 (1.00)
 inline array of global vars        2.680  (1.08)    5.580 (1.03)
 pointer to array of global vars    2.764  (1.12)    5.574 (1.03)

So the overhead of supporting multiple instances of the Gambit VM is between 8% and 12% for the version of fib which accesses global variables frequently, and is 3% for the Gambit compiler.

The overhead seems to be acceptably low, but for some programs accessing global variables frequently it could be noticeable (when accessing global variables even more frequently than in the above program).

Marc




More information about the Gambit-list mailing list