unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Linas Vepstas <linasvepstas@gmail.com>
To: Matt Wette <matt.wette@gmail.com>
Cc: Guile User <guile-user@gnu.org>
Subject: Re: Pure (side-effect-free) calls into c/c++?
Date: Sat, 11 Jan 2020 20:12:27 -0600	[thread overview]
Message-ID: <CAHrUA35Jy7p=VB4UZewBWn-sNgOzsKy4_6CS1khVhfawLj0oAg@mail.gmail.com> (raw)
In-Reply-To: <CAHrUA35zwsDRbSEvsWABNj-DfGJpEpk=u-ELp-Rd_d6Qj91RGw@mail.gmail.com>

To answer my own question, it appears doable with a very simply macro, then:

(define (bar x)
   (format #t "Called bar with ~A\n" x)
   (+ x 1))

(define (memoize FUNC)
"
  memoize a function FUNC which takes a single int as argument
"
   (define cache (make-hash-table))
   (define (int-hash INT SZ) (modulo INT SZ))
   (define (int-assoc INT ILIST)
      (find (lambda (pr) (equal? INT (car pr))) ILIST))

   (lambda (ITEM)
      (define val (hashx-ref int-hash int-assoc cache ITEM))
      (if val val
         (let ((fv (FUNC ITEM)))
            (hashx-set! int-hash int-assoc cache ITEM fv)
            fv)))
)

(define bar-memo (memoize bar))

(define-syntax foo
   (syntax-rules ()
      ((foo exp)
         (if (symbol? (quote exp))
            (begin (display "its a symb\n") (bar exp))
            (begin (display "no its not\n") (bar-memo exp))))))

scheme@(guile-user)> (define x 66)
scheme@(guile-user)> (foo x)
its a symb
Called bar with 66
$1 = 67
scheme@(guile-user)> (foo 42)
no its not
Called bar with 42
$2 = 43
scheme@(guile-user)> (foo 42)
no its not
$3 = 43
scheme@(guile-user)> (foo 42)
no its not
$4 = 43
scheme@(guile-user)> (foo 42)
no its not
$5 = 43
scheme@(guile-user)> (foo x)
its a symb
Called bar with 66
$6 = 67
scheme@(guile-user)> (foo 68)
no its not
Called bar with 68
$7 = 69
scheme@(guile-user)> (foo 68)
no its not
$8 = 69

So that works -- I can now memoize all constants, can pass all variables on
to the c++ function.

Now if I could just memoize-in-place, without the hash table ...

--linas

On Sat, Jan 11, 2020 at 12:52 PM Linas Vepstas <linasvepstas@gmail.com>
wrote:

> Or, thinking aloud a bit: boxes and symbols....
>
> So, for example, if I was able to tell apart calls (f 42) from calls (f x)
> where x is a "symbol" (or "variable", *see below*) referencing an integer,
> then, for the former case, I could create a new symbol (in guile) and
> attach it to a box, fill that box with whatever (f 42) would have returned.
> Thence-forward, any call site in the guile code that had (f 42) in it would
> get replaced by the symbol (or the unboxed value)...
>
> At the moment, I don't know how to tell apart 42, the literal number, from
> x, a symbol that references a number. (Somehow, I can't make symbol? work
> ...)  I also don't know how to "edit" the call site (the cell, the box?)
> that has (f 42) as the call-target, and replace it by a constant (or a
> boxed constant).
>
> But my naive thinking fails:
> (define x 0)
> (symbol? x)  => #f
> (variable? x) => #f
>
> So I guess that x is not a symbol, from the guile point of view!?  This is
> .. confusing. What is x, then, if not a symbol?
>
> (define (foo x)  (format #t "its ~A ~A\n" (symbol? x) (variable? x)) (+ x
> 1))
> (foo 42)
> its #f #f
> (define y 66)
> (foo y)
> its #f #f
>
> How can I tell apart "42" from "y"  ?
>
> -- Linas
>
>
>
> On Sat, Jan 11, 2020 at 12:11 PM Linas Vepstas <linasvepstas@gmail.com>
> wrote:
>
>> Hmm Thanks.  Perhaps I should have been more clear.  I'm talking about a
>> handful of values that behave like constants, and NOT about memoization.
>>
>> So here's a bit more detail. The only thing the C++ code is doing is
>> stuffing the values into a giant hash table... in C++. So its already very
>> fast. The return value is a pointer into that hash table.  Replicating that
>> hash table a second time, in guile is ... well ... it has tens/hundreds of
>> millions of entries, it would blow out RAM.  (And the other functions,
>> those that are actually CPU-intensive, already got the Grand Wazoo
>> treatment for memization; some in guile, some in C++)
>>
>> For this particular issue, I'm thinking I need to understand macros,
>> somehow.  The point being that there is just a tiny handful of values --
>> some dozens, maybe hundreds, that some human has written into the code, and
>> are being treated as if they were literal constants (because, in the C++
>> code, they *are* constants -- they're really just fixed entries in a symbol
>> table) and so I want to automatically replace these by the actual constant
>> value (the location in the c++ table).  To recap:  a macro that would
>> convert
>>
>> (define (foo x)   (g  (f 42) (f x) (f 43))
>>
>> into
>>
>> (define c42 (f 42))
>> (define c43 (f 43))
>> (define (foo x) (g c42 (f x) c43))
>>
>> so that guild can treat c42 and c43 as constants (boxes, I guess).
>>
>> -- Linas
>>
>>
>> On Sat, Jan 11, 2020 at 8:39 AM Matt Wette <matt.wette@gmail.com> wrote:
>>
>>> On 1/10/20 2:36 PM, Linas Vepstas wrote:
>>> > So, I've got lots of C code wrapped up in guile, and I'd like to
>>> declare
>>> > many of these functions to be pure functions, side-effect-free, thus
>>> > hopefully garnering some optimizations.  Is this possible? How would I
>>> do
>>> > it? A cursory google-search reveals no clues.
>>> >
>>> > To recap, I've got functions f and g that call into c++, but are pure
>>> (i.e.
>>> > always return the same value for the same arguments).   I've got
>>> > user-written code that looks like this:
>>> >
>>> > (define (foo x)
>>> >      (g  (f 42) (f x) (f 43))
>>> >
>>> > and from what I can tell, `f` is getting called three times whenever
>>> the
>>> > user calls `foo`. I could tell the user to re-write their code to
>>> cache,
>>> > manually: viz:
>>> >
>>> > (define c42 (f 42))
>>> > (define c43 (f 43))
>>> > (define (foo x) (g c42 (f x) c43))
>>> >
>>> > but asking the users to do this is .. cumbersome.  And barely worth
>>> it: `f`
>>> > takes under maybe 10 microseconds to run; so most simple-minded caching
>>> > stunts don't pay off. But since `foo` is called millions/billions of
>>> times,
>>> > I'm motivated to find something spiffy.
>>> >
>>> > Ideas? suggestions?
>>> >
>>> > -- Linas
>>>
>>> read this: http://community.schemewiki.org/?memoization
>>> and look at https://docs.racket-lang.org/memoize/index.html
>>>
>>>
>>>
>>>
>>
>> --
>> cassette tapes - analog TV - film cameras - you
>>
>
>
> --
> cassette tapes - analog TV - film cameras - you
>


-- 
cassette tapes - analog TV - film cameras - you


  parent reply	other threads:[~2020-01-12  2:12 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-10 22:36 Pure (side-effect-free) calls into c/c++? Linas Vepstas
2020-01-11 14:13 ` Zelphir Kaltstahl
2020-01-11 14:38 ` Matt Wette
2020-01-11 18:11   ` Linas Vepstas
2020-01-11 18:52     ` Linas Vepstas
2020-01-11 21:56       ` Taylan Kammer
2020-01-12  2:15         ` Linas Vepstas
2020-01-12  4:12         ` Linas Vepstas
2020-01-12  2:12       ` Linas Vepstas [this message]
2020-01-12  3:21         ` Taylan Kammer
2020-01-12  4:32           ` Linas Vepstas
2020-01-12  5:52             ` Linas Vepstas
2020-01-11 17:40 ` Linus Björnstam
2020-01-12  3:03   ` Christopher Lam
2020-01-12 10:35     ` Linus Björnstam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAHrUA35Jy7p=VB4UZewBWn-sNgOzsKy4_6CS1khVhfawLj0oAg@mail.gmail.com' \
    --to=linasvepstas@gmail.com \
    --cc=guile-user@gnu.org \
    --cc=matt.wette@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).