Re: Re: Pragmatic Requirements Summary : update

Brian Hurt <[email protected]> Tue, 5 Aug 2003 17:20:12 -0500 (CDT)
Newsgroups gmane.comp.programming.pragmatic
Message-ID <[email protected]>
On Tue, 5 Aug 2003, Eric Merritt wrote:

>  There have and are lisps that perform quite well. As a general rule
> they do not outperform C, however in may contexts they can beat C. In
> most contexts they are only a factor of 2 or 3 slower then C. A good
> example of this is CMUCL and its python compiler (no not python the
> langauge, python the compiler). It is very good at generating
> efficient code. From my understanding the commercial implementations
> of lisp generate even better code.

Notice that CMUCL is a native-code compiler.  I wasn't comparing the speed
of LISP to C, I was comparing the speed of interpreted implementations to
statically compiled implementations.

It's not the language which is fast or slow, so much as as the code 
written in the language, and the implementation of that language which is 
used.  The problem with code-as-data is that it encourages the interpreted 
implementations.

Here's an intriguing "what if"- on how a functional language like LISP or 
ML could be signifigantly faster than C.  No one has done this yet (any 
gradual students out there looking for a PhD thesis topic?), but it should 
be done.

The main limitation in computer architecture right now is the limitations 
on instruction level parallelism- how many instructions can be issued at 
once.  For imperitive (C and Fortran) programs, the practical limit seems 
to be 5-7 instructions issued at once:
http://citeseer.nj.nec.com/wall90limits.html

The functional units on a CPU- the circuits that actually do the "real 
work" of adding and subtracting and what have you- are becomming a 
vanishingly small portion of the transitors used.  Most of the rest of the 
chip is various amounts of support to attempt to take better advantage of 
the small number functional units- especially cache (which reduces the 
average amount of time the functional units need to stall waiting for 
memory) and instruction scheduling (which looks for that small handfull of 
instructions which can be executed).  It'd be trivial to add more 
functional units to a CPU- but pointless, as they'd almost never be used.  
You can't use more than 5-7 functional units.

Except what if you could?  Consider the following fragment of Ocaml:
	let x = foo a b
	and y = bar a b
	in
	...

Now, assuming foo and bar are purely functional, there is no dependency 
between them.  You can execute the call to foo first, or the call to bar 
first, and neither will notice.  Or- and here's the trick- you can inline 
them both, and intermingle their execution.  If foo has an average ILP of 
(say) 4 instructions, and so does bar, then their intermingled ILP would 
be 8 instructions.  Every clock you could execute 4 instructions from foo, 
and 4 more isntructions from bar.

I'm simplifying a lot here, but this gets across the core of my idea.  
That purely functional programming may expose parallelism that imperitive 
programming doesn't.  And give optimization opportunities commensurate 
with that.  This is especially important on CPUs like the Itanium, where 
the compiler can express this parallelism directly.

>  Most of this performance penalty can be made up in large programs
> with using the right alsgorithm. You made this point yourself.

Yep.  Interpretation is just a constant factor slowdown- easily overcome
by better algorithms.  Also, large hunks of the programming world simply
aren't that performance bound.  Generally anytime you're talking to a
database, the database is your main slowdown.  User I/O is also very slow.  
I had a friend who got bitched at once for writting a DB query in Perl,
when C was so much faster.  His response was that the query was hitting 
the optical jukebox, and would take 15 minutes to complete.  Wether the 
program spawning the query took 10 milliseconds or 100 milliseconds to run 
probably wasn't going to be an issue.

Most programmers, in my experience, have no clue where performance comes 
from or goes to.

>  
> >  
> > 2) Correctness.  How can you be sure for all inputs that the code  
> > generated is correct? 
>  
>  A program can only modify itself according to its input. If you know
> the input then the output is a foregone conclusion. Not that it cant
> be complex.

The fact that any given input will create a reproducable, and in some 
sense even predictable, result is not in question.  The question is wether 
the output it produces is the one *intended*.  Otherwise I can simply 
replace any program with the following C code:
#include <stdio.h>
int main (int argc, char ** argv) {
    fprintf(stderr, "Fatal error- segment fault.  Program exiting.\n");
    return -1;
}

Hey, it produces an output!  Probably not the one you were intending, 
but...

>  CMUCL's python compiler uses type inference to achieve its goals.
> Type inference and dynamic typing are not mutually exclusive. In fact,
> I would say they complement each other.

Yep.  There's been more than one point where I've wished that ocaml had 
"instanceof" or something similiar.  I'm just arguing against "instead 
of".

Brian



------------------------ Yahoo! Groups Sponsor ---------------------~-->
Buy Ink Cartridges or Refill Kits for Your HP, Epson, Canon or Lexmark
Printer at Myinks.com. Free s/h on orders $50 or more to the US & Canada. http://www.c1tracking.com/l.asp?cid=5511
http://us.click.yahoo.com/sO0ANB/LIdGAA/ySSFAA/W4wwlB/TM
---------------------------------------------------------------------~->

To unsubscribe from this group, send an email to:
pragmatic_lang-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/