Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

aref inline?

13 views
Skip to first unread message

lispn...@questions.com

unread,
Jun 3, 2001, 1:35:44 PM6/3/01
to
In a tight Lispworks loop which involves array references, disassembling the
code shows that aref is being called, and each call is being set up, such
that each aref takes many times longer than it could take.

Is there any easy way to get the speed effect in Lisp of doing simple array
referencing in C/C++ such as x+=y[i] etc.? E.g., is there an inline version
of aref, or any way to make it inline?

By the way, the answers I have been getting in this forum have been very
helpful, and I hope a lot of other people reading them are finding them
helpful too. Someone should go through these discussions sometime and write
a reference book from them, or maybe put them in some kind of specialized
search engine to find and browse discussions related to a particular
question.

Raymond Toy

unread,
Jun 3, 2001, 3:13:04 PM6/3/01
to
>>>>> "lispnewbie" == lispnewbie <lispn...@questions.com> writes:

lispnewbie> In a tight Lispworks loop which involves array references, disassembling the
lispnewbie> code shows that aref is being called, and each call is being set up, such
lispnewbie> that each aref takes many times longer than it could take.

lispnewbie> Is there any easy way to get the speed effect in Lisp of doing simple array
lispnewbie> referencing in C/C++ such as x+=y[i] etc.? E.g., is there an inline version
lispnewbie> of aref, or any way to make it inline?

Can't say specifically for Lispworks, but you should at least say what
type of array you're working on. CMUCL can inline aref if the array
is a 1-dimensional simple-array of "good" types like fixnum,
(signed-byte 32), single-float, double-float, etc. Otherwise, aref
can't be inlined, because the compiler doesn't know enough about the
array to inline the call.

Ray


Erik Naggum

unread,
Jun 3, 2001, 3:26:28 PM6/3/01
to
* lispn...@questions.com

> By the way, the answers I have been getting in this forum have been very
> helpful, and I hope a lot of other people reading them are finding them
> helpful too. Someone should go through these discussions sometime and
> write a reference book from them, or maybe put them in some kind of
> specialized search engine to find and browse discussions related to a
> particular question.

This is actually a _very_ bad idea. First off, the answers still belong
to the authors, who have implicitly given their permission to be used and
distributed in the context of a questions-and-answers style newsgroup,
and not for any other purpose. If you look around at the intellectual
property discussions in the news media, you will find that journalists
and other contributors demand extra payment for any "reuse" of their
material. Since contributors are _not_ paid on the Net, abusing their
goodwill by "collecting" their contributions is very difficult legal
territory. Search engines are difficult enough to defend, but if anyone
made money specifically on such collections, expect expensive.lawsuits.

Second, the reason technical answers to technical questions work so well
in this particular context is that anyone can, and usually does, correct
any and all mistakes and problems in the answers. In other words, it
pays off to be imprecise and incorrect in order to produce the most lucid
answers. The most precise and correct an answer is, the less discussion
it leads to. The reason you see such high quality articles in this
newsgroup in particular is that those people who care the most about
technical precision and accuracy care enough to respond and clarify.
Quite often on USENET, eager newbies respond with answers that are not
actually _wrong_, but still misleading and uninformed, because the more
experienced users have seen the same question thousands of times, and
only step in to correct a misleading response from an eager newbie. Some
eager newbies are not quite ready for this, and insist that their answers
are correct. The higher quality the answers in the newsgroup, the fewer
eager newbies, but also the fewer general number of posters, because few
people have the guts to stand up in a crowd of people they believe know
the answer better than them and speak.

The answer to your implicit request is just to hang around here even
after you tire of the repeated simple questions you know the answer to
and cannot imagine that somebody else failed to pick up from the many
available and high-quality sources. Having people ask questions is one
thing -- but a newsgroup thrives only when enough fearless newbies post
wrong answers -- that is the only way that the question gets any _real_
answers that lead to _understanding_.

This necessarily means that USENET is _not_ an archivable medium, but a
forum that lives in the precarious balance between experts and newbies.

So instead of automated tools that violate people's willingness to share,
just collect your own insights and bring them to the next "generation" of
people who discover Common Lisp by answering the questions and correcting
the mistakes made by other newbies who got it wrong in their eagerness.

