Mike Haertel <m...@ichips.intel.com> wrote: >But GCC doesn't use CPS. In fact, as far as I know no compiler for >any conventional imperative language uses CPS. There might be an >interesting research project in that.
Richard A. Kelsey's dissertation ("Compilation by Program Transformation", YALEU/CSD/RR #702, May, 1989) discusses compilation using CPS as an intermediate langauge and performing source to source transformations. He implemented compilers for Pascal and BASIC to code for the MC68020. Speed of the resulting code for some simple programs was comparable to the Apollo Pascal compiler.
(I must say that I found this dissertation very interesting.)
-- T. Kurt Bond, t...@wvlink.mpl.com, Kurt.B...@launchpad.unc.edu -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Launchpad is an experimental internet BBS. The views of its users do not necessarily represent those of UNC-Chapel Hill, OIT, or the SysOps. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
In article <TMB.94Aug17223...@arolla.idiap.ch> t...@arolla.idiap.ch (Thomas M. Breuel) writes:
Yes, for putting scalars into structures, you can generate reasonably efficient code, but few CL compilers actually do.
Yes, but you were not talking about limitations of current CL compilers. You were claiming that the semantics of CL was inherently deficient.
However, when you nest those structures, put them into arrays, or pass them as arguments, you have extra pointer and heap overhead. Furthermore, the compiler cannot statically decide to optimize the pointer overhead away, since that is sometimes wrong (i.e., less efficient) and can also change semantics.
Here is an idea: Take the semantics of structures to be defined to be indirect (as it is in current CL and Scheme). Then make structures immediate as an optimization. There are only two ways you could possibly tell the different between an indirect structure and an immediate structure:
a. EQ b. Mutating a slot. If the structure was implemented as an immediate structure then mutating one copy would unsoundly fail to mutate other copies.
If a compiler could prove that a given structure type never was mutated and never appeared as an argument to EQ it would be licensed to implement that structure as an immediate structure. It might choose not to do so for large structures since the cost of passing around large structures might outweigh the cost of allocation, reclaimation, and indirection. But it could use automatically generated profile data to help determine the tradeoff. Or it could ask the user, remember the responses between compilations, and allow the user to subsequently change the decision on a per-structure basis. Having this decision be orthogonal to the source code makes it easier to change this decision without having to update the source code in a consistent fashion.
It is incredibly useful to be able to specify reference vs. value semantics, and CL lacks the primitives for doing that.
How is value semantics anything more than a subset of reference semantics? Modulo efficiency, the only thing I can see is mutation of an immediate structure. That can be accomplished in reference semantics by making a new copy of the structure with one slot modified and the others copied over. I.e. in Scheme:
These can be defined as above and DEFSTRUCT can be modified to provide analogous nonmutating SET functions along with the standard mutating ones. This is all still within reference semantics. Simply the compiler can recognize when it optimizes a structure to be immediate and further eliminate the copying involved with the nonmutating SET functions.
Now all of this handles passing immediate structures as arguments, returning them as results, assigning them to variables, and storing them in structure or vector slots. A further optimization can be performed. If a compiler can prove that there can be at most only one pointer to a structure then even if the structure is mutated it can be implemented as an immediate structure. (If there can be only one pointer to a structure then it would not be possible for it to appear as both arguments to EQ.) Standard `linearity' analysis can be used to make this determination. Thus if one created a vector of structures, where the only pointers to those structures existed in that vector, even if the structure slots were mutated, the compiler could still optimize this as a vector of immediate structures. Similarly for structures slots containing structures.
Now immediate vectors are a bit harder since the length of the vector would need to be determined at compiler time if one wanted to have a structure or vector of immediate vectors. But again standard `manifestness' analysis can be used to determine the simple and most common instances of when this is the case and allow this optimization to take place. Of course one would need a nonmutating VECTOR-SET operation as a counterpart to VECTOR-SET! along the lines of the above. But as before, this can be defined purely within and on top of the current Scheme and CL language spec.
So as I see it the semantics of CL and Scheme are perfectly adequate in this regard. It is just a matter of optimization. --
In article <TFB.94Aug11164...@sorley.cogsci.ed.ac.uk> t...@cogsci.ed.ac.uk (Tim Bradshaw) writes:
--> * Jeff Dalton wrote: --> > I would agree that Lisp can do reasonably well on RISC machines, --> > but the point of Lisp machines was not just to make Lisp fast --> > but also to make it fast and safe at the same time and fast --> > without needing lots of declarations. --> --> > Recent Lisp implementations (especially CMU CL) have gone a fair --> > way towards making it easy to have safe, efficient code on RISC --> > machines, but it may always require a somewhat different way of --> > thinking. (Not a bad way, IMHO, but different from LM thinking --> > nonetheless.) --> --> Could any of the lisp machines do fast floating point, without --> declarations? I know maclisp was rumoured to be able to (on --> stock hardware even!) but did it use declarations?
(dotimes (i 10000) (* 123.4 i) )
each multiply seems to take 1.2 microseconds on my 25 MHz 32-bit Explorer 2.
(dotimes (i 10000) (* 1.234d2 i) )
appears to take almost the exact same amount of time.
(dotimes (i 10000) (/ 1.234d2 i) ;now we're dividing! )
also appears to take the same amount of time.
seems reasonably fast to me, given that it's *only* 25 MHz. clearly faster devices like a Sparc or Alpha chip would be much faster, although unless you spent a lot of time doing the math, it'd be hard to see it in your apps.
it doesn't seem to make too much difference about the declarations, but this is a poor test-case.
the LispChip has built-in floating-pt. the Exp 1 did not, and was slow about heavy floating-pt stuff. you wanted to be careful with your code not to waste time computing any floating-pt value more than once.
In article <TMB.94Aug15224...@arolla.idiap.ch> t...@arolla.idiap.ch (Thomas M. Breuel) writes: --> (think about how much space your --> typical "struct { int x; double y; char z;};" takes as a CommonLisp --> DEFSTRUCT)
my guess is that it would be 128 bits. 4 words, expecting word-alignment behavior (well, that's machine-dependent stuff, I was thinking of a 32-bit machine).
sounds like you're suggesting that it comes out otherwise...
| (dotimes (i 10000) | (* 123.4 i) | ) | | each multiply seems to take 1.2 microseconds on my 25 MHz 32-bit | Explorer 2.
this is really _outstanding_. on a SPARC 10, the following C program takes 3 seconds to run when given an argument, and an imperctibly small number with none, i.e., 3 microseconds per operation.
main (int argc, char ** argv) { if (argc == 2) { int i; double d; for (i = 0; i < 10000000; i++) d = 123.4 * i; } return 0;
}
of the three Common LISP implementations I have running here, interpreted performance for your LISP expression is:
In article <CuMwDB....@triple-i.com> k...@triple-i.com (Kirk Rader) writes:
--> In article <CuL4nH....@cogsci.ed.ac.uk> j...@aiai.ed.ac.uk (Jeff Dalton) writes: --> --> Not "necessarily slower", but in my experience it is more common in --> real-world programming projects to encounter cases were C's --> memory-management philosophy results in higher throughput and fewer --> problems for interactivity and real-time response than one which --> relies on GC.
isn't this a result comparable to that of declaring types? if I took a casually written lisp program and converted it to C, I'd have to declare lots more variables types than i did in lisp. I'd also have to use lots of malloc/free calls, which I didn't in lisp. let us say the the programs get tested with the exact same test suite...I'd expect the C version to not exhibit the GC-related slowdowns that might be apparent in the lisp version because that behavior would be distributed differently, even though the total would likely be exactly the same amount of RAM allocated and GC'd.
my currently used Lisp dialects do the typical thing--generational GC, which waits until a threshold is reached before GC'ing gen 0. a C program GCs every time you let go of something (free it), and so the time distribution is different. this is the most painful thing preventing "real-time" behavior--it occurs more-or-less randomly, and has unpredictable duration.
some years ago, when i was porting Macsyma to the Explorer, I fiddled with cons-areas, wondering if I could do a better job of controlling GC occurrences myself. the idea was that I would allocate an area, work in it, copy a result out of it and immediately free the area, avoiding having to GC that area, cutting the cost of a GC when it finally did occur. this was before generational GC had become available. Macsyma is/was horrible about generating garbage.
In article <Cuou41....@triple-i.com> k...@triple-i.com (Kirk Rader) writes:
> In article <vrotneyCuoAp7....@netcom.com> vrot...@netcom.com (William Paul Vrotney) writes:
> [...]
> >Instead of all this complex analysis, which I'm not sure is going anywhere, > >lets try some simple stuff for a change. Lets try this mind experiment. IF > >there was a Lisp compiler that compiled as efficiently as C (or even close > >to) and IF your boss said that you can program in either Lisp or C. What > >would your choice be? Case closed (one way or the other). I hope.
> >There are so many more interesting aspects of Lisp that this news group can > >be used for.
> I agree that this is far from the most interesting topic that could be > discussed in this newsgroup. I also see from the above that you have > missed my point entirely. Oh well.
In article <19940818.4...@naggum.no> Erik Naggum <e...@naggum.no> writes:
--> [ch...@labs-n.bbn.com] --> --> | (dotimes (i 10000) --> | (* 123.4 i) --> | ) --> | --> | each multiply seems to take 1.2 microseconds on my 25 MHz 32-bit --> | Explorer 2. --> --> this is really _outstanding_. on a SPARC 10, the following C program takes --> 3 seconds to run when given an argument, and an imperctibly small number --> with none, i.e., 3 microseconds per operation.
unfortunately, it's totally bogus. Marty Hall, a person CLEARLY more conversant on lisp compilers than I am, pointed out that the compiler would have eliminated the multiply, since the result wasn't being used. all I measured was 10000 loops of nothing.
the equivalent function, which didn't eliminate it:
(defun foo () ; 0.197 (let ((x 3.217)) (declare (optimize (speed 3) (safety 0))) (dotimes (i 10000) (declare (integer i)) (setq x (* x (float i))) ) x) )
10k times, single-float, best optimization. 0.197 seconds for the whole thing. conses about 35 words, or some such--that's a dynamic behavior,for reasons unknown to me. that's 20 microseconds per. still good, but not great. double-float time is 25 microseconds. divide is actually *faster*, but only about 1%.
disassembling this shows that it's only got 13 instructions, excluding the FEF overhead. I don't know how many registers the LispChip has, but it appears to be only one (!?) from looking at the assembly code. I do'nt know the design, but the assembly code has several push and pop instructions in it, which suggests that there's an on-chip stack-register, and the there are two working registers for holding numbers. the actual loop has three of these instructions in it, and my (fading) knowledge of microprocessor design suggests that if they were all registers they wouldn't be necessary here. or would you just have different ones? been too long...
--> main (int argc, char ** argv) --> { --> if (argc == 2) { --> int i; --> double d; --> for (i = 0; i < 10000000; i++) --> d = 123.4 * i; --> } --> return 0; --> } --> --> of the three Common LISP implementations I have running here, interpreted --> performance for your LISP expression is: --> --> GCL 0.6 seconds --> CLISP 2.2 seconds --> CMUCL 4.1 seconds
those are decent numbmers. interpreted runtime on the E2-25 is ~9.8 seconds. for ten thousand cycles, single-float.
--> are you sure you meant _microseconds_, not milliseconds?
absolutely. the original number I gave was 0.012 seconds, but it was a bogus number. the real one is 0.2 seconds.
Allegro 4.2 tells me it's 33 milliseconds for the compiled version, i.e., about 3 microseconds per multiply. and the dissassemble is bigger, apparently. looks like 104 words, and 28 instructions, 8 for overhead.
>In article <TFB.94Aug15180...@oliphant.cogsci.ed.ac.uk> t...@cogsci.ed.ac.uk (Tim Bradshaw) writes: >|Sounds pretty much >|identical to that of C to me. A lot of CL implementations seem to >|have rather poor I/O but that's because the I/O systems aren't well >|written. >CL's I/O system is also lacking some rather important primitives, >like block read/block write.
1. You say "like". What other examples are there?
2. What exactly is the problem with lacking user-visible block read and write? The underlying I/O system will still use block r/w.
>|However these >|problems are in fact just as bad for other programs (for instance X >|servers exhibit many of the same characteristics, and thrash VM >|systems the same way as Lisp on resource-starved machines. >Sure, but CommonLisp systems will resource-starve a machine much more >quickly than an equivalent C program.
That depends, in part, on what you count as equivalent.
> The reason is that CL lacks >important primitives for expressing some fundamental kinds of data >abstractions in a space-efficient way (think about how much space your >typical "struct { int x; double y; char z;};" takes as a CommonLisp >DEFSTRUCT).
How much? Do you have some actual numbers?
(There are cases where Lisps typically represent things more efficiently than C -- consider e.g. a naive implementation of cons in C using malloc.)
> Also, rampant consing by the standard libraries is a real >problem in CL.
What standard libraries are those? Which Common Lisps?
Do you know that a number of Lisps never cons unless required to do so by the user's program?
> And, most systems still don't have efficient floating >point arguments/return values for separately compiled functions.
Is this an inherent problem or just a matter of implementation traditions?
>Yes, you are right, neither VM behavior of CommonLisp nor garbage >collection are the problem. However, VM thrashing and excessive >garbage collections are frequently observed symptoms of problems with >the CommonLisp language.
I wonder what people are doing so that this is so. I don't usually have much problem with excessive GC and when I do it's often easy to fix.
>|CL's I/O model is basically buffered streams. >CL has _typed_ buffered streams. Whatever the CL I/O design was >supposed to achieve, it fails to achieve in practice. Those stream >types at best cause lots of headaches.
Do you have any examples?
This problem with think kind of account is that it assumes everyone knows what you're talking about. It lines up with what lots of people who dislike Lisp already believe, but doesn't say just how bad the problem actually is. People therefore assume it's as bad as they always thought it was, or worse, since they may not have considered all your examples (what exactly is wrong with typed streams, for instance?).
>>I find this rather strange. What is the mismatch in I/O models? >>And why would Lisp's lightweight processes be a problem? Is the >>OS not expecting to give timer interrupts? Memory management I >>can almost see, but what exactly is going wrong? Berkeley Unix >>tried to take Franz Lisp into account. Have things moved backwards >>since then? >As one concrete example of the kind thing to which I referred, SGI's >filesystem substrate maintains its recently-deallocated file cache >buffers in a "semi-free" state on the theory that they will quickly be >reallocated for the same purpose. Watching the output of gr_osview as >an I/O intensive lisp application executes you can easily see conflict >between the different buffering and memory-management policies being >used by the OS's filesystem and virtual-memory management mechanisms >and by the I/O and memory-management mechanisms of at least two >commercial Common Lisp implementations and one shareware Scheme >implementation with which I am familiar.
What exactly is the problem? I don't have an SGI system, so I can't watch the output of gr_osview and easily see what's happening. Is there any reason to suppose it's an inherent Lisp problem rather than a poorly tuned implementation?
>[...] >>Sure there is. It might be fine for Lisp A but not for Lisp B. >>Besides, I/O and scheduling and much of memory management is >>the OS, not the hardware. The OS on ordinary non-Lisp machines >>could change to work better with Lisp. >All these arguments about "lisp A vs lisp B" are red-herrings.
Not when someone says a Lisp machine is bound to be fine for Lisp.
>On a given lisp-machine you could only be described as perverse for using >any other dialect than one for which the machine was designed.
Why is that any more perverse than using gcc rather than the compiler from the hardware manufacturer? Who says a Lisp machine has to be for only one Lisp and an ordinary machine can be for any C and indeed a whole range of languages? Even existing Lisp machines weren't that restricted!
>I understand your real argument to be that it is in principle possible >to design lisp-friendly OS's and Unix- (or other particular OS-) >friendly lisps. That is undeniably true, but market forces have yet >to produce viable examples of such implementations, so far as I can >tell.
Strictly speaking, market forces don't produce implementations? Surely they select among them instead. Moreover, they don't have to respect technical merit or performance or anything else.
Now, it was fairly easy on VAXes to find cases where Franz Lisp was faster than C. Moreover, for some time after Common Lisps appeared, Franz fit better with C and Unix than they did. Some CLs have passed Franz in some ways, but then development of Franz stopped years ago. Now we're starting to see Lisps that compile to C and pass arguments on the C stack (which KCL did to some extent in the mid 80s), that are packaged as shared libraries, that can be linked into C programs on a more or elss equal basis, etc. There are also roles for Lisp that don't involve competing with C but complementing C instead. What we now think of as a typical Lisp didn't have to be typical and may not be typical in the future. Whether market forces will take any notice is a different question.
>>I didn't say it was easy. But it's true that I don't think it's >>as hard as some other people seem too. Moreover, I blame particular >>Lisp implementations rather than "Lisp". >"Lisp", as opposed to particular lisp implementations, can only be >understood to refer to the concept of any member of a particular >family of programming languages.
Sure, but it's not confined to already existing members.
> The common usage of "lisp" implies a >language with certain features that make it difficult to implement in >a way that won't conflict with a Unix workstation's or PC's model of >the universe.
Well, so you say. (Actually, there's not a very good fit between C and some PC operating systems.) The standard machine for Lisp used to be the PDP-10. I suspect that Lisp machines have distorted perceptions of how well Lisp fits with "mainstream" machines. There are often actual problems with linkers, memory management, etc, but I don't think there's a fundamental mismatch with the hardware or even, in most cases, with the software.
> The richer and more featureful the lisp dialect, the >more difficult it has proven to be.
Common Lisp didn't have to be implemented the way it typically was.
>>Well, I (at least) have never made any claim about the number of >>machine instructions or indeed any "micro-level measure of compiler >>efficiency". So why are you saying this in response to me? >Because your earlier contribution to this thread came in the context >of and both quoted and added various statements about implementation >details and compiler efficiency that simply ignored the more general >issues that cause them to only address one small aspect of the whole >problem.
I still don't know what from my messages you have in mind.
> My central point all along has been that the choice of which >language to use for a particular project is a complex one due to the >many trade-offs entailed no matter which language is used.
But I agree with that.
> In the >absence of any contextual information about the nature of the >platform, the particular language implementations, and the >requirements of the application both of the statements "Lisp is better >than C" and "C is better than lisp" are either meaningless or false, >depending on one's semantic theory.
k...@triple-i.com (Kirk Rader) writes: >In article <CuL4nH....@cogsci.ed.ac.uk> j...@aiai.ed.ac.uk (Jeff Dalton) writes: >>My point here is that if a claim says "Lisp", the supporting >>evidence should be more general that popular commercial CLs. >I have also used various commercial and shareware non-Common Lisp >dialects on both Unix workstations and PC-class machines with similar >results. My point is not about any particular implementation of any >particular dialect, but about language-intrinsic features of lisp as a >class of programming language.
Yes, but I disagree with that point, to a fair extent, and even more with the way it has been argued. That you have observed cases that you've understood in a certain way doesn't show there's a language-intrinsic problem. You may well be right about typical implementations or most applications or something like that.
Of course, there will be some applications for which Lisp works less well than C. But so far as I can tell, there's no language- intrinsic feature that prevents there being cases where Lisp works as well as or better than C. Of course, maybe there's some lesser consequence we should consider.
> I did draw some particular examples >from a particular project implemented using a particular commercial >Common Lisp, but I also very explicitly stated that these were >intended to illustrate points about "lisp", as the term is commonly >understood, in general.
Sure, but illustration and demonstration are two different things. Illustrations would be useful if they let one see how the general claim was correct. So far, yours have not done so, at least not for me.
>>A straw man, since no one has said otherwise. >Your continuing focus on "lisp" as opposed to "particular lisp >implementations" shows that you are saying otherwise.
Bull. I have never thought or claimed that Lisp is (you said "connotes") "any language based on the lambda-calculus or any one that has generic features to support higher-order functions and a functional programming paradigm". That is, I agree that "Lisp connotes not not just" any such language.
It's possible, I suppose, that someone else disagrees, thus making it not a straw man, but it's not me.
>>Do you count reference counting as GC? >I am indifferent as to how you choose to categorize different >memory-management strategies, other than the basic difference between >languages which automatically allocate and deallocate memory and those >which only do so under explicit programmer control.
So you do count reference counting in your claim.
>Some form of >automatic memory allocation and recovery strategy is central to most >people's idea of what a lisp dialect entails.
It's also pretty essential to proper implementation of strings in Basic, but people don't go around saying Basic is inherently unsuited to workstations and PCs.
> If you choose to >include in the set of "lisps" some language which has a malloc() / >free() style of memory management, then that dialect would, of course, >be much less prone to memory-management conflicts with widely-used >OS's.
Well, I certainly include implementations that use reference counting and even ones that don't reclaim at all (see e.g. JonL White's paper in the 1980 Lisp conference), since I'm not planning to define "Lisp" so as to do violence to past usage. Now if you want to show that automatic reclamation inherently causes a mismatch with worstations and PCs, or whatever your acctual claim is, please do so. I would like to understand what the problem is.
>>Besides, there are a number of cases where Lisp's alloc + GC will be >>faster than "manual" alloc and dealloc. >And such cases are among those for which I have explicitly advocated >using lisp earlier in this and related threads.
So what _is_ supposed to be the problem with Lisp, then?
>>Now, if someone wants to argue that (say) a language with GC is >>necessarily slower than one that works like C, let them do so. >Not "necessarily slower", but in my experience it is more common in >real-world programming projects to encounter cases were C's >memory-management philosophy results in higher throughput and fewer >problems for interactivity and real-time response than one which >relies on GC.
Since this is probably not clear, let me say it explicitly. If someone came along in comp.lang.lisp and said
in my experience it is more common in real-world programming projects to encounter cases were C's memory-management philosophy results in higher throughput and fewer problems for interactivity and real-time response than one which relies on GC.
>>CL's I/O model is basically buffered streams. Sounds pretty much >>identical to that of C to me. A lot of CL implementations seem to >>have rather poor I/O but that's because the I/O systems aren't well >>written. >C's "minimalist" philosophy makes it much easier for the >implementation to provide alternative library entry points [open() vs >fopen(), etc.] and greater opportunity for the programmer to >circumvent whatever problems there are with a given library >implementation.
I've found that Lisp typically gives more opportunity to do that.
Anyway, in Franz Lisp, "ports" are alost directly FILE *s. Nothing prevents there being fd-based operations as well. (Indeed, there's an fdopen.)
>It is silly to suggest that C and Common Lisp are >really on a par when it comes to the amount semantic "baggage" they >carry for I/O or anything else. If that were true, what advantage >would lisp _ever_ have?
That Lisp has something extra doesn't mean it must always have excess baggage.
>C's memory-management philosophy is to rely on the standard-library's >interface to the OS. I do not see how this could be more different >from lisp's reliance on a built-in memory-management scheme.
What do you mean? Lisp uses the same OS operatins C does.
>And what possible relevence could it have that other software systems also >exhibit similar performance problems to those of lisp?
It suggests that the problems people observe with Lisp may not be due to Lisp, since they can (evidently) have other causes.
>>Can you give details? I have spent some time watching large CL (CMUCL) >>programs on Suns, and other than VM problems (and CMUCL's garbage >>collection is not exactly `state of the art') I find they do fine. >>And they weren't even very well written. >I specifically referred to using gr_osview on SGI's. In particular, >it is easy to observe conflicts between lisp's memory management and >I/O mechanisms and Irix's filesystem and memory-management mechanisms.
Can you say something more about this for those of us who can't us gr_osview on SGIs?
>> Lightweight processes are >>not part of CL BTW. >But they are part of almost every "serious" implementation of every >lisp dialect with which I am familiar, and I was not talking just about >some particular implementation of some particular dialect.
But they're not part of every serious implementation of every Lisp dialect, unless you make it true by definition of "serious".
And what is the problem for Lisp lw processes anyway?
>The question isn't whether it is possible to write programs in any >particular language that perform well, but rather for any given >programming task do the features of the language make it easier or >harder to achieve acceptable performance? The semantics of a language >which includes GC style memory management, lexical closures, so-called >"weak types", etc. has consciously chosen expressive power in favor of >highest-possible performance. In many cases that is an appropriate >choice, but in many cases it isn't.
The semantics of Lisp say objects (normally) have indefinite extent. Implementations typically use GC as a way to reuse storage. Whether this has to make it harder for programmers to obtain acceptable performance is not clear. It depends on the implementation and the application.
Inclusion of lexical closures in a language does not slow down cases that don't use them. So how is this part of a consistent choice of expressive power over highest possible performance?
k...@triple-i.com (Kirk Rader) writes: >In article <TMB.94Aug15222...@arolla.idiap.ch> t...@idiap.ch writes: >>So, if Irix can't cope with Lisp, that's a problem with Irix. And >>that problem will not just bite you with Lisp, but also with many >>other kinds of applications. >As someone who makes his living creating software for SGI's I cannot >afford to use any tool that does not run well under Irix, whether or >not Irix is particularly well designed. The fact is that there is a >whole SGI software industry, and if lisp evangelists would like to see >more cases of lisp being used there, they would have a greater >likelihood of success by suggesting that the lisp vendors do a better >job of accomodating the platform than that the platform vendor >accomodate lisp. It's a simple matter of economics.
That I agree with. But do you accept that Lisp vendors could do a better job, opr are there inherent properties of Lisp that prevent them from doing so (or from doing it to a sufficient extent)?
>In article <CuMuHo....@triple-i.com> k...@triple-i.com (Kirk Rader) writes: >> ... >> problem. My central point all along has been that the choice of which >> language to use for a particular project is a complex one due to the >> many trade-offs entailed no matter which language is used. [...] >Instead of all this complex analysis, which I'm not sure is going anywhere, >lets try some simple stuff for a change. Lets try this mind experiment. IF >there was a Lisp compiler that compiled as efficiently as C (or even close >to) and IF your boss said that you can program in either Lisp or C. What >would your choice be? Case closed (one way or the other). I hope. >There are so many more interesting aspects of Lisp that this news group can >be used for.
I agree. I wish people would stop using it to attack Lisp. Many of the same criticisms of Lisp could be made in a more constructive fashion and could include something to let us see exactlky what and how bad the problems are.
>In article <QOBI.94Aug15225...@qobi.ai> q...@qobi.ai (Jeffrey Mark Siskind) writes: >|In article <TMB.94Aug15224...@arolla.idiap.ch> t...@arolla.idiap.ch (Thomas M. Breuel) writes: >| >| The reason is that CL lacks >| important primitives for expressing some fundamental kinds of data >| abstractions in a space-efficient way (think about how much space your >| typical "struct { int x; double y; char z;};" takes as a CommonLisp >| DEFSTRUCT). >| >|What primitives does CL lack? The Scheme compiler that I am writing provides >|a DEFINE-STRUCTURE that is essentially a subset of the CL DEFSTRUCT. And it >|can produce *exactly* the code "struct { int x; double y; char z;};" for >|(DEFINE-STRUCTURE FOO X Y Z) when type inference determines that the X slot >|will only hold exact integers, the Y slot only inexact reals, and the Z slot >|characters. Note that it does this without any declarations at all. I presume >|that the same thing can be done for CL. >Sorry, I mixed two arguments into one. >Yes, for putting scalars into structures, you can generate reasonably >efficient code, but few CL compilers actually do. >However, when you nest those structures, put them into arrays, or pass >them as arguments, you have extra pointer and heap overhead.
Which is what, exactly?
>Furthermore, the compiler cannot statically decide to optimize the >pointer overhead away, since that is sometimes wrong (i.e., less >efficient) and can also change semantics. >It is incredibly useful to be able to specify reference vs. value >semantics, and CL lacks the primitives for doing that.
In article <330d8n$...@info-server.bbn.com> ch...@labs-n.bbn.com writes:
|isn't this a result comparable to that of declaring types? if I took a |casually written lisp program and converted it to C, I'd have to declare |lots more variables types than i did in lisp.
The problem is that even if you add the same number (or more) declarations to your Lisp program, on many Lisp implementations it would still not run as fast as the corresponding C program. And there is no standard way of figuring out why.
For example, in CMU CL, at some point, FLOOR was much slower than TRUNCATE because FLOOR didn't get inlined. In Lucid, adding redundant declarations could slow down your program. Trying to track down the sources of such problems is just as hard as trying to track down a compiler bug or a pointer bug in C (actually, harder than a pointer bug if you have Purify for C...).
Another problem is that if you want to get memory utilization in CommonLisp that is as efficient as in C, you often have to change your program logic radically, in ways that are much less abstract than in C. For example, arrays of structures end up having one pointer and one structure header overhead for each element ("struct { int x,y; } foo[N];"). Structures having multiple "small" objects do not get packed by most CommonLisp implementations ("struct { char x,y,z; } foo[N];"). Structures of fixed-size arrays have a pointer plus an array header overhead for each element ("struct { float vect1[3],vect2[3]; } foo[N];").
The only way to program around those limitations is to convert everything to FORTRAN-style code, where you don't use structures and rely on monotyped arrays of characters, bytes, and floating point numbers and use array indexes as pointers. If you do program FORTRAN-style, it is usually relatively easy to get good performance in CommonLisp (there are still some gotchas to watch out for), but most people choose Lisp in order to have convenient and powerful means of expressing their algorithms at their disposal, not to be squeezed into FORTRAN-style programming.
That different kinds of languages are best suited to different kinds of tasks, so saying that "language X is better than language Y" is false or meaningless without specifying better for _what_.
Your previous posting amounted to saying "lisp is better because, other things being equal, wouldn't you rather use it?" I am paraphrasing, but that is what I understood you to be saying. I have been explicitly talking all along about cases for which other things are _not_ equal. If you really know that the cost of implementing lisp's more powerful features relative to a C-like language will not in fact result in unacceptable performance for a given application then it is true either that lisp is better (if you also intend to use those features) or at least, as you stated, the choice of language is simply a matter of taste, or organizational requirements, or whatever. In my experience, however, there is a significant class of applications for which the cost of implementing lisp's features has proven to be too high, such that C-like languages are in fact better in those cases just as the existence of lisp's more powerful features make it a better choice in others.
>Yes, but I disagree with that point, to a fair extent, and even >more with the way it has been argued. That you have observed cases >that you've understood in a certain way doesn't show there's a >language-intrinsic problem. You may well be right about typical >implementations or most applications or something like that.
a It is hardly fair to excerpt only those quotes from a long thread which refer to specific examples and then complain that the argument is based solely on particular implementation details. This thread has been going on for weeks now (hopefully it won't for weeks more!) and most of the concrete examples to which you refer were offered as "existence proofs" to people who claimed that arguments based solely on general principles were unconvincing. I do not blame someone who has never (presumably because they have been working in a problem domain to which lisp is well-suited) encountered these kinds of unacceptable performance problems to require concrete examples. I consider it false to say that in this thread I have relied solely on such specific examples.
>Of course, there will be some applications for which Lisp works >less well than C. But so far as I can tell, there's no language- >intrinsic feature that prevents there being cases where Lisp works >as well as or better than C. Of course, maybe there's some lesser >consequence we should consider.
I have repeatedly agreed that that there are applications for which lisp is better suited than C.
[...]
>Sure, but illustration and demonstration are two different things. >Illustrations would be useful if they let one see how the general >claim was correct. So far, yours have not done so, at least not >for me.
But you seem to have ignored the many other quotes in many messages in this same thread that did refer to the kind of general principles that you claim are lacking in my argument. Rather than repeat a large number of them here, let me ask the following question. Since lisp's semantics are unarguably richer and more powerful than C's, how do you expect any implementation to obtain them for free? It seems elementary to me that if a language is intrinsically more powerful, it will be intrinsically more complex and have more overhead in its implementation. For many applications, the greater expressive power of lisp more than pays for itself. For many others, it doesn't. It is an open question for any given application into which class it falls.
[...]
>Bull. I have never thought or claimed that Lisp is (you said >"connotes") "any language based on the lambda-calculus or any >one that has generic features to support higher-order functions >and a functional programming paradigm". That is, I agree that >"Lisp connotes not not just" any such language.
Bull yourself. You have several times tried to argue lisp's performance "problems" (the quotes around "problems" is to emphasize that I consider them real problems only for some applications, since you seem to be missing that point fairly consistently) are not real based on how it could run on hypothetical platforms or how it could evolve so as to avoid the features that have been performance stumbling blocks. I have been explicitly referring to existing dialects running on current platforms, and used the word "connotes" deliberately so as to emphasize the particular usage of the word "lisp" I was referring to.
>>>Do you count reference counting as GC?
>>I am indifferent as to how you choose to categorize different >>memory-management strategies, other than the basic difference between >>languages which automatically allocate and deallocate memory and those >>which only do so under explicit programmer control.
>So you do count reference counting in your claim.
As I said in the quote which I left in, above, I do not count reference counting per se either in or out of my "claim". There are for example, a number of standard idioms used in C and C++ that use reference counting, sometimes to good effect and sometimes not, but which still never allocate anything "behind the programmer's back", as it were. I do not count this as a GC-based approach, even though reference counting can be used to implement a GC. The critical difference is that in the non-GC use of reference counting, even when a "deallocation" is deferred due to a positive count, the block of memory by definition is still not "garbage".
[...]
>It's also pretty essential to proper implementation of strings >in Basic, but people don't go around saying Basic is inherently >unsuited to workstations and PCs.
"People" may not, but I certainly would say that the class of applications for which Basic is well-suited is probably smaller than the classes of applications for which either lisp or C is well-suited. I also am not among those "people" who say that "lisp inherently unsuited to workstations and PCs." I have only ever claimed that there exist applications for which lisp is not particularly well-suited, just as there are applications for which C or any other particular language is not well-suited.
[...]
>Well, I certainly include implementations that use reference counting >and even ones that don't reclaim at all (see e.g. JonL White's paper >in the 1980 Lisp conference), since I'm not planning to define "Lisp" >so as to do violence to past usage. Now if you want to show that >automatic reclamation inherently causes a mismatch with worstations >and PCs, or whatever your acctual claim is, please do so. I would >like to understand what the problem is.
This particular problem is that for some applications GC is not the optimum memory-management strategy, even though there are applications for which it is. My rule of thumb is that if an application needs to make many small allocations, GC is likely to be the ideal memory management strategy. If an application needs to make only a few but large allocations, malloc / free is likely to be more efficient for the application as a whole.
[...]
>So what _is_ supposed to be the problem with Lisp, then?
Again, "the problem with Lisp" is only a problem for those applications for which lisp's semantics are not a good fit. Of course, there are also applications for which lisp's sematics are a better fit than, say, C's, so in those cases "the problem" would be with C. What started all this was my taking exception with claims that lisp was always or almost always as good or better a choice than C or C++, and that all claims of it being "too big" or "too slow" for any particular application were ill-founded.
[...]
>Since this is probably not clear, let me say it explicitly. >If someone came along in comp.lang.lisp and said
> in my experience it is more common in real-world programming > projects to encounter cases were C's memory-management philosophy > results in higher throughput and fewer problems for interactivity and > real-time response than one which relies on GC.
In article <Cusnxr....@festival.ed.ac.uk> j...@festival.ed.ac.uk (J W Dalton) writes:
[...]
>That I agree with. But do you accept that Lisp vendors could >do a better job, opr are there inherent properties of Lisp that >prevent them from doing so (or from doing it to a sufficient extent)?
Well, both. I know that some vendors, at least, are working very hard to correct many of the particular kinds of performance issues I have raised. But I just don't see how it can be thought that one language which is inherently more powerful than another won't necessarily have made some performance trade-offs in order to achieve that extra power. So. I expect that it will always be the case that there will be some applications that are best done in a lower-level language. I don't anticipate a time when some "one size fits all" language will have been developed that makes it suitable for every type of application.
>I've found that Lisp typically gives more opportunity to do that.
Well then, I can only say our experiences have been different.
>Anyway, in Franz Lisp, "ports" are alost directly FILE *s. >Nothing prevents there being fd-based operations as well. >(Indeed, there's an fdopen.)
Nothing prevents it, perhaps, but nothing encourages it particularly either. The fact that particular implementations may provide particular hooks into the underlying OS just seems to me to confirm the necessity from time to time of bypassing lisp's higher level functionality. QED
[...]
>That Lisp has something extra doesn't mean it must always have >excess baggage.
How do you get the "something extra" for free?
[...]
>What do you mean? Lisp uses the same OS operatins C does.
And it imposes a significantly more complex additional layer of functionality on top of it. If this additional complexity pays for itself, as it does in many cases, well and good. But in many other cases, the additional complexity doesn't pay for itself. In those cases I would consider it "excess baggage" (as opposed to "useful or necessary baggage".)
[...]
>It suggests that the problems people observe with Lisp may not be >due to Lisp, since they can (evidently) have other causes.
Or, as I believe is actually the case, that other systems sometimes suffer symptoms due to the same or similar causes as lisp.
[...]
>Can you say something more about this for those of us who can't >us gr_osview on SGIs?
Irix has a fairly complex buffer-management scheme of its own which is implemented at the lowest level of the filesystem and VM substrates. Due to the multiple layers of functionality referred to above, the I/O mechanisms of the particular lisp implementation that I was using in this example were causing unnecessary cache and page thrashing due to more memory being allocated per I/O operation than was necessary, or is typical in applications that use the standard library calls directly.
[...]
>But they're not part of every serious implementation of every >Lisp dialect, unless you make it true by definition of "serious".
If you want to exclude that particular example from your consideration on such grounds, by all means do so. For the particular application on which I work and which I was using as an example, we could not use any implementation of any dialect that did not include such a facility, since it is a requirement of the design of our suite of integrated applications.
>And what is the problem for Lisp lw processes anyway?
The same as with lisp memory-management. The additional layer of OS-like functionality on top of the real OS.
[...]
>The semantics of Lisp say objects (normally) have indefinite extent. >Implementations typically use GC as a way to reuse storage. Whether >this has to make it harder for programmers to obtain acceptable >performance is not clear. It depends on the implementation and >the application.
>Inclusion of lexical closures in a language does not slow down >cases that don't use them. So how is this part of a consistent >choice of expressive power over highest possible performance?
>-- jd
Because one can only avoid the overhead inherent in using lexical-closures by choosing not to use them (without even raising the issue of whether they get used in the run-time system, outside of the application programmer's control.) If one must exercise greater awareness of performance issues in order to specifically avoid using exactly those features of lisp that make it more powerful in order to achieve acceptable performance for a particular application, than how could it be considered other than a handicap? For such an application I would expect the programmer to be more productive and the application to require less debugging and performance tuning if it had been developed in C to start with. For other applications, where the nature of the application is such that lisp's more powerful features are an asset rather than a liability, the advantage would clearly go to lisp.
>>> ... >>> problem. My central point all along has been that the choice of which >>> language to use for a particular project is a complex one due to the >>> many trade-offs entailed no matter which language is used. [...]
>>Instead of all this complex analysis, which I'm not sure is going anywhere, >>lets try some simple stuff for a change. Lets try this mind experiment. IF >>there was a Lisp compiler that compiled as efficiently as C (or even close >>to) and IF your boss said that you can program in either Lisp or C. What >>would your choice be? Case closed (one way or the other). I hope.
>>There are so many more interesting aspects of Lisp that this news group can >>be used for.
>I agree. I wish people would stop using it to attack Lisp. >Many of the same criticisms of Lisp could be made in a more >constructive fashion and could include something to let us see >exactlky what and how bad the problems are.
Since you included a quote from me in this, I assume you consider me to be one of those who has been attacking lisp. I do not feel that to be the case. I also think that it is a little hypocritical to criticize the same line of argument for being both "too dependent on illustrative examples" and "not including anything to see what the problems are" (my paraphrase) as you have in this set of related messages.
My repeatedly emphasized point is not deep, mysterious, hard to grasp, or even requiring much in the way of complex justification or analysis. A higher level language like lisp will have made performance trade-offs making it a better choice of language for some applications and a worse choice for others relative to a lower-level language like C. All of the lengthy thread which has ensued is, I believe, the result of people who feel so threatened by any suggestion that there can be any application for which lisp is not the best choice of implementation language that they have felt it necessary to vehemently attack what were mild observations of (to me. at least) obvious truths.
From: ch...@labs-n.bbn.com Date: 18 Aug 1994 19:36:55 GMT ... some years ago, when i was porting Macsyma to the Explorer, I fiddled with cons-areas, wondering if I could do a better job of controlling GC occurrences myself. the idea was that I would allocate an area, work in it, copy a result out of it and immediately free the area, avoiding having to GC that area, cutting the cost of a GC when it finally did occur. this was before generational GC had become available. Macsyma is/was horrible about generating garbage.
The problem of "intermediate expression swell" is innate in many computer algebra calculations and is not necessarily specific to Macsyma. In fact Macsyma was one of the driving forces behind Moon's original ephemeral GC implementation for MIT Lispms, as well as many other features of MacLisp/Lispm-lisp that made their way into CLtL2. Of course once can optimize using temporary consing areas, but if you go too far you are almost doing the same thing as you would in C with malloc/free.
Date: 19 Aug 1994 21:10:48 GMT From: ch...@labs-n.bbn.com
disassembling this shows that it's only got 13 instructions, excluding the FEF overhead. I don't know how many registers the LispChip has, but it appears to be only one (!?) from looking at the assembly code.
At the macroinstruction level, it's a stack machine, with some shortcuts and warts in various places. Most instructions leave their result(s) on the stack, and args and locals are kept there (the top 1K is buffered on-chip). At the microcode level, it's mostly register-to-register with 32 pseudo-two-ported and 992 scratch registers (and at times in the past we had experimental microcodes that implemented stack-accumulator and register-window architectures).
As for the multiply speed, my memory and the 1987 chip spec suggest that the only hardware assist was support for a two-bit-per-step Booth algorithm for 32-bit integer multiply. Plus, floats are consed; header word plus 32 or 64 bits of data (but consed in a special area that's GC'd quickly and frequently).
Yeah, there are still some lispm people out here. I'm typing this on a Sun with the diamond keys mapped to Control and Control to Rubout (but I read mail on the Explorer).
Paul Fuqua Texas Instruments, Dallas, Texas p...@hc.ti.com
>> entirely in a commercial Common Lisp, using lisp to implement all of > ^^^^^^^^^^^^^^^^^^^^^^^ >> the bells-and-whistles like multi-threading that a large-scale > ^^^^^^^^^^^^^^^ >> application is likely to require.
>That's what I hate the most about current implementations. >Take advantage of the OS. Do not rewrite it. >No wonder if performance and COMPATIBILITY stink..
What exactly is the problem with providing (multiple) threads for Lisp programs? If the OS-/C-library-provided lw process mechanism isn't sufficient, what are we supposed to do? Give up?