From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Linas Vepstas Newsgroups: gmane.lisp.guile.user Subject: Re: Pure (side-effect-free) calls into c/c++? Date: Sat, 11 Jan 2020 20:12:27 -0600 Message-ID: References: Reply-To: linasvepstas@gmail.com Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="186330"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Guile User To: Matt Wette Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Sun Jan 12 03:15:16 2020 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iqSkY-000PuE-Sc for guile-user@m.gmane-mx.org; Sun, 12 Jan 2020 03:13:11 +0100 Original-Received: from localhost ([::1]:34526 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iqSkX-000869-Aw for guile-user@m.gmane-mx.org; Sat, 11 Jan 2020 21:13:09 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:48225) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iqSk9-00085q-Le for guile-user@gnu.org; Sat, 11 Jan 2020 21:12:47 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iqSk7-0006SB-E3 for guile-user@gnu.org; Sat, 11 Jan 2020 21:12:45 -0500 Original-Received: from mail-lj1-x234.google.com ([2a00:1450:4864:20::234]:44016) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iqSk6-0006Mu-S6 for guile-user@gnu.org; Sat, 11 Jan 2020 21:12:43 -0500 Original-Received: by mail-lj1-x234.google.com with SMTP id a13so6188473ljm.10 for ; Sat, 11 Jan 2020 18:12:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:reply-to:from:date:message-id :subject:to:cc; bh=xGEppKhiZOzCOuYbJTTu+xSPBFZdqM0PDgB12krbqL4=; b=inWv1YshZftpOg5cPYBu7SG6G6Ouzkbgy467syrsHnZl0EnJyPPvE1tZd5tys2fITf p2VAHUQc+3lc6h2JzN9Q/uPLEJi2PDn9KEKmyUckYBHh/kuiiVWfI4M2Y+RJmdrkuEvx 91pjrEnrXhv5sC5V9+Nod0DBqRbTHt0Xpo/eYrXHPonNY/sdug0T/3MbqWkYXN+9EvJK fRN9bepUmc39T+pmjiwm/e0Pg5rGgM8Xvh3rQpOEg6uDp9ypU2bcQvbtpeGP4T2JTFdW 0pDcrJr2ojo3hyfds2c914sOAuEJby9OSSUhyXy2fU8YXdAUqYE8yA5P6KmkIJT2I4kz S/AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:reply-to :from:date:message-id:subject:to:cc; bh=xGEppKhiZOzCOuYbJTTu+xSPBFZdqM0PDgB12krbqL4=; b=E/iIwsQvUzXDmjoWopglsl30Gdc3fhEmerojFUBDcdYS7b70ZuyjDdPog1+F+PJune xfvM67m8DcVuJD7Uls5OgWbhYy+EgsTAGQ8aYg3sek+soPSBnRsN+t2uHfRXicisMB34 0ls/xYmLY7KHmpj2JJmNF4dp7a9nvtZbbdEu5MEnT4n9F+/X/5grf57A76gOpN8NmvTG Rll29ewUNEipCf61PY3oQILQyhmUiAaaM50nnvMG5FDyADTVrqjFP75g5gUui+sUvWeo pQZPpmguFbvU90vlwP5j9l7DX9mT8sgTmwdANdMsl9LrrvGJSF2ibw7gtzpHwnsGqOXN d6ew== X-Gm-Message-State: APjAAAV5ZxrMFNoaPv9Zz+LMsBllY4tR4CmRQL04nY16GPdvLu+bHT9V UfBpck+0LLIdhxoiUVmacItMFEDtusYGWShvuYc= X-Google-Smtp-Source: APXvYqzVRPMNr+UchIlJW7g+LTyiPJ4Zs1OJm8fbk3zw1qGlalfdFWsyxMcvHzcbzlQ8Qj59mhYY3N1cTgULlHd+qvk= X-Received: by 2002:a2e:858f:: with SMTP id b15mr4910969lji.275.1578795159405; Sat, 11 Jan 2020 18:12:39 -0800 (PST) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::234 X-Content-Filtered-By: Mailman/MimeDel 2.1.23 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.org gmane.lisp.guile.user:16035 Archived-At: 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 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 > 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 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