#:Erik
--
Travel is a meat thing.

Stephen J. Bevan

unread,
Jun 3, 2001, 5:12:05 PM6/3/01
to
lispn...@questions.com writes:
> In a tight Lispworks loop which involves array references, disassembling the
> code shows that aref is being called, and each call is being set up, such
> that each aref takes many times longer than it could take.

It would help to see the loop and generated code to see what, if any,
hints you gave the compiler regarding the type of the array and array
index and whether you were explicitly compiling for speed or for
safety.

lispn...@questions.com

unread,
Jun 4, 2001, 12:37:01 AM6/4/01
to
On Sun, 03 Jun 2001 21:12:05 GMT, stephe...@yahoo.com (Stephen J. Bevan)
wrote:

>It would help to see the loop and generated code to see what, if any,
>hints you gave the compiler regarding the type of the array and array
>index and whether you were explicitly compiling for speed or for
>safety.

(defun test1 (n)
(declare (optimize speed (safety 0)
(fixnum-safety 0) (debug 0)))
(let ((v (make-sequence '(vector fixnum) 500000)))
(dotimes (i n)
(loop as e across v sum e))))

20FD52C2:
0: 55 push ebp
1: 89E5 move ebp, esp
3: 50 push eax
4: 50 push eax
5: 50 push eax
6: 50 push eax
7: 50 push eax
8: 50 push eax
9: 50 push eax
10: 50 push eax
11: 6871634720 push 20476371 ; (VECTOR FIXNUM)
16: B502 moveb ch, 2
18: B80020A107 move eax, 7A12000
23: FF1528970020 call [20009728] ; MAKE-SEQUENCE
29: 8945F4 move [ebp-C], eax
32: 8B75FC move esi, [ebp-4]
35: 8975E0 move [ebp-20], esi
38: C745E800000000 move [ebp-18], 0
45: 8B7DE0 move edi, [ebp-20]
48: 83FF00 cmp edi, 0
51: 7E5F jle L4
53: C745EC00000000 move [ebp-14], 0
60: 807DE000 cmpb [ebp-20], 0
64: 755A jne L5
66: 8B7DE0 move edi, [ebp-20]
L1: 69: 89FE move esi, edi
71: 81EE00010000 sub esi, 100
77: 8975E4 move [ebp-1C], esi
L2: 80: C745FC00000000 move [ebp-4], 0
87: C745F800000000 move [ebp-8], 0
94: 8B45F4 move eax, [ebp-C]
97: B501 moveb ch, 1
99: FF1580B22020 call [2020B280] ;
SYSTEM::ACROSS-CHECK-IS-VECTOR
105: 8945F0 move [ebp-10], eax
108: 8B7DF0 move edi, [ebp-10]
111: 83FF00 cmp edi, 0
114: 7540 jne L7
L3: 116: 8B5DEC move ebx, [ebp-14]
119: 8B7DE4 move edi, [ebp-1C]
122: 3BDF cmp ebx, edi
124: 7C25 jl L6
126: 8B7DE8 move edi, [ebp-18]
129: 81C700010000 add edi, 100
135: 897DE8 move [ebp-18], edi
138: 8B5DE8 move ebx, [ebp-18]
141: 8B7DE0 move edi, [ebp-20]
144: 3BDF cmp ebx, edi
146: 7CBC jl L2
L4: 148: FD std
149: B810000000 move eax, 10
154: C9 leave
155: C3 ret
L5: 156: BF00FFFF7F move edi, 7FFFFF00
161: EBA2 jmp L1
L6: 163: 8B7DEC move edi, [ebp-14]
166: 81C700010000 add edi, 100
172: 897DEC move [ebp-14], edi
175: 897DE8 move [ebp-18], edi
178: EB9C jmp L2
L7: 180: 8B7DF4 move edi, [ebp-C]
183: 57 push edi
184: B502 moveb ch, 2
186: 33C0 xor eax, eax
188: FF1520470020 call [20004720] ; AREF
L8: 194: 8B7DF8 move edi, [ebp-8]
197: 03C7 add eax, edi
199: 8945F8 move [ebp-8], eax
202: 8B7DFC move edi, [ebp-4]
205: 81C700010000 add edi, 100
211: 897DFC move [ebp-4], edi
214: 8B5DFC move ebx, [ebp-4]
217: 8B7DF0 move edi, [ebp-10]
220: 3BDF cmp ebx, edi
222: 7494 je L3
224: 8B7DF4 move edi, [ebp-C]
227: 57 push edi
228: 8B45FC move eax, [ebp-4]
231: B502 moveb ch, 2
233: FF1520470020 call [20004720] ; AREF
239: EBD1 jmp L8
241: 90 nop

lispn...@questions.com

unread,
Jun 4, 2001, 12:46:26 AM6/4/01
to
On 03 Jun 2001 15:13:04 -0400, Raymond Toy <t...@rtp.ericsson.se> wrote:

>Can't say specifically for Lispworks, but you should at least say what
>type of array you're working on. CMUCL can inline aref if the array

Ok, I posted some example code a few minutes ago, but my real question is
more general. In general, is there a way to explicitly tell the Lispworks
compiler to make a built-in function inline? Or can it only be done by
telling to you want speed, etc., and hoping it can figure out that making the
function inline would be helpful? And if that is the case, does it actually
do it for any specific functions? If so, what are they? And what is the
best way to find this general kind of information? Are there any specific
manuals which go into such details?

Pierre R. Mai

unread,
Jun 4, 2001, 9:14:56 AM6/4/01
to
lispn...@questions.com writes:

> On Sun, 03 Jun 2001 21:12:05 GMT, stephe...@yahoo.com (Stephen J. Bevan)
> wrote:
>
> >It would help to see the loop and generated code to see what, if any,
> >hints you gave the compiler regarding the type of the array and array
> >index and whether you were explicitly compiling for speed or for
> >safety.
>
> (defun test1 (n)
> (declare (optimize speed (safety 0)
> (fixnum-safety 0) (debug 0)))
> (let ((v (make-sequence '(vector fixnum) 500000)))
> (dotimes (i n)
> (loop as e across v sum e))))

There are obvious (to the initiated ;) ways in which you can improve
the type declarations in this function to allow LW to generate better
code:

- Although a sufficiently smart compiler might be able to deduce the
type of v by itself, most compilers aren't that clever, and hence it
pays to declare it specifically. Since you didn't do so, LW assumes
that v can be any kind of object, or at least any kind of array,
which includes non-simple arrays (like displaced arrays, arrays with
fill-pointers, adjustable arrays, etc.), arrays with other element
types (and hence other memory layouts), multi-dimensional arrays,
etc. To take care of all of these situations, aref will have to do
much work, and hence it doesn't pay of to inline that large amount
of code, so LW doesn't.

By adding a declaration of the form

(declare (type (simple-array fixnum (*)) v))

Or even more specific

(declare (type (simple-array fixnum (500000)) v))

You will allow LW to inline aref profitably, because it now knows
exactly what kind of array to expect, and can therefore open-code
just the relevant stuff (a couple of instructions instead of a
couple of hundred instructions).

The important speed-up here doesn't come from inlining/open-coding
itself, but rather from eliding quite a number of checks,
calculations, etc.

- Adding declarations for e and the sum of it (the sum of two fixnums
isn't necessarily a fixnum itself), you can speed up the summation
part quite a bit as well, if you can guarantee that the sum of all
elements still fits inside a fixnum.

- While we are at it, we might want to add declarations for n and i as
well.

This gives us the following function:

(defun test1 (n)
(declare (optimize speed (safety 0) (fixnum-safety 0) (debug 0))

(fixnum n))


(let ((v (make-sequence '(vector fixnum) 500000)))

(declare (type (simple-array fixnum (500000)) v))
(dotimes (i n)
(declare (fixnum i))
(loop as e of-type fixnum across v sum e of-type fixnum))))

Which sums 1,000,000,000 fixnums (invoked with n=2000) in 24.5s on an
AMD K6-2/550, or 24.5ns per fixnum/iteration, which comes out at
around 13.5 cycles per iteration.

On current CMU CL you will get down to 11.4ns or 6.25 cycles per
iteration (and you might safe yourself a couple of the declarations,
because CMU CL's compiler does a slightly better job at infering type
declarations from other known types).

The inner-most loop looks like this in CMU CL:

89: L1: MOV ECX, [EDX+EBX+1]
8D: ADD EBX, 4
90: ADD ESI, ECX
92: L2: CMP EBX, EDI
94: JL L1

Regs, Pierre.

--
Pierre R. Mai <pm...@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein

Raymond Toy

unread,
Jun 4, 2001, 9:37:45 AM6/4/01
to
>>>>> "lispnewbie" == lispnewbie <lispn...@questions.com> writes:

lispnewbie> On Sun, 03 Jun 2001 21:12:05 GMT, stephe...@yahoo.com (Stephen J. Bevan)
lispnewbie> wrote:

>> It would help to see the loop and generated code to see what, if any,
>> hints you gave the compiler regarding the type of the array and array
>> index and whether you were explicitly compiling for speed or for
>> safety.

lispnewbie> (defun test1 (n)
lispnewbie> (declare (optimize speed (safety 0)
lispnewbie> (fixnum-safety 0) (debug 0)))
lispnewbie> (let ((v (make-sequence '(vector fixnum) 500000)))
lispnewbie> (dotimes (i n)
lispnewbie> (loop as e across v sum e))))

My guess is that Lispworks isn't smart enough to see that v is really
a (simple-array fixnum (5000000)), and thus can't inline aref. For
this example, CMUCL does inline the aref. However, CMUCL has other
deficiencies such as not knowing the types of the loop counters and
using generic arithmetic on them.

Ray

Lieven Marchand

unread,
Jun 4, 2001, 8:41:38 AM6/4/01
to
lispn...@questions.com writes:

> In a tight Lispworks loop which involves array references, disassembling the
> code shows that aref is being called, and each call is being set up, such
> that each aref takes many times longer than it could take.
>

In the case of your code, use svref instead of aref and Lispworks will
inline it.

--
Lieven Marchand <m...@wyrd.be>
Making laws appears to win votes. Enforcing them doesn't.
See Rule One. Roger Burton West in the monastery.

Barry Margolin

unread,
Jun 4, 2001, 1:26:44 PM6/4/01
to
In article <sg4mhtcmqinjblq7o...@4ax.com>,

<lispn...@questions.com> wrote:
>Ok, I posted some example code a few minutes ago, but my real question is
>more general. In general, is there a way to explicitly tell the Lispworks
>compiler to make a built-in function inline? Or can it only be done by
>telling to you want speed, etc., and hoping it can figure out that making the
>function inline would be helpful?

No, there's no way to request that a particular built-in function be
open-coded; what if it doesn't have the information available to open-code
that function? In general, if the implementation knows how to open-code a
function call, it will do it automatically unless you've told it not to do
so (with a NOTINLINE declaration).

> And if that is the case, does it actually
>do it for any specific functions? If so, what are they? And what is the
>best way to find this general kind of information? Are there any specific
>manuals which go into such details?

I think you'll probably find that just about every implementation
open-codes low-level functions like CONS, CAR, and CDR. I don't think most
implementation document this level of detail; if you want to know whether a
particular function is inlined, disassemble a function that calls it.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Kent M Pitman

unread,
Jun 4, 2001, 1:53:55 PM6/4/01
to
Barry Margolin <bar...@genuity.net> writes:

> No, there's no way to request that a particular built-in function be
> open-coded; what if it doesn't have the information available to open-code
> that function? In general, if the implementation knows how to open-code a
> function call, it will do it automatically unless you've told it not to do
> so (with a NOTINLINE declaration).

I think I would have said:

There's no way to request that a particular
function be "open-codable", since that is done by placing
an INLINE declaration BEFORE the time of definition, and since built-ins
are, by definition, things whose definition time has passed. There IS a way
to request that a particular function be "open-coded", in case the system
definers made the right declaration (or equivalent) earlier in order to
follow up on such a thing.

> I think you'll probably find that just about every implementation
> open-codes low-level functions like CONS, CAR, and CDR. I don't think most
> implementation document this level of detail; if you want to know whether a
> particular function is inlined,

[in a particular circumstance]


> disassemble a function that calls it.

Some compilers provisionally open-code things, so it won't tell you reliably
for the general case. Ask the implementor if you really want to be sure.

Barry Margolin

unread,
Jun 4, 2001, 3:02:56 PM6/4/01
to
In article <sfw4rtw...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
>Barry Margolin <bar...@genuity.net> writes:
>
>> No, there's no way to request that a particular built-in function be
>> open-coded; what if it doesn't have the information available to open-code
>> that function? In general, if the implementation knows how to open-code a
>> function call, it will do it automatically unless you've told it not to do
>> so (with a NOTINLINE declaration).
>
>I think I would have said:
>
>There's no way to request that a particular
>function be "open-codable", since that is done by placing
>an INLINE declaration BEFORE the time of definition, and since built-ins
>are, by definition, things whose definition time has passed. There IS a way
>to request that a particular function be "open-coded", in case the system
>definers made the right declaration (or equivalent) earlier in order to
>follow up on such a thing.

How do you request that a particular function be open-coded? I know you
can request that it *not* be open-coded, by using NOTINLINE. Are you
suggesting that he use INLINE explicitly on a built-in function?

My expectation (I don't think the standard actually says so, but in
practice I suspect I'm right) is that if the implementor made a function
open-codABLE, they default to making it open-codED, so such a declaration
is unnecessary (except to undo an earlier NOTINLINE declaration). Does
anyone actually suggest that people put the following in their code, just
in case the implementor chose the wrong default?

(declaim (inline car cdr cons + - * /))

The standard may not require implementations to open-code these functions,
but market forces generally do.

Kent M Pitman

unread,
Jun 4, 2001, 5:53:00 PM6/4/01
to
Barry Margolin <bar...@genuity.net> writes:

> In article <sfw4rtw...@world.std.com>,
> Kent M Pitman <pit...@world.std.com> wrote:
> >Barry Margolin <bar...@genuity.net> writes:
> >
> >> No, there's no way to request that a particular built-in function be
> >> open-coded; what if it doesn't have the information available to open-code
> >> that function? In general, if the implementation knows how to open-code a
> >> function call, it will do it automatically unless you've told it not to do
> >> so (with a NOTINLINE declaration).
> >
> >I think I would have said:
> >
> >There's no way to request that a particular
> >function be "open-codable", since that is done by placing
> >an INLINE declaration BEFORE the time of definition, and since built-ins
> >are, by definition, things whose definition time has passed. There IS a way
> >to request that a particular function be "open-coded", in case the system
> >definers made the right declaration (or equivalent) earlier in order to
> >follow up on such a thing.
>
> How do you request that a particular function be open-coded? I know you
> can request that it *not* be open-coded, by using NOTINLINE. Are you
> suggesting that he use INLINE explicitly on a built-in function?

I think I'm suggesting he could.. unless someone finds a passage saying
you can't do that. I don't know that making an INLINE declarationw ould
do much good, for reasons you cite, but it doesn't seem to me to cause lots
of harm. It probably already is INLINE, as you note.



> My expectation (I don't think the standard actually says so, but in
> practice I suspect I'm right) is that if the implementor made a function
> open-codABLE, they default to making it open-codED, so such a declaration
> is unnecessary (except to undo an earlier NOTINLINE declaration).

Yes, but it might have been disabled subsequent to that. Not only by the
system folks, but by some "helpful" other user-package, including your own.

> Does
> anyone actually suggest that people put the following in their code, just
> in case the implementor chose the wrong default?
>
> (declaim (inline car cdr cons + - * /))

Well, I personally don't recommend EVER proclaiming or declaiming a system
function to be NOTINLINE, but it could happen. I would only do it by DECLARE
within a known lexical region, so it doesn't overflow into someone else's
code, forcing a need for a defensive INLINE. Normally I'd expect such an
INLINE to be superfluous, but ...

> The standard may not require implementations to open-code these functions,
> but market forces generally do.

A more interesting case isn't + or - but MAPCAR. It's a toss-up whether
to open-code MAPCAR, I bet, because of all the code bloat. I can imagine
an implementation not doing so in general. But there may be cases where
it's a good idea, and doing
(locally (declare (inline mapcar))
(mapcar ...))
might be helpful in some implementations, I would think. Then again, the
system might already do it based on speed > space or some other such thing.
But it's beyond the definition of the spec to know how the system actually
decides. Seems to me the INLINE declaration is the most perspicuous, direct
way to say what you want.

Pierre R. Mai

unread,
Jun 4, 2001, 7:25:17 PM6/4/01
to
Kent M Pitman <pit...@world.std.com> writes:

> Barry Margolin <bar...@genuity.net> writes:

[...]

> > How do you request that a particular function be open-coded? I know you
> > can request that it *not* be open-coded, by using NOTINLINE. Are you
> > suggesting that he use INLINE explicitly on a built-in function?
>
> I think I'm suggesting he could.. unless someone finds a passage saying
> you can't do that. I don't know that making an INLINE declarationw ould
> do much good, for reasons you cite, but it doesn't seem to me to cause lots
> of harm. It probably already is INLINE, as you note.

CMU CL has an ext:maybe-inline declaration, which tells the compiler
to record the expansion of a function, but doesn't cause actual inline
expansion to occur, unless the space optimization quality in effect at
the expansion site is 0, or the function is subsequently/locally
declared inline. Various built-in functions are declared
maybe-inline, and hence the user can cause inline expansion of those
to happen by locally declaring them inline.

Things like digit-char-p, maphash, read-char, unread-char, read-byte
are declared ext:maybe-inline, and there have been requests to declare
more functions ext:maybe-inline, though one has to be careful not do
overdo something like this.

> A more interesting case isn't + or - but MAPCAR. It's a toss-up whether
> to open-code MAPCAR, I bet, because of all the code bloat. I can imagine
> an implementation not doing so in general. But there may be cases where
> it's a good idea, and doing
> (locally (declare (inline mapcar))
> (mapcar ...))
> might be helpful in some implementations, I would think. Then again, the
> system might already do it based on speed > space or some other such thing.
> But it's beyond the definition of the spec to know how the system actually
> decides. Seems to me the INLINE declaration is the most perspicuous, direct
> way to say what you want.

maphash is an example of CMU CL enabling such a thing. mapcar isn't
declared ext:maybe-inline, because mapcar is always open-coded in CMU
CL via a source-transform.

Barry Margolin

unread,
Jun 4, 2001, 7:38:57 PM6/4/01
to
In article <871yozl...@orion.bln.pmsf.de>,

Pierre R. Mai <pm...@acm.org> wrote:
>CMU CL has an ext:maybe-inline declaration, which tells the compiler
>to record the expansion of a function, but doesn't cause actual inline
>expansion to occur, unless the space optimization quality in effect at
>the expansion site is 0, or the function is subsequently/locally
>declared inline. Various built-in functions are declared
>maybe-inline, and hence the user can cause inline expansion of those
>to happen by locally declaring them inline.

Except for the fact that it conditionalizes on the space optimization
quality, this is essentially equivalent to:

(declaim (inline <func-name>))
(defun <func-name> ...)
(declaim (notinline <func-name>))

There's no portable way to get open coding conditionalized on optimization
settings.

Pierre R. Mai

unread,
Jun 5, 2001, 4:03:45 AM6/5/01
to
Barry Margolin <bar...@genuity.net> writes:

> In article <871yozl...@orion.bln.pmsf.de>,
> Pierre R. Mai <pm...@acm.org> wrote:
> >CMU CL has an ext:maybe-inline declaration, which tells the compiler
> >to record the expansion of a function, but doesn't cause actual inline
> >expansion to occur, unless the space optimization quality in effect at
> >the expansion site is 0, or the function is subsequently/locally
> >declared inline. Various built-in functions are declared
> >maybe-inline, and hence the user can cause inline expansion of those
> >to happen by locally declaring them inline.
>
> Except for the fact that it conditionalizes on the space optimization
> quality, this is essentially equivalent to:
>
> (declaim (inline <func-name>))
> (defun <func-name> ...)
> (declaim (notinline <func-name>))

Yes, but it is more convenient, too, because you don't need two
declarations in different places.

> There's no portable way to get open coding conditionalized on optimization
> settings.

Indeed there isn't even portable access to the current optimization
settings, which would be nice to have, so that users could tailor
their compiler-macros accordingly, etc.

lispn...@questions.com

unread,
Jun 5, 2001, 5:07:20 AM6/5/01
to
On 04 Jun 2001 15:14:56 +0200, "Pierre R. Mai" <pm...@acm.org> wrote:

> (declare (type (simple-array fixnum (500000)) v))

Yes, declaring the array to be of fixnums turns out to be the key to making
this kind of code an order of magnitude faster in Lispworks and approximately
the same speed as C/C++.

Thanks for all of your very helpful answers to my "newbie" questions. I hope
a thousand lurking newbies are reading them and learning as much as I am from
them.

Barry Margolin

unread,
Jun 5, 2001, 11:07:14 AM6/5/01
to
In article <87bso3j...@orion.bln.pmsf.de>,

Pierre R. Mai <pm...@acm.org> wrote:
>Barry Margolin <bar...@genuity.net> writes:
>
>> In article <871yozl...@orion.bln.pmsf.de>,
>> Pierre R. Mai <pm...@acm.org> wrote:
>> >CMU CL has an ext:maybe-inline declaration, which tells the compiler
>> >to record the expansion of a function, but doesn't cause actual inline
>> >expansion to occur, unless the space optimization quality in effect at
>> >the expansion site is 0, or the function is subsequently/locally
>> >declared inline. Various built-in functions are declared
>> >maybe-inline, and hence the user can cause inline expansion of those
>> >to happen by locally declaring them inline.
>>
>> Except for the fact that it conditionalizes on the space optimization
>> quality, this is essentially equivalent to:
>>
>> (declaim (inline <func-name>))
>> (defun <func-name> ...)
>> (declaim (notinline <func-name>))
>
>Yes, but it is more convenient, too, because you don't need two
>declarations in different places.

That can be fixed portably quite easily:

(defmacro defun-inlinable (name args &body body)
`(progn
(declaim (inline ,name))
(defun ,name ,args ,@body)
(declaim (notinline ,name))))

In fact, you could even do:

(defmacro defun-inlinable (name args &body body)
`(progn
(declaim (#+cmucl ext:maybe-inline #-cmucl inline ,name))
(defun ,name ,args ,@body)
#-cmucl (declaim (notinline ,name))))

Now, not only does it do what you want without having to have multiple
declarations, but it does CMUCL's cool thing automatically as well.

Kent M Pitman

unread,
Jun 5, 2001, 12:29:30 PM6/5/01
to
Barry Margolin <bar...@genuity.net> writes:

> (defmacro defun-inlinable (name args &body body)
> `(progn
> (declaim (#+cmucl ext:maybe-inline #-cmucl inline ,name))
> (defun ,name ,args ,@body)
> #-cmucl (declaim (notinline ,name))))

I would have spelled this defun-inlineable. But because either form
is so visually painful, I recommend instead just avoiding the whole
issue and going with:

(defmacro defun-inline (name args &body body)
`(progn
(declaim (inline ,name))
(defun ,name ,args ,@body)))

(defmacro defun-maybe-inline (name args &body body)
`(progn
#+cmucl (declaim (ext:maybe-inline ,name))
#+cmucl (declaim (inline ,name))
(defun ,name ,args ,@body)
#-cmucl (declaim (notinline ,name))
',name))

(defmacro defun-notinline (name args &body body)


`(progn
(declaim (inline ,name))
(defun ,name ,args ,@body)
(declaim (notinline ,name))

',name))

Note also that purely as a style issue, I prefer to put the #+/#- in a
different position than Barry put them in order to make grep and/or
tags-search more likely to succeed with pattern substrings that
juxtapose the paren with the conditionalized item.

Pierre R. Mai

unread,
Jun 5, 2001, 1:51:08 PM6/5/01
to
Barry Margolin <bar...@genuity.net> writes:

> That can be fixed portably quite easily:
>
> (defmacro defun-inlinable (name args &body body)
> `(progn
> (declaim (inline ,name))
> (defun ,name ,args ,@body)
> (declaim (notinline ,name))))

Yes, that's another way to achieve similar results, although it has
associated costs of function definitions not being as recognizable
anymore (it might also fool tools that work on the source code). Not
a high cost to pay, and probably one preferable to inventing
non-portable declarations.

0 new messages