[gambit-list] Running times: real vs. CPU

Taylor Venable taylor at metasyntax.net
Sun Apr 26 16:34:03 EDT 2009


On Sun, Apr 26, 2009 at 01:05:31PM -0400, Marc Feeley wrote:
>
> On 26-Apr-09, at 12:09 PM, Taylor Venable wrote:
>
>> On Sun, Apr 26, 2009 at 10:10:39AM -0400, Marc Feeley wrote:
>>> This sounds like more than one UNIX process is running.  Can you try
>>> running "top" while you execute ./a.out ?
>>
>> First of all, I'm on a system that looks like it has two CPUs (I have
>> one of those Pentium 4 processors with hyper-threading).
>>
>> Looking at `top` and comparing the three aforementioned Scheme
>> implementations, I see some interesting results: whereas Chicken and
>> MzScheme both stay in the process running state (onproc), Gambit
>> frequently does a nanosleep which forces it to go into the
>> ready-to-run state (run) before it can execute again.  The Chicken and
>> MzScheme impls will use the CPU that they're running on 100% but it's
>> about 40% - 60% idle when running the Gambit version.
>
> Strange indeed!  Is your program calling thread-sleep! or process- 
> status?  I don't see why it would call nanosleep otherwise.  Actually  
> can you send me your program?

Sure.  Attached is compiled.scm which uses C code for an intensive
part; you can also comment this out and replace it with the
pure-Scheme version.  Both methods are shown in the timings below.

> Please let me know if that solves the problem.  It would be interesting 
> to know if this problem also occurs on other UNIX flavors, or if it is 
> specific to Linux (which I assume you are using).  Which kernel is this 
> on?

UNDEF-ing that definitely improved things.  Here are some new timings:

When I do `gsc -link` and compiled with `gcc -O2` I get:

    (sum-of-squares written in C)

    real    0m26.889s
    user    0m19.580s
    sys     0m7.290s

When I do plain `gsc` and use `gsi 092.o1` I get:

    (sum-of-squares written in C)

    real    0m25.510s
    user    0m18.130s
    sys     0m7.360s

When I do plain `gsc` and use `gsi 092.o2` I get:

    (using pure-Scheme sum-of-squares)

    real    0m50.049s
    user    0m49.600s
    sys     0m0.430s

So putting the UNDEF in place makes it run onproc nearly constantly
and reduces the wall-clock run time to the expected amounts.  Now,
another thing I wonder about is whether the system time should be that
high with the code that uses a C implementation of sum-of-squares.  Is
that the result of translating data between Scheme and C types?

The OS I'm running is OpenBSD 4.5 on x86 (P4 3.0GHz w/ HT) running the
bsd.mp kernel to utilize both "CPUs" and 1024MB RAM.

At the risk of saying too much at once, I also receive this message
during the configure step:

    checking sys/sysctl.h usability... no
    checking sys/sysctl.h presence... yes
    configure: WARNING: sys/sysctl.h: present but cannot be compiled
    configure: WARNING: sys/sysctl.h:     check for missing prerequisite headers?
    configure: WARNING: sys/sysctl.h: see the Autoconf documentation
    configure: WARNING: sys/sysctl.h:     section "Present But Cannot Be Compiled"
    configure: WARNING: sys/sysctl.h: proceeding with the preprocessor's result
    configure: WARNING: sys/sysctl.h: in the future, the compiler will take precedence
    configure: WARNING:     ## -------------------------------------- ##
    configure: WARNING:     ## Report this to gambit at iro.umontreal.ca ##
    configure: WARNING:     ## -------------------------------------- ##
    checking for sys/sysctl.h... yes

Not sure if that has any bearing on this problem whatsoever.  At least
I can say with confidence that not using nanosleep seems to have
improved performance considerably in this situation.  I have no other
systems here at home to test this on, but I can test my Ubuntu x86_64
box at work tomorrow if you like.

Thanks,

-- 
Taylor Christopher Venable
http://real.metasyntax.net:2357/
-------------- next part --------------
;; Writing this in C roughly doubles the speed of Gambit's code.

(c-declare #<<c-declare-end
int sum_of_squares(char *s) {
    int sum = 0;
    int x = 0;
    while (*s) {
        x = (int)(*s) - (int)'0';
        sum += x * x;
        s++;
    }
    return sum;
}
c-declare-end
)

(define c-sum-of-squares (c-lambda (char-string) int "sum_of_squares"))
(define sum-of-squares
  (lambda (n)
    (c-sum-of-squares (number->string n))))

; (define sum-of-squares
;   (lambda (n)
;     (apply + (map (lambda (x) (* x x)) (map (lambda (c) (- (char->integer c) (char->integer #\0))) (string->list (number->string n)))))))

(define convergence
  (lambda (n)
    (if (or (= n 1) (= n 89)) n
      (convergence (sum-of-squares n)))))

(define solution
  (lambda ()
    (let* ((maximum (sum-of-squares 9999999))
           (table (make-vector (+ maximum 1) #f))
           (ones 1)
           (eighty-nines 1))
      (vector-set! table 1 1)
      (vector-set! table 89 89)
      (let counter ((i 1))
        (if (> i 9999999)
          (begin (newline) (display "SOLUTION = ") (display eighty-nines) (newline))
          (begin
            (let reducer ((n i))
              (if (> n maximum)
                (reducer (sum-of-squares n))
                (begin
                  (if (not (vector-ref table n))
                    (vector-set! table n (convergence n))
                    #f)
                  (cond ((= (vector-ref table n) 1)
                         (set! ones (+ ones 1)))
                        ((= (vector-ref table n) 89)
                         (set! eighty-nines (+ eighty-nines 1)))
                        (else (error "internal inconsistency discovered"))))))
            (counter (+ i 1))))))))

(solution)


More information about the Gambit-list mailing list