Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
Robert
--
Robert AH Prins
prino@onetel.net.uk
|
|
0
|
|
|
|
Reply
|
prino
|
5/26/2004 2:44:56 PM |
|
Robert AH Prins wrote:
>
> Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
"The programmer should make a conscious decision to choose a less
efficient implementation over a more efficient implementation
based on economic or engineering concerns, rather than simply utilizing
the first implementation that comes to mind."
Damn! *That's* what's wrong with my code! :)
Best,
Frank
|
|
0
|
|
|
|
Reply
|
Frank
|
5/26/2004 6:35:20 PM
|
|
Robert AH Prins wrote:
> Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
>
> Robert
Mr. Hyde and I fully agree on the need for any modern programmer worth
his salt to know assembly language.
However, the article degenerates into a sales campaign for his pet
"HLA" project. How anyone can call MASM a good example of an assembler
is beyond me. Its a complete abomination, not really designed, but more
thrown together at random, with a ridiculous typing system that dramatically
reduces the clarity of the assembly functions being coded, something
Mr. Hyde claims to not want.
Further, the idea that we need "high level assembly" as a go between
assembly and high level language based on flawed logic. The reality of
todays program environment is that code is done in high level language,
and assembly routines are used to solve special problems such as access
to instructions that don't exist in HLL, or special problems with device
accesses, etc. When I turn out a single page routine to solve a special
problem, I am doing so with the mind set that I want to get all the power
of the assembly language (as Mr. Hyde appears to want). But that means
I want to see the assembly code EXACTLY as it will be fed to the machine.
I don't want macros, high level constructs or similar features. Often I
even override the assemblers "autosizing" on features like jumps. Ie., I
want to see a 32 bit jump when I ask for one, or an 8 bit jump, etc.
Typically I have hard timing requirements that dictate this.
In short, "high level assembly" fills a need I, and apparently many other,
programmers don't have. I code mostly in HLL, and I need good, short
assembly routines to complement it. I don't need or want in "in-between"
tool that combines the lack of insight into the machine that HLL inflicts
with the lack of portability of pure assembly language.
Mr. Hyde is an assembly language zealot, there is certainly a place for
that. However, he also is clearly biased against high level languages
in general (see several articles from his web site), and is flogging
high level assemblers, and old idea which has been tried and discarded
over and over since the 1950's.
In conclusion, a programmer who cannot code assembly is not worth his salt.
Programmers who insist on any approach as a religion should be taken with
a grain of salt.
|
|
0
|
|
|
|
Reply
|
Scott
|
5/28/2004 5:50:51 PM
|
|
On Fri, 28 May 2004 17:50:51 +0000 (UTC), Scott Moore
<samiam@moorecad.com> wrote:
<snip>
>In short, "high level assembly" fills a need I, and apparently many other,
>programmers don't have. I code mostly in HLL, and I need good, short
>assembly routines to complement it. I don't need or want in "in-between"
>tool that combines the lack of insight into the machine that HLL inflicts
>with the lack of portability of pure assembly language.
My understanding is that HLA wasn't particularly written for those of
us who already know assembly, but for beginners who are best served
by something to ease the transition from a conventional HLL.
I can't comment on how well it succeeds on that account, since it's
been too many years since the time it might have helped!
Bob Masta
dqatechATdaqartaDOTcom
D A Q A R T A
Data AcQuisition And Real-Time Analysis
www.daqarta.com
|
|
0
|
|
|
|
Reply
|
NoSpam
|
5/28/2004 7:05:06 PM
|
|
"Scott Moore" <samiam@moorecad.com> wrote in message
news:X2Ctc.21201$eT4.20696@attbi_s54...
> Robert AH Prins wrote:
> > Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
> >
>
> However, the article degenerates into a sales campaign for his pet
> "HLA" project.
Interesting comment. Out of several thousand words present in that article,
here is the only text that mentions HLA:
>>>>
Still on the crusade, I started to work on a brand-new,
high-level assembler (HLA, the High-Level Assembler),
a new version of The Art of Assembly Language, and a
new, 32-bit, HLA-based set of library routines. This effort
culminated with the release of the published edition of
The Art of Assembly (AoA) in 2003. To date, thousands
and thousands of programmers have enthusiastically embraced
this new way of learning assembly language using AoA,
HLA, and the HLA Standard Library.
<<<<<
Hardly what I would consider "degenerating into a sales campaign"
for the "HLA project".
The problem with such an article, of course, is that people on
both sides of the "assembly vs. HLLs" get so emotional about
the subject that they start reading between the lines and making
stuff up. I really like the comments, for example, from the
"anti-assembly" crowd that make statements about how stupid
the author is for suggesting that people write assembly language
code. In fact, if they'd have bothered to *read* the article, they'd
have noticed that it makes *no* such claims. In fact, the article
explicitly states:
>>>>>>>>>>>>
Though it would be foolish to start claiming that programmers should begin
writing commercial applications in assembly language, it is clear today that
the demise of assembly language's popularity has had a big impact on the
efficiency of modern software.
<<<<<<<<<<<<
Whoops! I guess all those people arguing that the article is
preaching about a return to assembly completely missed this.
> Mr. Hyde is an assembly language zealot, there is certainly a place for
> that. However, he also is clearly biased against high level languages
> in general.
I guess you really missed the whole point of this article too.
Just to make it clear to you, the article is pushing my
"Write Great Code" project, which teaches low-level style
programming *IN HIGH-LEVEL LANGUAGES*.
> How anyone can call MASM a good example of an assembler
> is beyond me.
That would be *your* opinion. However, given that MASM v6
is the most popular assembler ever created, learned and used
by more people than any other assembler ever created, and
emulated by several assemblers (e.g., TASM and OPTASM),
well, I'd say that most people disagree with you.
You are, however, welcome to your opinion.
> Its a complete abomination, not really designed, but more
> thrown together at random, with a ridiculous typing system that
dramatically
> reduces the clarity of the assembly functions being coded, something
> Mr. Hyde claims to not want.
Where on Earth did you *ever* get the idea that I don't want
a typing system in assembly language? If this were true, how do
you explain the strong typing system in my pet project, HLA?
>
> Further, the idea that we need "high level assembly" as a go between
> assembly and high level language based on flawed logic. The reality of
> todays program environment is that code is done in high level language,
> and assembly routines are used to solve special problems such as access
> to instructions that don't exist in HLL, or special problems with device
> accesses, etc.
I believe you miss the whole point of HLA, which is to teach beginners
(who know a HLL) assembly so they can understand the low-level
operation of their CPU. This, for example, helps them write better
HLL code. If they really want to write assembly code after learning
assembly, they may continue to do so in HLA (which offers just about
every low-level feature other assemblers provide) or they can switch
to another assembler such as MASM, FASM, whatever.
> When I turn out a single page routine to solve a special
> problem, I am doing so with the mind set that I want to get all the power
> of the assembly language (as Mr. Hyde appears to want). But that means
> I want to see the assembly code EXACTLY as it will be fed to the machine.
HLA allows you to do this, what's your problem?
> I don't want macros, high level constructs or similar features.
And you don't have to use them.
> Often I
> even override the assemblers "autosizing" on features like jumps. Ie., I
> want to see a 32 bit jump when I ask for one, or an 8 bit jump, etc.
> Typically I have hard timing requirements that dictate this.
I suppose you also need to control the opcode emission for mov reg, reg
for timing purposes, too :-)
Seriously, I hope you're writing code for a *single* CPU. Because if
your optimizing jump displacement size (presumably to align targets
appearing later in your code), then your optimizations aren't going to
apply generally across the x86 family. This is fine for certain
applications,
but a waste of time for most applications. If this kind of optimization is
"typical" for you, I'd love to know what you *typically* work on.
Because for most applications, this type of optimization buys you very
little.
>
> In short, "high level assembly" fills a need I, and apparently many other,
> programmers don't have.
Yes, you already know assembly. HLA was not designed for you.
I'm not expecting you to switch to HLA from some other assembler,
that would be a lot of work and your attitude certainly suggests you
wouldn't benefit at all from that work. But now consider a beginner
who doesn't already know an assembler or an existing assembly
syntax. But they *do* know a HLL. Something like HLA offers
a great path from the HLL to assembly, that lets them make the
transition much more smoothly.
That is the intended audience for HLA, and given books sales
and usage in Colleges and Universities, I'd suggest that HLA is
doing quite well for its intended audience.
> I code mostly in HLL, and I need good, short
> assembly routines to complement it. I don't need or want in "in-between"
> tool that combines the lack of insight into the machine that HLL inflicts
> with the lack of portability of pure assembly language.
Again, there's very little you can do with any other assembler that
can't be also done with HLA. Obviously, you haven't looked much
into HLA, or you'd realize this.
> (see several articles from his web site), and is flogging
> high level assemblers, and old idea which has been tried and discarded
> over and over since the 1950's.
Actually, if you read the articles a little more closely, you find that
the first mention of high-level assemblers describes a product built
in the middle 1960's. Some high-level assemblers have become
*very* popular, e.g., PL/M. However, it wasn't until MASM v6
came along that a fully-featured high-level assembler (that provided
all the low-level features of assembly combined with some HLL-like
features) became popular. Today, the majority of new assembly
code being written is being written in MASM using a high-level
assembly programming style. That may not be *your* preferred
style of programming, you may not *like* that this is happening
with assembly, but it kind of contradicts your statement that
this idea has been discarded. Indeed, one could easily argue that
MASM v6 plus Hutch's MASM32 package and the Iczelion
tutorials (which really jump started the usage of high-level
assembly coding) are largely responsible for the recent
resurgence in interest in assembly language programming.
Hardly a "discarded idea" if you ask me.
>
> In conclusion, a programmer who cannot code assembly is not worth his
salt.
I agree.
>
> Programmers who insist on any approach as a religion should be taken with
> a grain of salt.
I agree.
And I would add that any programmer who immediately dismisses
any approach on near religious grounds should also be taken with
a graiin of salt.
Cheers,
Randy Hyde
>
|
|
0
|
|
|
|
Reply
|
Randall
|
5/29/2004 5:05:05 AM
|
|
On Sat, 29 May 2004 05:05:05 +0000 (UTC)
"Randall Hyde" <randyhyde@earthlink.net> wrote:
:The problem with such an article, of course, is that people on
:both sides of the "assembly vs. HLLs" get so emotional about
:the subject that they start reading between the lines and making
:stuff up.
As the Simon and Garfunkel song so aptly put it, "A man hears what he wants
to hear, and disregards the rest".
|
|
0
|
|
|
|
Reply
|
Charles
|
5/29/2004 5:23:29 AM
|
|
Randall Hyde wrote:
<clip>
Randall, we have talked before. Quite a bit of your reply consisted of
your misunderstanding or perhaps not even really reading what I wrote.
I have been in letter exchanges where I am continually attempting to
correct misunderstandings on the other parties part, it is a losing
game.
I simply believed that your article needed a counterpoint. I provided that.
|
|
0
|
|
|
|
Reply
|
Scott
|
5/29/2004 6:31:43 PM
|
|
> > Further, the idea that we need "high level assembly" as a go between
> > assembly and high level language based on flawed logic. The reality
of
> > today's program environment is that code is done in high level
language,
> > and assembly routines are used to solve special problems such as
access
> > to instructions that don't exist in HLL, or special problems with
device
> > accesses, etc.
> I believe you miss the whole point of HLA, which is to teach beginners
> (who know a HLL) assembly so they can understand the low-level
> operation of their CPU. This, for example, helps them write better
> HLL code. If they really want to write assembly code after learning
> assembly, they may continue to do so in HLA (which offers just about
> every low-level feature other assemblers provide) or they can switch
> to another assembler such as MASM, FASM, whatever.
FWIW, I am pretty new to Assembly programming. I have been studying x86
for the last 5 years but haven't gotten very far. That said, I have
come across Mr. Hyde's HLA several times, but it and the books related
to it will not fill the need I have for assembly. That said, let me
explain what _my_ need it....
I am a student of writing operating systems. I enjoy the low level
stuff, and I am working on writing my own operating system. I have
wanted to learn assembly to write the low level details of the operating
system - boot sector, etc. - but HLA and its resultant books/etc don't
provide that kind of information. As a beginner, I would really
appreciate a book that taught Assembly for what it really is - a
language that controls the entire computer - and at the undergraduate
level. I would really appreciate a book that started with a Hello World
boot sector and helped build a system, showing the full power of the
language, and showing the constructs with real examples. (Of course,
it'd have to have an environment like Bochs or VMware for testing.)
"Randall Hyde" <randyhyde@earthlink.net> wrote in message
news:MPUtc.14544$Tn6.5725@newsread1.news.pas.earthlink.net...
> "Scott Moore" <samiam@moorecad.com> wrote in message
> news:X2Ctc.21201$eT4.20696@attbi_s54...
> > Robert AH Prins wrote:
> > > Here
<http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
> > How anyone can call MASM a good example of an assembler
> > is beyond me.
> That would be *your* opinion. However, given that MASM v6
> is the most popular assembler ever created, learned and used
> by more people than any other assembler ever created, and
> emulated by several assemblers (e.g., TASM and OPTASM),
> well, I'd say that most people disagree with you.
> You are, however, welcome to your opinion.
>From my time spent reading the NASM mailing list, I would be to differ.
MASM handles several things incorrectly and is a sloppy implementation.
Its popularity comes from the fact that it is provided from Microsoft
and is taught at most schools that teach Microsoft style programming.
It's like Newton's law in physics - things that are in motion tend to
stay in motion. So, likely, MASM will continue to be used so long as
Microsoft has motion behind them.
> > Its a complete abomination, not really designed, but more
> > thrown together at random, with a ridiculous typing system that
> dramatically
> > reduces the clarity of the assembly functions being coded, something
> > Mr. Hyde claims to not want.
> Where on Earth did you *ever* get the idea that I don't want
> a typing system in assembly language? If this were true, how do
> you explain the strong typing system in my pet project, HLA?
Typing has nothing to do with Assembly. That much I know. Typing is
purely a HLL construct. Assembly's power is its lack of typing.
> > I don't want macros, high level constructs or similar features.
> And you don't have to use them.
True.
> > Often I
> > even override the assemblers "autosizing" on features like jumps.
Ie., I
> > want to see a 32 bit jump when I ask for one, or an 8 bit jump, etc.
> > Typically I have hard timing requirements that dictate this.
> I suppose you also need to control the opcode emission for mov reg,
reg
> for timing purposes, too :-)
>
> Seriously, I hope you're writing code for a *single* CPU. Because if
> your optimizing jump displacement size (presumably to align targets
> appearing later in your code), then your optimizations aren't going to
> apply generally across the x86 family. This is fine for certain
> applications,
> but a waste of time for most applications. If this kind of
optimization is
> "typical" for you, I'd love to know what you *typically* work on.
> Because for most applications, this type of optimization buys you very
> little.
>
> >
> > In short, "high level assembly" fills a need I, and apparently many
other,
> > programmers don't have.
> That is the intended audience for HLA, and given books sales
> and usage in Colleges and Universities, I'd suggest that HLA is
> doing quite well for its intended audience.
One of my professors kept using a book for probably about 10 years. The
book was full of mistakes (grammar, spelling, etc.) , incorrect
translations, and terrible. But he kept using it for some reason. Books
sales don't necessarily mean a good book, or that a book is meeting the
needs of its audience - especially a book targetted at academia. Rather,
it means that a number of professors are pushing the book; perhaps they
think it might be useful, or perhaps the book mediates between where
they are (or their point of view) and the course they have to teach.
> > In conclusion, a programmer who cannot code assembly is not worth
his
> salt.
> I agree.
I very much agree. Even with my limited exposure to assembly and only
having it just start coming together - i.e. I have only recently been
able to start writing boot sectors from scratch to the same level of
where I was able to get them with help, e.g. by copying code or
constructs in order to learn what is going on - that limited exposure
has certainly influenced my HLL programming and thinking.
That said - I do respect Mr. Hyde for his continued teaching of
assembly. I wish more people would do so. I also wish more people would
teach programming a computer with nothing other than the BIOS for
services. Programmers today are just not what the use to be, and the
usage of Java in academia is not helping in any way either.
Ben
|
|
0
|
|
|
|
Reply
|
Ben
|
5/30/2004 11:14:06 PM
|
|
"Ben Meyer" <bmeyer67@verizon.net> wrote in message
news:Gcruc.11539$Lq1.1449@nwrddc03.gnilink.net...
>
> I am a student of writing operating systems. I enjoy the low level
> stuff, and I am working on writing my own operating system. I have
> wanted to learn assembly to write the low level details of the operating
> system - boot sector, etc. - but HLA and its resultant books/etc don't
> provide that kind of information. As a beginner, I would really
> appreciate a book that taught Assembly for what it really is - a
> language that controls the entire computer - and at the undergraduate
> level. I would really appreciate a book that started with a Hello World
> boot sector and helped build a system, showing the full power of the
> language, and showing the constructs with real examples. (Of course,
> it'd have to have an environment like Bochs or VMware for testing.)
Well, when you find such a book for some other assembler, let us
all know. :-).
BTW, other than the 16-bit boot loader program, there is absolutely
nothing you could do with an assembler like MASM when writing an
OS that couldn't also be written with HLA. The only reason HLA
doesn't allow this (directly, anyway), is because it is a 32-bit flat
model assembler (sorta like FASM and a couple of other assemblers,
I might add).
I'm sorry "Art of Assembly" doesn't teach you how to write your own
OS. But it's already 1,500 pages long and I'd argue that it's not even
complete when it comes to teaching *assembly language*! Fortunately,
there are several good textbooks on Operating Systems' design that
you can refer to. Though they tend to use the C programming language
quite a bit, once you master assembly language (and C), it shouldn't
be too hard to mentally translate that information from C to assembly.
And that's true regardless of which assembler you use.
Bottom line: if having a good book on operating system design is
what's holding you back from using a particular assembler, you'll
probably have to forget about learning assembly language - no such
book exists and it's doubtful one will ever get written. As I mentioned
already, the only reasonable way to do what you want to do is to
learn both C and assembly and then pick up a decent C-based
book on operating systems and translate that yourself.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
Randall
|
5/31/2004 6:31:19 AM
|
|
Ben Meyer wrote:
> I am a student of writing operating systems. I enjoy the low level
> stuff, and I am working on writing my own operating system. I have
> wanted to learn assembly to write the low level details of the operating
> system - boot sector, etc. - but HLA and its resultant books/etc don't
> provide that kind of information. As a beginner, I would really
> appreciate a book that taught Assembly for what it really is - a
> language that controls the entire computer - and at the undergraduate
> level. I would really appreciate a book that started with a Hello World
> boot sector and helped build a system, showing the full power of the
> language, and showing the constructs with real examples. (Of course,
> it'd have to have an environment like Bochs or VMware for testing.)
You'll find the bootloader on John Fines' page:
http://my.execpc.com/CE/AC/geezer/johnfine/
The book you want is at:
http://www.amazon.com/exec/obidos/tg/detail/-/0672306557/qid=1085991771/sr=1-2/ref=sr_1_2/102-8721749-1917755?v=glance&s=books
Doing your own operating system is a professionals' task, whether you do it in
assembly or HLL (I've done upwards of 10). A novice can do an operating system,
but you will be a professional by the time you are done, or you will quit. And
most likey you will throw the first one away. I'll give you the best hint for
such work I wish I had got when I started:
Operating systems are overblown device multiplexers. Learn how to do that right,
and the rest will follow.
I also cannot recommend the work for someone who does not like direct hardware
programming such as device drivers. No drivers = no operating system. If you
develop for the PC, you will need to understand PCI. Nowdays PCI is the primary
protocol you use to talk to all onboard hardware devices.
Luck !
|
|
0
|
|
|
|
Reply
|
Scott
|
5/31/2004 8:52:03 AM
|
|
"Scott Moore" <samiam@moorecad.com> wrote in message
news:i4Cuc.23392$eY2.400@attbi_s02...
> Ben Meyer wrote:
> > I am a student of writing operating systems. I enjoy the low level
> > stuff, and I am working on writing my own operating system. I have
> > wanted to learn assembly to write the low level details of the
operating
> > system - boot sector, etc. - but HLA and its resultant books/etc
don't
> > provide that kind of information. As a beginner, I would really
> > appreciate a book that taught Assembly for what it really is - a
> > language that controls the entire computer - and at the
undergraduate
> > level. I would really appreciate a book that started with a Hello
World
> > boot sector and helped build a system, showing the full power of the
> > language, and showing the constructs with real examples. (Of course,
> > it'd have to have an environment like Bochs or VMware for testing.)
> You'll find the bootloader on John Fines' page:
> http://my.execpc.com/CE/AC/geezer/johnfine/
> The book you want is at:
>
http://www.amazon.com/exec/obidos/tg/detail/-/0672306557/qid=1085991771/sr=1-2/ref=sr_1_2/102-8721749-1917755?v=glance&s=books
Thanks! I think between that and "Protected Mode Software Architecture"
I should be good; though I think I'll go with the 2000 edition of the
above.
> Doing your own operating system is a professionals' task, whether you
do it in
> assembly or HLL (I've done upwards of 10). A novice can do an
operating system,
> but you will be a professional by the time you are done, or you will
quit. And
> most likey you will throw the first one away. I'll give you the best
hint for
> such work I wish I had got when I started:
> Operating systems are overblown device multiplexers. Learn how to do
that right,
> and the rest will follow.
> I also cannot recommend the work for someone who does not like direct
hardware
> programming such as device drivers. No drivers = no operating system.
If you
> develop for the PC, you will need to understand PCI. Nowdays PCI is
the primary
> protocol you use to talk to all onboard hardware devices.
So, so true. My biggest issue has been finding resources. I do have the
Intel manuals, but some things aren't quite clicking.
I also have a copy of "Assembly Language for the Intel-Based Computers"
by Irvine, which I have found to be a great help in understanding
Assembly. It really puts 1 & 1 together to make 2 in how he laid it out.
(I only wish he used an assembler like gas or nasm instead of masm, but
oh well.)
Thanks!
BRM
|
|
0
|
|
|
|
Reply
|
Ben
|
5/31/2004 6:02:18 PM
|
|
Scott Moore wrote:
> The book you want is at:
> [ Developing Your Own 32-Bit Operating System ]
Great reviews! :-)
|
|
0
|
|
|
|
Reply
|
Grumble
|
6/8/2004 6:07:28 PM
|
|
"Grumble" <a@b.c> wrote in message news:ca4iia$ge8$1@news-rocq.inria.fr...
> Scott Moore wrote:
>
> > The book you want is at:
> > [ Developing Your Own 32-Bit Operating System ]
>
> Great reviews! :-)
Yeah, you never can tell though.
I'm scared to recommend that book because of the reviews.
OTOH, most of them are of a highly "academic" nature and
as such, need to be taken with a grain of salt.
Then, on the other hand, I usually don't have much praise
for a book where someone takes a program they've written
and adds some prose around the code to turn it into a book.
I always figured that this is what design documentation is
supposed to be for. Then again, at least the code is commented :-)
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
Randall
|
6/8/2004 8:32:57 PM
|
|
Damn good article Mr. Hyde.
I'm sure it must've upset quite a few out there.
Seems like when a man's capacity is challenged his first reaction is
outrage.
When you mention the "efficiency" of programs you're pokeing a lot of
"programmers" right in the wound, heheh.
Robert AH Prins wrote:
> Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
>
> Robert
> --
> Robert AH Prins
> prino@onetel.net.uk
|
|
0
|
|
|
|
Reply
|
CII
|
4/7/2005 6:25:19 PM
|
|
On Thu, 7 Apr 2005 18:25:19 +0000 (UTC), CII <spamtrap@crayne.org>
wrote:
>Damn good article Mr. Hyde.
>I'm sure it must've upset quite a few out there.
>Seems like when a man's capacity is challenged his first reaction is
>outrage.
>When you mention the "efficiency" of programs you're pokeing a lot of
>"programmers" right in the wound, heheh.
>
>
>Robert AH Prins wrote:
>
>> Here <http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html>
>>
>> Robert
>> --
>> Robert AH Prins
>> prino@onetel.net.uk
When I found that article last September my decision (seven years ago)
to learn assembly code was vindicated. These days I try to persuade
everyone on my CompSci course that learning to program at the lowest
level is a good idea, because it teaches us how to structure our
high-level code.
Plus, I'm a machine code fanatic...
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/8/2005 1:36:25 AM
|
|
Alex <spamtrap@crayne.org> wrote:
>When I found that article last September my decision (seven years ago)
>to learn assembly code was vindicated. These days I try to persuade
>everyone on my CompSci course that learning to program at the lowest
>level is a good idea, because it teaches us how to structure our
>high-level code.
Good for you (and your students)! I am one thesis shy of having an M.S. in
C.S. and was one of the very few students in my class who liked the
assembly language/machine architecture class required of all Freshmen in
the curricula. I liked it so much that I focused on it in grad school. I
cannot tell you how much knowing what is going on inside the machine
really helps in solving real-world problems.
One of the problems with most C.S. programs is that they do not do much
to help to encourage the students to understand that the software, hardware,
and network (if applicable) function as a system.
>Plus, I'm a machine code fanatic...
I can do it, but haven't in years. I wrote a set of macros to implement 8087
instructions in MASM when it did not support the numeric coprocessor. (I
snagged them from BYTE or some other techie compurag and modified them a bit).
>'You are in the presence of a System Administrator. KNEEL.' --Unknown
ROFLMAO!!! That is so damn funny! I have walked into a room full of users
wasting work time chatting about the latest football game and watched as
it came to dead silence as I crossed the doorway. Admittedly, none of them
knew a thing about computers and were lucky to be able to use a simple
word processor, but still... They liked me because I would actually show up
and fix a problem with their computers ASAP. They even took me to lunch
a few times. Of course, that meant I felt obligated to take them all to
lunch one day... It was fun. We became friends. I miss those grad student
days. What made it kind of ironic was the fact that I was earning more than
some of the full-time staff while I had just a 25%-time graduate assistantship.
I made a pile of money on my weekend and vacation consulting excursions and
was thus able to afford to buy lunch for a dozen people.
Knowing x86 architecture was a major part of it, as many of my clients
were financial planners who were trying to figure tax estimates to the
penny or wanted stock market forecasting software that was on target. When
the 8087 came out, I was rather busy.
Regards,
Mark
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/8/2005 3:36:46 AM
|
|
On Fri, 8 Apr 2005 03:36:46 +0000 (UTC), Mark Gibson
<spamtrap@crayne.org> wrote:
>Alex <spamtrap@crayne.org> wrote:
>
>>When I found that article last September my decision (seven years ago)
>>to learn assembly code was vindicated. These days I try to persuade
>>everyone on my CompSci course that learning to program at the lowest
>>level is a good idea, because it teaches us how to structure our
>>high-level code.
>
>Good for you (and your students)! I am one thesis shy of having an M.S. in
>C.S. and was one of the very few students in my class who liked the
>assembly language/machine architecture class required of all Freshmen in
>the curricula. I liked it so much that I focused on it in grad school. I
>cannot tell you how much knowing what is going on inside the machine
>really helps in solving real-world problems.
Erm... actually... I'm one of the students. All the lecturers here
appear to be Java/Haskell fanatics. I can't remember how many times
I've been told that 'Assembly is worthless and obsolete for anything
but OS programming', or something of that nature. Everyone seems to
have Object Orientation on the brain. OOP does allow anyone to write a
program, but on the other hand, it does allow anyone to write a
program.
>One of the problems with most C.S. programs is that they do not do much
>to help to encourage the students to understand that the software, hardware,
>and network (if applicable) function as a system.
On my course we study Computer Architecture (and three different
high-level languages) in the first year, learning how the CPU works.
In the second year we have to write a compiler. I think they bridge
the gap between high- and low-level quite nicely at this Uni, but the
main focus is always on the high-level. That's not exactly a bad
thing, unless the students get the idea that the underlying
implementation isn't worth knowing about...
>>Plus, I'm a machine code fanatic...
>
>I can do it, but haven't in years. I wrote a set of macros to implement 8087
>instructions in MASM when it did not support the numeric coprocessor. (I
>snagged them from BYTE or some other techie compurag and modified them a bit).
>
>>'You are in the presence of a System Administrator. KNEEL.' --Unknown
>
>ROFLMAO!!! That is so damn funny! I have walked into a room full of users
>wasting work time chatting about the latest football game and watched as
>it came to dead silence as I crossed the doorway. Admittedly, none of them
>knew a thing about computers and were lucky to be able to use a simple
>word processor, but still... They liked me because I would actually show up
>and fix a problem with their computers ASAP. They even took me to lunch
>a few times. Of course, that meant I felt obligated to take them all to
>lunch one day... It was fun. We became friends. I miss those grad student
>days. What made it kind of ironic was the fact that I was earning more than
>some of the full-time staff while I had just a 25%-time graduate assistantship.
>I made a pile of money on my weekend and vacation consulting excursions and
>was thus able to afford to buy lunch for a dozen people.
I reeeally need to get a job... I fix the occasional computer problem
(most of the students in this part of Bristol know me as the 'go-to
guy' to get technical help) but since I'm worried I'll make a mess of
something I generally don't charge for the service.
The sig comes from... actually, I can't remember where it came from.
Probably a 'Best of ASR' website. I'm a fan of Simon's BOfH series.
>Knowing x86 architecture was a major part of it, as many of my clients
>were financial planners who were trying to figure tax estimates to the
>penny or wanted stock market forecasting software that was on target. When
>the 8087 came out, I was rather busy.
>
>Regards,
>Mark
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/8/2005 7:35:33 PM
|
|
Alex <spamtrap@crayne.org> wrote:
>I reeeally need to get a job... I fix the occasional computer problem
>(most of the students in this part of Bristol know me as the 'go-to
>guy' to get technical help) but since I'm worried I'll make a mess of
>something I generally don't charge for the service.
>The sig comes from... actually, I can't remember where it came from.
>Probably a 'Best of ASR' website. I'm a fan of Simon's BOfH series.
Ditto. I've been reading BOFH for years and hated the long hiatus.
While not quite so over-the-top as the BOFH, I have been known to play
some nasty pranks on users who just pissed me off. One of my favorites
was to set their user process level down to one level below the default
user process level on the system. It is so fun watching a poor user compete
with the print spooler for CPU cycles. :-) In my assembly language class,
I "accidentally" left a copy of the source code to a program that would
terminate a user's session with extreme prejudice sitting on my desk when
I left the room. Judging by the wailing and gnashing of teeth the next
day in class, quite a few of the students decided to copy, assemble, and
run the uncommented code. <hehehehe> Being a sysadmin can be so much fun!
Regards,
Mark
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/9/2005 3:26:20 PM
|
|
On Sat, 9 Apr 2005 15:26:20 +0000 (UTC), Mark Gibson
<spamtrap@crayne.org> wrote:
>Alex <spamtrap@crayne.org> wrote:
>
>
>>I reeeally need to get a job... I fix the occasional computer problem
>>(most of the students in this part of Bristol know me as the 'go-to
>>guy' to get technical help) but since I'm worried I'll make a mess of
>>something I generally don't charge for the service.
>>The sig comes from... actually, I can't remember where it came from.
>>Probably a 'Best of ASR' website. I'm a fan of Simon's BOfH series.
>
>Ditto. I've been reading BOFH for years and hated the long hiatus.
>While not quite so over-the-top as the BOFH, I have been known to play
>some nasty pranks on users who just pissed me off. One of my favorites
>was to set their user process level down to one level below the default
>user process level on the system. It is so fun watching a poor user compete
>with the print spooler for CPU cycles. :-)
I'm more of a logfile fan myself. If it's possible to log $it, I will
log $it. And I will spend time writing scripts to search through the
logfiles for $it.
A few weeks later, when $person thinks $it has been forgotten...
*manic cackle*
I've done that to my parents a few times. My Dad wasn't aware of IE's
'History' function. Then he wasn't aware of the download manager I'd
installed.
Now, he's annoyed me once too often about Windows XP not doing what he
wants it to. An upgrade to Linux is on the cards, I think. At least he
can't break it if he doesn't have root. As an added bonus, I can play
mind games with him by renice-ing his processes via SSH.
>In my assembly language class,
>I "accidentally" left a copy of the source code to a program that would
>terminate a user's session with extreme prejudice sitting on my desk when
>I left the room. Judging by the wailing and gnashing of teeth the next
>day in class, quite a few of the students decided to copy, assemble, and
>run the uncommented code.
Sounds like the 'slay' application, available for Linux. Another
favourite of mine. What a shame the Uni systems don't give the
students permissions to run things like that, and the ResNet service
comes down heavily on people who do such things across the Uni
residential network. They like logfiles too.
> Being a sysadmin can be so much fun!
I can imagine... if you can deal with the occasional annoyance from
the users. Some of the tech problems I've had to deal with have just
been silly. I swear, I'm going to put a big 'RTFM' sign on my door.
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/9/2005 5:43:25 PM
|
|
On Sat, 9 Apr 2005 15:26:20 +0000 (UTC), Mark Gibson
<spamtrap@crayne.org> wrote:
>Alex <spamtrap@crayne.org> wrote:
>
>
>>I reeeally need to get a job... I fix the occasional computer problem
>>(most of the students in this part of Bristol know me as the 'go-to
>>guy' to get technical help) but since I'm worried I'll make a mess of
>>something I generally don't charge for the service.
>>The sig comes from... actually, I can't remember where it came from.
>>Probably a 'Best of ASR' website. I'm a fan of Simon's BOfH series.
>
>Ditto. I've been reading BOFH for years and hated the long hiatus.
>While not quite so over-the-top as the BOFH, I have been known to play
>some nasty pranks on users who just pissed me off. One of my favorites
>was to set their user process level down to one level below the default
>user process level on the system. It is so fun watching a poor user compete
>with the print spooler for CPU cycles. :-)
I'm more of a logfile fan myself. If it's possible to log $it, I will
log $it. And I will spend time writing scripts to search through the
logfiles for $it.
A few weeks later, when $person thinks $it has been forgotten...
*manic cackle*
I've done that to my parents a few times. My Dad wasn't aware of IE's
'History' function. Then he wasn't aware of the download manager I'd
installed.
Now, he's annoyed me once too often about Windows XP not doing what he
wants it to. An upgrade to Linux is on the cards, I think. At least he
can't break it if he doesn't have root. As an added bonus, I can play
mind games with him by renice-ing his processes via SSH.
>In my assembly language class,
>I "accidentally" left a copy of the source code to a program that would
>terminate a user's session with extreme prejudice sitting on my desk when
>I left the room. Judging by the wailing and gnashing of teeth the next
>day in class, quite a few of the students decided to copy, assemble, and
>run the uncommented code.
Sounds like the 'slay' application, available for Linux. Another
favourite of mine. What a shame the Uni systems don't give the
students permissions to run things like that, and the ResNet service
comes down heavily on people who do such things across the Uni
residential network. They like logfiles too.
> Being a sysadmin can be so much fun!
I can imagine... if you can deal with the occasional annoyance from
the users. Some of the tech problems I've had to deal with have just
been silly. I swear, I'm going to put a big 'RTFM' sign on my door.
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/9/2005 7:16:31 PM
|
|
Alex <spamtrap@crayne.org> wrote:
>On Sat, 9 Apr 2005 15:26:20 +0000 (UTC), Mark Gibson [wrote:]
>> Being a sysadmin can be so much fun!
>I can imagine... if you can deal with the occasional annoyance from
>the users. Some of the tech problems I've had to deal with have just
>been silly. I swear, I'm going to put a big 'RTFM' sign on my door.
Users are the people who indirectly paid my bills for many years. As a
serious computer, firearm, book, music, and video collector, my bills were
not insubstantial. We're talking about a dozen computers ranging from Sun
workstations to a fairly fast IBM Thinkpad A20p and a 2.2Ghz Compaq minitower
I bought over a year ago. I really enjoy helping users, especially those who
are really computer illiterate but want to learn about computers. When I
was last consulting on a full-time basis, I would tell prospective clients
that my rate was $100/hr. -- more if the work involved skills I knew they
could not find elsewhere in the area. I can think of two who were very
surprised when I spend an hour or two fixing something on their LANs and
then said "No charge." when they asked me how much they owed me. Reason I
did that? In both cases they kept asking me intelligent questions while
I was working on their systems. Both of them ended up being regular paying
clients, so I think the freebies were worth it.
OOTC: With one of those clients, I used an instruction I found by disassembling
Lotus Symphony to look for undocumented keywords. These days, I use a
disassembler on most application software I intend to write code for, but
today, more software companies are not storing keywords in plain text. <sigh>
Regards,
Mark Gibson
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/9/2005 9:37:13 PM
|
|
Alex wrote:
>
>Now, he's annoyed me once too often about Windows XP not doing what he
>wants it to. An upgrade to Linux is on the cards, I think. At least he
>can't break it if he doesn't have root. As an added bonus, I can play
>mind games with him by renice-ing his processes via SSH.
I've heard that particular process described as "upgrading Windows XP to
Service Pack Linux".
--
- Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
|
|
0
|
|
|
|
Reply
|
Tim
|
4/10/2005 4:12:16 AM
|
|
Alex <spamtrap@crayne.org> wrote:
> As an added bonus, I can play mind games with him by
> renice-ing his processes via SSH.
And just how do you think he would notice? `nice` value only
affects maximum timeslice -- most process hit a blocking syscall first.
Only with running multiple CPU hogs does `nice` change much.
This is ASM. You're supposed to know the machine at
low-level. And enough to know that the childish BoFH
tricks are undignified.
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/10/2005 5:50:50 PM
|
|
Robert Redelmeier <redelm@ev1.net.invalid> wrote:
>Alex <spamtrap@crayne.org> wrote:
>> As an added bonus, I can play mind games with him by
>> renice-ing his processes via SSH.
>And just how do you think he would notice? `nice` value only
>affects maximum timeslice -- most process hit a blocking syscall first.
>Only with running multiple CPU hogs does `nice` change much.
>This is ASM. You're supposed to know the machine at
>low-level. And enough to know that the childish BoFH
>tricks are undignified.
Trust me. I make a hobby out of trashing the computers/networks of those
malware hackers I can target. With a couple of sites that spammed me, it
was possible to insert some really insidious code as I replied from a
throwaway email address. I'll never know what ensued, but I'm sure it was
painful for the sysadmin on the other end. This only works with bozos who
use the Web for Email. A text-based mailreader won't execute the code. I
use other methods to deal with spammers I can't target directly.
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/10/2005 6:43:43 PM
|
|
On Sat, 9 Apr 2005 21:37:13 +0000 (UTC), Mark Gibson
<spamtrap@crayne.org> wrote:
>Alex <spamtrap@crayne.org> wrote:
>>On Sat, 9 Apr 2005 15:26:20 +0000 (UTC), Mark Gibson [wrote:]
>
>>> Being a sysadmin can be so much fun!
>
>>I can imagine... if you can deal with the occasional annoyance from
>>the users. Some of the tech problems I've had to deal with have just
>>been silly. I swear, I'm going to put a big 'RTFM' sign on my door.
>
>Users are the people who indirectly paid my bills for many years. As a
>serious computer, firearm, book, music, and video collector, my bills were
>not insubstantial. We're talking about a dozen computers ranging from Sun
>workstations to a fairly fast IBM Thinkpad A20p and a 2.2Ghz Compaq minitower
>I bought over a year ago. I really enjoy helping users, especially those who
>are really computer illiterate but want to learn about computers. When I
>was last consulting on a full-time basis, I would tell prospective clients
>that my rate was $100/hr. -- more if the work involved skills I knew they
>could not find elsewhere in the area. I can think of two who were very
>surprised when I spend an hour or two fixing something on their LANs and
>then said "No charge." when they asked me how much they owed me. Reason I
>did that? In both cases they kept asking me intelligent questions while
>I was working on their systems. Both of them ended up being regular paying
>clients, so I think the freebies were worth it.
I enjoy fixing problems too and usually the client is no problem. They
ask intelligent questions and are willing to learn. Most who fall
under this heading are capable of fixing the problem themselves if it
crops up again. Those who can't often insist on paying me, which I
decline.
I don't like charging for spending an hour or two (or in one case,
eight) tinkering with someone else's computer.
Then there are those who sincerely believe that it's their Godgiven
right to have their computer fixed, right now, in my free time. These
are the ones to which I was referring ;-) And they are /very/ annoying
because they don't bother to listen when I'm explaining how the
problem could've been avoided.
Either that, or they tell (not ask, /tell/) me to explain to them how
to fix it, step by step. Problem with this is, unless I know exactly
what's causing the fault, I tend to poke around a bit on instinct to
find the cause, and it's difficult to do that through someone else
(especially when said person is not following the instructions). I
suppose it's good training for doing Tech Support in a call centre,
but that's one job I don't think I could do for very long.
>OOTC: With one of those clients, I used an instruction I found by disassembling
>Lotus Symphony to look for undocumented keywords. These days, I use a
>disassembler on most application software I intend to write code for, but
>today, more software companies are not storing keywords in plain text. <sigh>
>
>Regards,
>Mark Gibson
Damned obfuscators... I'm definitely starting to lean towards Open
Source software, although that's mainly because of the unreliability
of some of the junk being sold commercially these days. My current
project will most definitely be Open Source when it's working, because
I'm not sure how stable it's going to be and in this case I'll be
relying on other people to find and help fix the bugs. Kernel-mode
WinXP drivers are complex things.
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/10/2005 7:06:28 PM
|
|
Mark Gibson wrote:
>
> Trust me. I make a hobby out of trashing the computers/networks of
those
> malware hackers I can target. With a couple of sites that spammed
me, it
> was possible to insert some really insidious code as I replied from a
> throwaway email address. I'll never know what ensued, but I'm sure
it was
> painful for the sysadmin on the other end. This only works with
bozos who
> use the Web for Email. A text-based mailreader won't execute the
code. I
> use other methods to deal with spammers I can't target directly.
Then you deserve each other. What, pray, is this nonsense part of this
thread doing on clax? There are enough other places on the net for
this.
--
Regards
Alex McDonald
|
|
0
|
|
|
|
Reply
|
Alex
|
4/10/2005 9:58:49 PM
|
|
>>>>
Damn good article Mr. Hyde.
I'm sure it must've upset quite a few out there.
Seems like when a man's capacity is challenged his first reaction is
outrage.
When you mention the "efficiency" of programs you're pokeing a lot of
"programmers" right in the wound, heheh.
<<<<
Heck, as you can see, it's upset quite a few people around here :-)
Seriously, though, I love some of the review of Write Great Code (about
which the article originally mentioned in this thread was written).
People say things like "in the days of multi-gigahertz machines, we
don't have to worry about speed anymore..." or "now that machines have
a gigabyte of RAM installed, we don't have to worry about saving space
anymore..." I have to laugh. These people don't realize that they are
prime examples of exactly why I felt "Write Great Code" needed to be
written in the first place.
While I'm not advocating that people count cycles for each instruction
in each program that they write, I do believe that people *ought* to
consider the efficiency of their applications when they design them.
Those who fail to do so, thinking that worrying about efficiency is an
outdated concept, are doomed to produce slow, bloated, code. Alas,
we've lost a generation of programmers to the dogma of "efficiency
doesn't matter." Hopefully, we can rescue the next generation.
The only good new is, CPU performance is not increasing as rapidly as
it did in the 1990s, so as the article points out, it's now the
programmer's turn to shine -- they can no longer rely on ever-faster
CPUs to cover their behinds. Given that OSes continue to extract large
chunks of memory and CPU performance, we' re soon going to see some
*real* sluggish systems again.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/11/2005 2:04:28 AM
|
|
Alex McDonald <spamtrap@crayne.org> wrote:
>Mark Gibson wrote:
>>
>> Trust me. I make a hobby out of trashing the computers/networks of
>those
>> malware hackers I can target. With a couple of sites that spammed
>me, it
>> was possible to insert some really insidious code as I replied from a
>> throwaway email address. I'll never know what ensued, but I'm sure
>it was
>> painful for the sysadmin on the other end. This only works with
>bozos who
>> use the Web for Email. A text-based mailreader won't execute the
>code. I
>> use other methods to deal with spammers I can't target directly.
>Then you deserve each other. What, pray, is this nonsense part of this
>thread doing on clax? There are enough other places on the net for
>this.
Fair question. It is often (not always) easy to determine the machine
code used at an offensive site. If you do, the damage you can send back
is almost limitless. I've been paid obscene amounts of money to "heal"
systems, because I know the language they speak. I get giggles and grins
out of trashing spammers' systems for for much the same reason.
I really wish someone would start a thread here that is about assembly
code in a general (objective) view -- not just x86 code. I think the
moderator would allow it. The point being that you have to work in a
certain frame of mind to write very low level code. It is not far different
from the mindset of a malicious hacker in most respects. Go figure.
For instance, what would you consider to be an ultimate .asm instruction
set? How orthoganonal would it be? Mine would do integer arithmetic in
hardware. (Need a fancy processor as well as a good assembler.) String
processing instructions are another priority for me. x86 has several, but they
are crude.
Regards,
Mark
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/11/2005 2:35:45 AM
|
|
>>>>
I really wish someone would start a thread here that is about assembly
code in a general (objective) view -- not just x86 code.
<<<<
Technically, that's why the alt.lang.asm newsgroup exist.
It's too bad certain people have destroyed that newsgroup. There
actions are the main reason this newsgroup became moderated a while
back and threads like the one you're suggesting get whacked once they
grow out of control. BTW, I don't think the moderator would have a
problem with such a thread, I just think that it would grow into a big
mess (anti-80x86/anti-Microsoft/anti-Intel) before too long, and that
*should* get nipped in the bud around here.
>>>>>
For instance, what would you consider to be an ultimate .asm
instruction
set?
<<<<<
The NS32532 came pretty damn close. Very orthogonal. (and did integer
arithmetic in hardware -- perhaps you should explain that one as most
CPUs do this, unless I've misinterpreted your statement), and it has
some decent string processing instructions.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/11/2005 3:53:58 AM
|
|
On Mon, 11 Apr 2005 03:53:58 +0000 (UTC)
"randyhyde@earthlink.net" <spamtrap@crayne.org> wrote:
:For instance, what would you consider to be an ultimate .asm
:instruction
:set?
Personally, I would like one which matches the target architecture's
instruction set.
-- Chuck
|
|
0
|
|
|
|
Reply
|
Charles
|
4/11/2005 6:04:19 AM
|
|
"randyhyde@earthlink.net" wrote:
> >>>>
> Damn good article Mr. Hyde.
> I'm sure it must've upset quite a few out there.
> Seems like when a man's capacity is challenged his first reaction is
> outrage.
> When you mention the "efficiency" of programs you're pokeing a lot of
> "programmers" right in the wound, heheh.
> <<<<
>
> Heck, as you can see, it's upset quite a few people around here :-)
>
Well I'm sure this newsgroup is an unlikely place to find "programmers"..
Or is it?
>
> Seriously, though, I love some of the review of Write Great Code (about
> which the article originally mentioned in this thread was written).
> People say things like "in the days of multi-gigahertz machines, we
> don't have to worry about speed anymore..." or "now that machines have
> a gigabyte of RAM installed, we don't have to worry about saving space
> anymore..." I have to laugh. These people don't realize that they are
> prime examples of exactly why I felt "Write Great Code" needed to be
> written in the first place.
>
> While I'm not advocating that people count cycles for each instruction
> in each program that they write, I do believe that people *ought* to
> consider the efficiency of their applications when they design them.
> Those who fail to do so, thinking that worrying about efficiency is an
> outdated concept, are doomed to produce slow, bloated, code. Alas,
> we've lost a generation of programmers to the dogma of "efficiency
> doesn't matter." Hopefully, we can rescue the next generation.
>
I blame the philosophy of "structured well behaved programming" for that.
And I would extend the concept of "the lost generation" beyond
programming. Ironically, the mediocrity found in so many levels not just
in written and working code but in the philosophy of programming itself is
being disguised by its popularity among professionals. You know, for some
time I feared that I was one of the few who could actually perceive the
loss. A good part of the '90s I felt like Neville in Matheson's story.
>
> The only good new is, CPU performance is not increasing as rapidly as
> it did in the 1990s, so as the article points out, it's now the
> programmer's turn to shine -- they can no longer rely on ever-faster
> CPUs to cover their behinds. Given that OSes continue to extract large
> chunks of memory and CPU performance, we' re soon going to see some
> *real* sluggish systems again.
> Cheers,
> Randy Hyde
And that's why, Mr. Hyde, we need all the hardware information and examples
that we can get. You know, for a good part of the '80s -on a personal
note- I resisted programming 16 bit processors because I got the odd
feeling (at the time) that 8 bit technology hadn't been streched to its
capacity then. In a sense I still believe I wasn't wrong, and I think that
time may prove me correct. The same thing happened to 16 bit technology,
too quickly forced to 32 bits. Bytes are more and more resembling memory
cores to me as time passes by.
Sometimes it would seem like more "powerful" hardware was being developed
to make up for the shortcomings of an industry of programmers undisciplined
or simply not competent enough for the job, instead of designing it to make
real advances in computer knowledge. That trend is then being sold as
"progress". It all seems like pseudo-progress to me. We have already
begun to see the results of such trends, starting with the quality of
programmed code and with the true efficiency and "power" of a given piece
of hardware.
I've always said it, statistics and hardware simply don't mix.
|
|
0
|
|
|
|
Reply
|
CII
|
4/11/2005 9:27:46 AM
|
|
>>>>>>>>>>
Sometimes it would seem like more "powerful"
hardware was being developed
to make up for the shortcomings of an
industry of programmers undisciplined
or simply not competent enough for the
job, instead of designing it to make
real advances in computer knowledge.
That trend is then being sold as
"progress". It all seems like pseudo-progress
to me. We have already begun to see the
results of such trends, starting with the quality of
programmed code and with the true efficiency
and "power" of a given piece of hardware.
<<<<<<<<<<<
I don't know that I agree. Back in the 1980s we had a large number of
microprocessor programmers who knew what they were doing. They had to--
that was the *only* way to get decent performance out of the machines
at the time.
One problem I've seen with the last several generations of programmers
(in my time scale, one generation = approximately seven years, time
enough for an undergraduate to go through graduate school and get a
sufficiently advanced degree to begin teaching the next generation) is
that the early programmers, who really knew their stuff, gained
sufficient experience that they could write fairly great code "off the
cuff" without having to sit down and think about it a whole lot. Such
is the benefit of experience. Someone who knows how to write efficient
code can look at a problem and realize where the effort is going to be
needed and where they can get lazy. Someone who has lots of experience
is going to write fairly decent code right off the bat, without going
back and hand optimizing everything (I'm not talking about cycle
counting kind of stuff here, I'm just talking about having the
experience to know what kinds of statements compile to efficient code
and knowing which statements compile to horrible code, and choosing the
better of the two). So this experienced programmer can write a decent
application and make claims like "there is no need to worry about
optimizing this code because CPUs are increasing in performance so
rapidly that by the time my application ships, the performance I've
lost by not writing absolute optimal code will be regained by improved
CPU performance." It is important to point out, here, that by
"optimization" this programmer means the "cycle-counting,
instruction-scheduling" craziness that is a lot of work and difficult
to master. This is the kind of stuff, for example, that Dijkstra was
talking about when he said "premature optimization is the root of all
evil."
Unfortunately, the new generation of programmers hears comments like
this and they interpret it to mean that they don't have to worry about
performance at all. Having never actually optimized a program in their
lives, they don't understand what "optimizating a program" really
means. Heck, most of them have never used a *profiler* before, much
less gone in and done cycle-counting kinds of optimization. So they
interpret statements like "there is no need to optimize my program" to
mean "there is no need to worry about performance at all."
The reason "more powerful hardware" was developed was to give a
manufacturer a leg up over the competition, of course. Programmers
really had nothing to do with it (otherwise, RISC architectures never
would have taken off). Programmers have benefited from the more
powerful hardware, but the power was really intended for use by the
computer user, not the computer programmer. If Intel doubles the speed
of their chips and programmers start writing code that is half as fast
as before, what benefit is there to the user who actually *buys* the
machines? While Intel loves the fact that software is making more and
more demands on hardware (they get to sell faster and faster chips for
more and more money), the bottom line is that if today's machines don't
run today's software any faster than yesterday's machines and
yesterday's software, people are going to stick with yesterday's
machines and software for as long as they can. This is already create
headaches for Intel.
Again, the good news is that most of today's software is written so
inefficiently, that there is considerable room to improve the
performance without moving on to multi-core chip sets or 64-bit
processors.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/11/2005 9:27:04 PM
|
|
randyhyde@earthlink.net wrote:
> So this experienced programmer can write a decent
> application and make claims like "there is no need to worry about
> optimizing this code because CPUs are increasing in performance so
> rapidly that by the time my application ships, the performance I've
> lost by not writing absolute optimal code will be regained by improved
> CPU performance." It is important to point out, here, that by
> "optimization" this programmer means the "cycle-counting,
> instruction-scheduling" craziness that is a lot of work and difficult
> to master. This is the kind of stuff, for example, that Dijkstra was
> talking about when he said "premature optimization is the root of all
> evil."
>
>
> Again, the good news is that most of today's software is written so
> inefficiently, that there is considerable room to improve the
> performance without moving on to multi-core chip sets or 64-bit
> processors.
> Cheers,
> Randy Hyde
>
Except that the current generation of processors is hitting the end
of Moore's law for speed (not size of transistor):
http://siepr.stanford.edu/news/Moores_Law.html
What it means, is that for the 90nm generation and below, although
the size of transistors continues to shrink at the Moore rate, the
speed does not continue to double each year, as it did previously.
This is the rationale of the need for multicore CPUs. However, to
truly take advantage of multicore CPUs to speed up applications,
and not just make a background window downloading illegal CD copies
faster, applications must take better advantage of multithreading.
So the era of "free" performance improvements has come to an end,
and now the only issue up for debate is if it will start going
again, due to some technological miracle.
In the meantime, we are supposed to bone up on multithreading. But
the more practical progammers will go back to basics and improve
their single thread code as well.
For the people who are saying that its not worth optimizing because
of CPU scaling, the prescription is showing them the above article
(or one of the many like it), or a swift boot to the head, or
perhaps both.
|
|
0
|
|
|
|
Reply
|
Scott
|
4/11/2005 10:59:35 PM
|
|
Mark Gibson <spamtrap@crayne.org> wrote:
> I get giggles and grins out of trashing spammers' systems
> for for much the same reason.
Cyber-vigilante, eh? First, you may be hitting innocents
(relays). Second, do two wrongs make a right? Third, if
you wander into a honeypot the Feds will throw you in jail.
Unauthorized access to a computer system is a felony.
Spam
> For instance, what would you consider to be an ultimate
> .asm instruction set? How orthoganonal would it be?
As little as possible. Orthogonality implies redundancy,
and that makes instructions longer. Ideally, I'd like
a precompressed instruction set.
> Mine would do integer arithmetic in hardware
Gee, I don't know any processor that doesn't.
All do binary, and many, including x86 will do BCD.
x87 will do 18 digits at a time in hardware.
> String processing instructions are another priority for me.
Are you arguing for a Big-Endian machine?
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/12/2005 12:07:53 AM
|
|
Charles A. Crayne <spamtrap@crayne.org> wrote:
> :For instance, what would you consider to be an ultimate
> :.asm instruction set?
> Personally, I would like one which matches the target
> architecture's instruction set.
Sad that this has to be requested!
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/12/2005 12:07:59 AM
|
|
>>>>>>>>
Except that the current generation of processors is hitting the end
of Moore's law for speed (not size of transistor):
http://siepr.stanford.edu/news�/Moores_Law.html
<<<<<<<<
Of course, Moore's law says nothing about speed. It has to do with the
number of transistors and the size of the dies upon which chips are
built. Nothing else. Speed has been an incidental by-product of having
more transistors, but computer architects have seem to run out of ways
of speeding up CPUs by simply adding more transistors to the mix.
>>>>>>>>>>
This is the rationale of the need for multicore CPUs. However, to
truly take advantage of multicore CPUs to speed up applications,
and not just make a background window downloading illegal CD copies
faster, applications must take better advantage of multithreading.
<<<<<<<<<<
Multi-core isn't going to buy much for a couple of reasons:
1. "n" cores don't provide n-times speedup. Particularly beyond n=4 and
unless you've got a butt-kicking bus, you reach the point of
diminishing returns at around n=16.
2. To get n times speed up with an n-processor design requires very
specially written software. A two-core device will speed up normal
user's systems a bit, because all the background processes will run on
one CPU while the "foreground" process runs on the other, but by and
large we aren't going to see a lot of multi-thread applications being
written. The truth is, most software is not easily parallelizable and
there is little to gain from a multiprocessing system, particularly
beyond 2-4 processors, for the average user.
>>>>>>>>>
So the era of "free" performance improvements has come to an end,
and now the only issue up for debate is if it will start going
again, due to some technological miracle.
<<<<<<<<<
Yep. There is always the possibility of a new technology coming along.
But it's hard to imagine chip manufacturers switching from CMOS to
something else in the near future (say, within a decade or two) and
most people think we've just about reached the end of the line for CMOS
clock speeds.
On the plus side, while my original article griped about how
ever-increasing software performance has allowed programmers to get
lazy, in a sense, this same technological advance has allowed hardware
designers to get lazy, too. Kudos to AMD for showing us that you don't
need 4GHz to achieve the equivalent performance of a 4GHz PIV. All it
takes is a better design. Intel failed to produce a 4GHz CPU, but AMD
delivers a 64-bitter that they claim has that performance. Just as
software developers can improve the performance of their applications
without relying on technology to rescue them, so can hardware
designers. For example, why doesn't Intel fix the horrible times for
instructions like the shifts, rotates, ADC, and so on?
>>>>>>>>
In the meantime, we are supposed to bone up on multithreading. But
the more practical progammers will go back to basics and improve
their single thread code as well.
<<<<<<<<
As I said, concurrency won't work for most applications. Oh, there's no
doubt that it will be cool to have Microsoft Word checking your
spelling and grammar on a different CPU (thus regaining some of the
time lost on single CPU systems, helping MS Office perform like a pig),
but by and large we're not going to see a ton of applications moving
over to the multi-threaded model. There are, and will be for a *very*
long time, too many uniprocessor boxes for this to be anything but a
niche software market. Sure, you can run multi-threaded code on a
uniprocessor box, but why? It runs slower (than a single-threaded app)
and costs a *heck* of a lot more to develop (debugging concurrent code
is pure misery). I agree that it's a good thing to learn, but don't
expect most applications to take considerable advantage of this anytime
soon.
>>>>>>>>>
For the people who are saying that its not worth optimizing because
of CPU scaling, the prescription is showing them the above article
(or one of the many like it), or a swift boot to the head, or
perhaps both.
<<<<<<<<<<
Try reading the responses at
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html
Clearly, some of these people need a swift boot to the head :-)
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/12/2005 1:53:59 AM
|
|
Robert Redelmeier <redelm@ev1.net.invalid> wrote:
>Mark Gibson <spamtrap@crayne.org> wrote:
>> I get giggles and grins out of trashing spammers' systems
>> for for much the same reason.
>Cyber-vigilante, eh? First, you may be hitting innocents
>(relays). Second, do two wrongs make a right? Third, if
>you wander into a honeypot the Feds will throw you in jail.
>Unauthorized access to a computer system is a felony.
>Spam
>> For instance, what would you consider to be an ultimate
>> .asm instruction set? How orthoganonal would it be?
>As little as possible. Orthogonality implies redundancy,
>and that makes instructions longer. Ideally, I'd like
>a precompressed instruction set.
>> Mine would do integer arithmetic in hardware
>Gee, I don't know any processor that doesn't.
>All do binary, and many, including x86 will do BCD.
>x87 will do 18 digits at a time in hardware.
>> String processing instructions are another priority for me.
>Are you arguing for a Big-Endian machine?
A full-blown VAX instruction set implemented in hardware, not firmware.
The busses would have to be on the wide side so we're looking at at least
a six-layer mobo and an expensive chipset in addition to a pricey CPU. x86
is here to stay, but it is ugly. We need a better platform to write tight
code for. I'm hoping my new AMD 64-bit CPU might come close. Randy Hyde
can explain it for you. I've used his HLA, and while I don't like it, I can
tell he knows how to write .asm code. For years now, I have been looking for
a nice off the shelf .asm integer math package. I am coming to the
conclusion that I will have to write one myself. Long division will be a
bitch. Good thing that Don Knuth wrote some great books, at least one of
which addresses the subject.
Orthogonal implies just the opposite of redundancy, BTW. Each instruction
does its thing, and only its thing.
Regards,
Mark
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/12/2005 2:55:40 AM
|
|
Scott Moore <spamtrap@crayne.org> wrote:
>randyhyde@earthlink.net wrote:
>> So this experienced programmer can write a decent
>> application and make claims like "there is no need to worry about
>> optimizing this code because CPUs are increasing in performance so
>> rapidly that by the time my application ships, the performance I've
>> lost by not writing absolute optimal code will be regained by improved
>> CPU performance." It is important to point out, here, that by
>> "optimization" this programmer means the "cycle-counting,
>> instruction-scheduling" craziness that is a lot of work and difficult
>> to master. This is the kind of stuff, for example, that Dijkstra was
>> talking about when he said "premature optimization is the root of all
>> evil."
>>
>>
>> Again, the good news is that most of today's software is written so
>> inefficiently, that there is considerable room to improve the
>> performance without moving on to multi-core chip sets or 64-bit
>> processors.
>> Cheers,
>> Randy Hyde
>>
>Except that the current generation of processors is hitting the end
>of Moore's law for speed (not size of transistor):
>http://siepr.stanford.edu/news/Moores_Law.html
>What it means, is that for the 90nm generation and below, although
>the size of transistors continues to shrink at the Moore rate, the
>speed does not continue to double each year, as it did previously.
>This is the rationale of the need for multicore CPUs. However, to
>truly take advantage of multicore CPUs to speed up applications,
>and not just make a background window downloading illegal CD copies
>faster, applications must take better advantage of multithreading.
>So the era of "free" performance improvements has come to an end,
>and now the only issue up for debate is if it will start going
>again, due to some technological miracle.
>In the meantime, we are supposed to bone up on multithreading. But
>the more practical progammers will go back to basics and improve
>their single thread code as well.
>For the people who are saying that its not worth optimizing because
>of CPU scaling, the prescription is showing them the above article
>(or one of the many like it), or a swift boot to the head, or
>perhaps both.
Well, wait until molecular level processors hit the local computer stores.
They are almost certainly going to be RISC chips of some sort, very
fast ones. There is talk of even faster tech, but it isn't real world yet.
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/12/2005 3:15:46 AM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
>>>>>>>>>
>Except that the current generation of processors is hitting the end
>of Moore's law for speed (not size of transistor):
>http://siepr.stanford.edu/news?/Moores_Law.html
><<<<<<<<
>Of course, Moore's law says nothing about speed. It has to do with the
>number of transistors and the size of the dies upon which chips are
>built. Nothing else. Speed has been an incidental by-product of having
>more transistors, but computer architects have seem to run out of ways
>of speeding up CPUs by simply adding more transistors to the mix.
>>>>>>>>>>>
>This is the rationale of the need for multicore CPUs. However, to
>truly take advantage of multicore CPUs to speed up applications,
>and not just make a background window downloading illegal CD copies
>faster, applications must take better advantage of multithreading.
><<<<<<<<<<
>Multi-core isn't going to buy much for a couple of reasons:
>1. "n" cores don't provide n-times speedup. Particularly beyond n=4 and
>unless you've got a butt-kicking bus, you reach the point of
>diminishing returns at around n=16.
Kick ass, Randy!
>2. To get n times speed up with an n-processor design requires very
>specially written software. A two-core device will speed up normal
>user's systems a bit, because all the background processes will run on
>one CPU while the "foreground" process runs on the other, but by and
>large we aren't going to see a lot of multi-thread applications being
>written. The truth is, most software is not easily parallelizable and
>there is little to gain from a multiprocessing system, particularly
>beyond 2-4 processors, for the average user.
Yeah, writing tight parallel code is very difficult for most programmers.
A typical compiler won't do it for you, you have to optimize for ||
processing on your own. This is where knowing machine architecture pays off.
>So the era of "free" performance improvements has come to an end,
>and now the only issue up for debate is if it will start going
>again, due to some technological miracle.
><<<<<<<<<
>Yep. There is always the possibility of a new technology coming along.
>But it's hard to imagine chip manufacturers switching from CMOS to
>something else in the near future (say, within a decade or two) and
>most people think we've just about reached the end of the line for CMOS
>clock speeds.
Good money says withing a decade. It is a fast paced world out there...
>On the plus side, while my original article griped about how
>ever-increasing software performance has allowed programmers to get
>lazy, in a sense, this same technological advance has allowed hardware
>designers to get lazy, too. Kudos to AMD for showing us that you don't
>need 4GHz to achieve the equivalent performance of a 4GHz PIV. All it
>takes is a better design. Intel failed to produce a 4GHz CPU, but AMD
>delivers a 64-bitter that they claim has that performance. Just as
>software developers can improve the performance of their applications
>without relying on technology to rescue them, so can hardware
>designers. For example, why doesn't Intel fix the horrible times for
>instructions like the shifts, rotates, ADC, and so on?
No shit. Those instructions are lousy on Intel CPUs.
These days, everyone seems to be nHz crazy. I like VUPS since they
measure performance, not mere clock speed. But they are only applied
to VAXen for the most part.
>>>>>>>>>
>In the meantime, we are supposed to bone up on multithreading. But
>the more practical progammers will go back to basics and improve
>their single thread code as well.
><<<<<<<<
>As I said, concurrency won't work for most applications. Oh, there's no
>doubt that it will be cool to have Microsoft Word checking your
>spelling and grammar on a different CPU (thus regaining some of the
>time lost on single CPU systems, helping MS Office perform like a pig),
>but by and large we're not going to see a ton of applications moving
>over to the multi-threaded model. There are, and will be for a *very*
>long time, too many uniprocessor boxes for this to be anything but a
>niche software market. Sure, you can run multi-threaded code on a
>uniprocessor box, but why? It runs slower (than a single-threaded app)
>and costs a *heck* of a lot more to develop (debugging concurrent code
>is pure misery). I agree that it's a good thing to learn, but don't
>expect most applications to take considerable advantage of this anytime
>soon.
Your comment about bus width/speed applies here. Given enough money I can
make a 4GHz PC, but it will cost about $10K if done right, and it will
still be just another 32-bit box. Let me design a cool 128-bit box and it
will run at least $100K off a production line, assuming they sell well.
>For the people who are saying that its not worth optimizing because
>of CPU scaling, the prescription is showing them the above article
>(or one of the many like it), or a swift boot to the head, or
>perhaps both.
><<<<<<<<<<
>Try reading the responses at
>http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html
>Clearly, some of these people need a swift boot to the head :-)
>Cheers,
>Randy Hyde
Way to go!, Randy.
Best regards,
Mark Gibson
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/12/2005 3:35:15 AM
|
|
On Tue, 12 Apr 2005 01:53:59 +0000 (UTC), "randyhyde@earthlink.net"
<spamtrap@crayne.org> wrote:
[snip]
>Try reading the responses at
>http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html
>Clearly, some of these people need a swift boot to the head :-)
>Cheers,
>Randy Hyde
<pedant>
In one of the comments was "Debug points are set in the Intel 80x86
through an INT 9 software interrupt."
IIRC, INT9 is the old Coprocessor Segment Overrun exception. I don't
think it's used anymore. INT3 is the breakpoint instruction because
it's a single-byte opcode.
</pedant>
I can identify with part of this:
>If nothing else, I would honestly have to agree that knowledge of
>assembler, has made me an all round better C/C++ programmer. It took
>me about 1 year of assembler studies to reach 'compiler' level.
>After 2 years, I was thinking and coding like a compiler. After 3
>years, compilers are left in the dust.
It feels strange to be looking at a piece of C code and know exactly
how it would appear in Assembly (six years ago I wouldn't've been able
to tell what the C code did). For that matter, I can't help but wonder
sometimes if the compiler would spot all the optimisations I do, or if
it sees some that I don't.
I can optimise code by hand, but I'm damned if I know how to write an
algorithm that will do it! Compiler construction is very much an
arcane art from my point of view. There's always something new to
learn...
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/12/2005 3:48:43 AM
|
|
Alex <spamtrap@crayne.org> wrote:
>On Tue, 12 Apr 2005 01:53:59 +0000 (UTC), "randyhyde@earthlink.net"
><spamtrap@crayne.org> wrote:
>[snip]
>>Try reading the responses at
>>http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html
>>Clearly, some of these people need a swift boot to the head :-)
>>Cheers,
>>Randy Hyde
><pedant>
>In one of the comments was "Debug points are set in the Intel 80x86
>through an INT 9 software interrupt."
>IIRC, INT9 is the old Coprocessor Segment Overrun exception. I don't
>think it's used anymore. INT3 is the breakpoint instruction because
>it's a single-byte opcode.
></pedant>
>I can identify with part of this:
>>If nothing else, I would honestly have to agree that knowledge of
>>assembler, has made me an all round better C/C++ programmer. It took
>>me about 1 year of assembler studies to reach 'compiler' level.
>>After 2 years, I was thinking and coding like a compiler. After 3
>>years, compilers are left in the dust.
>It feels strange to be looking at a piece of C code and know exactly
>how it would appear in Assembly (six years ago I wouldn't've been able
>to tell what the C code did). For that matter, I can't help but wonder
>sometimes if the compiler would spot all the optimisations I do, or if
>it sees some that I don't.
>I can optimise code by hand, but I'm damned if I know how to write an
>algorithm that will do it! Compiler construction is very much an
>arcane art from my point of view. There's always something new to
>learn...
I know it sounds quirky but learn to think like a computer. Then you
can optimize for a given platform to your heart's delight. I play with
math packages a lot. They are non-intuitive. To get max performance,
you have to understand what the hardware offers you. There are programs
out there that use integer arithmetic to substitute for fixed point math
functions in order to save some time. You have to be careful not to
exceed the precision of the math package.
Regards,
Mark
--
"The universe is quite robust in design and appears to be doing
just fine on its own, incompetent support staff notwithstanding."
-- the Dennis formerly known as (evil), MCFL
|
|
0
|
|
|
|
Reply
|
Mark
|
4/12/2005 2:39:54 PM
|
|
>>>>>>>>>>
It feels strange to be looking at a piece of C code and know exactly
how it would appear in Assembly (six years ago I wouldn't've been able
to tell what the C code did). For that matter, I can't help but wonder
sometimes if the compiler would spot all the optimisations I do, or if
it sees some that I don't.
I can optimise code by hand, but I'm damned if I know how to write an
algorithm that will do it! Compiler construction is very much an
arcane art from my point of view. There's always something new to
learn...
<<<<<<<
Compiler optimizers alternately amaze me and confound me. When I study
the output of various compilers (as I am doing now, while working on
"Write Great Code, Volume II"), I often find some amazing code
sequences and think "it's amazing a compiler can do that." Later on in
the same object code module, however, I invariably run into a sequence
that makes me wonder how people can even begin to claim compilers do a
decent job at all (much less, generate better code than humans). We're
talking about code that a beginning assembly programmer could do
better.
Some of my favorite examples are:
for( i=0; i<strlen( s ); ++i )
{
... // no code that modifies s
}
Several good compilers are smart enough to replace strlen(s) with
in-line code that computes the length directly (though they tend to
emit a slow scasb instruction rather than the faster discrete sequence
of instructions). Unfortunately, no compiler I've seen will compute the
length outside the loop, shove that value in a variable, and use that
value rather than recomputing the length on each pass. C'mon! Loop
induction is a problem compiler writers solved a long time ago.
Granted, dealing with aliases (i.e., pointers to character arrays, like
strings) is a difficult problem for optimizers to deal with, but when
the body of the loop contains no other character pointer references at
all, it should be possible for the compiler to move the strlen function
call outside the loop.
I strongly suspect that people who argue that compilers generate code
that is just as good as a human either:
1. Only feed their compilers hand-optimized code to begin with (that
is, they would manually move that strlen call outside the loop),
2. Don't know enough assembly language to know what is good code and
what is not code,
3. "Cherry pick" optimizations from different compilers, rather than
sticking with one compiler (e.g., if you consider GCC and VC++, where
one compiler completely drops the ball on optimization, the other may
do a good job. If you pick the best code sequence from either compiler
working on the same program, the result can be quite good). Problem is,
no compiler generates universally great code. So trying to pass off
optimizations done by several different compilers as though this was
current state of the art for a single compiler is disengineous, at
best.
On the plus side, one could make a viable argument for case (1). If you
know how code is generated by a compiler and you write your HLL code
accordingly, you can get some *very* good machine code output.
Unfortunately, you have to have a pretty good knowledge of what machine
code is all about (and how compilers produce it) in order to write code
this way (a subject, btw, that I'm trying to teach in the Write Great
Code series). The only problem is, when some HLL proponent starts
making claims about how great compilers are, based on that person's
ability to manipulate the machine code the compiler produces, beginning
programmers get the impression they can write code in an arbitrary
fashion and the compiler will take care of them. They don't even
realize how bad the generated machine code turns out to be (because
they haven't a clue about how good it could be).
Sad.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/12/2005 5:07:13 PM
|
|
randyhyde@earthlink.net wrote:
>
> Some of my favorite examples are:
>
> for( i=0; i<strlen( s ); ++i )
> {
> ... // no code that modifies s
> }
>
> Several good compilers are smart enough to replace strlen(s) with
> in-line code that computes the length directly (though they tend to
> emit a slow scasb instruction rather than the faster discrete sequence
> of instructions). Unfortunately, no compiler I've seen will compute the
> length outside the loop, shove that value in a variable, and use that
> value rather than recomputing the length on each pass. C'mon! Loop
> induction is a problem compiler writers solved a long time ago.
> Granted, dealing with aliases (i.e., pointers to character arrays, like
> strings) is a difficult problem for optimizers to deal with, but when
> the body of the loop contains no other character pointer references at
> all, it should be possible for the compiler to move the strlen function
> call outside the loop.
Well, you don't name a compiler, so we can't check, but one thing to try
would be to place your own version of strlen (which is a very simple
routine) in the same file marked "inline". The reason is that yes,
induction variables are a common optimization, and if the compiler had
"inlined" strlen, it probally would have found that.
My guess is that the compiler is being "clever" and recognizing strlen,
and directly substituting code for it. Thats good because it does not
need to grab the strlen code from the library (the soruce code for which is
usually long gone), but bad because it may have short circuited the
induction checks.
>
> I strongly suspect that people who argue that compilers generate code
> that is just as good as a human either:
>
> 1. Only feed their compilers hand-optimized code to begin with (that
> is, they would manually move that strlen call outside the loop),
No, thats not the hallmark of a good compiler. Thats typically
indicative of a poor compiler. If a good compiler can do significant
rearrangement of the code, it could be actually more difficult to make
the compiler generate slow code.
> 2. Don't know enough assembly language to know what is good code and
> what is not code,
> 3. "Cherry pick" optimizations from different compilers, rather than
> sticking with one compiler (e.g., if you consider GCC and VC++, where
> one compiler completely drops the ball on optimization, the other may
> do a good job. If you pick the best code sequence from either compiler
> working on the same program, the result can be quite good). Problem is,
> no compiler generates universally great code. So trying to pass off
> optimizations done by several different compilers as though this was
> current state of the art for a single compiler is disengineous, at
> best.
You named two not particularly good compilers, gcc and vc++ (opps, now
I have inflamed the gcc crowd !). I'd be more interested in what the
Intel vector compiler came up with.
Bottom line, you get what you pay for. Watcom produced compilers that
outperformed Microsoft's own by %10 or more, and they are dead from
lack of demand.
Now we have good compilers for free. We don't have great compilers.
Free is hard to compete with under any conditions.
So although I disagree with your assertation, it may be true for
the current crop of compilers. But it is not true for compilers in
general.
|
|
0
|
|
|
|
Reply
|
Scott
|
4/12/2005 7:49:44 PM
|
|
On Tue, 12 Apr 2005 17:07:13 +0000 (UTC), "randyhyde@earthlink.net"
<spamtrap@crayne.org> wrote:
[snip]
>
>Some of my favorite examples are:
>
>for( i=0; i<strlen( s ); ++i )
>{
> ... // no code that modifies s
>}
>
>Several good compilers are smart enough to replace strlen(s) with
>in-line code that computes the length directly (though they tend to
>emit a slow scasb instruction rather than the faster discrete sequence
>of instructions). Unfortunately, no compiler I've seen will compute the
>length outside the loop, shove that value in a variable, and use that
>value rather than recomputing the length on each pass. C'mon! Loop
>induction is a problem compiler writers solved a long time ago.
>Granted, dealing with aliases (i.e., pointers to character arrays, like
>strings) is a difficult problem for optimizers to deal with, but when
>the body of the loop contains no other character pointer references at
>all, it should be possible for the compiler to move the strlen function
>call outside the loop.
I'm in the habit of manually moving function calls out of loops
wherever possible. My C code is generally hand-optimised[0] as I write
it.
I had to write a compiler for my Uni course this year, using ANTLR and
Java. The basic task was to convert a very simple BASIC-like language
into a simple assembly code that ran on a VM. Once it was working, we
could earn extra marks by adding optimisations.
One of the first things I thought of was shifting code common to both
branches of an IF statement outside it, and moving unchanging results
out of loops. Implementing these things turned out to be too difficult
to figure out on my own and I had to submit the project before I had
time to look at how other compilers did it. That mainstream compilers
might not actually do this never occurred to me!
Currently, I'm working on a language called Megaplex. It falls into
the same horrible category as INTERCAL and Befunge, and I'm wondering
if anyone will ever devise a way of compiling it, since it's
multidimensional and can self-modify. Optimising Megaplex code could
be an... interesting... challenge.
[0] For a given value of 'optimised'...
Alex Davidson
----------------------------------------------------------------------
'You are in the presence of a System Administrator. KNEEL.' --Unknown
|
|
0
|
|
|
|
Reply
|
Alex
|
4/12/2005 7:49:51 PM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> Some of my favorite examples are:
>
> for( i=0; i<strlen( s ); ++i )
> { ... // no code that modifies s }
>
> Several good compilers are smart enough to replace strlen(s)
> with in-line code that computes the length directly (though
> they tend to emit a slow scasb instruction rather than the
> faster discrete sequence of instructions). Unfortunately,
> no compiler I've seen will compute the length outside the
> loop, shove that value in a variable, and use that value
> rather than recomputing the length on each pass. C'mon!
IANA 'c' pgmr, but I do not believe that the `c` standard
would allow this. The std calls for the test to be exec'd
as written every time. The compiler knows _nothing_ about
what strlen() does (until link time when it might inline).
`c` is a fairly low-level language, with precise effects.
If you don't want strlen() run each time, you can certainly
hoist it out of the loop yourself:
k=strlen(s) ;
for (i=0; i<k; ++i) {}
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/12/2005 9:24:19 PM
|
|
>>>>>>>>>
IANA 'c' pgmr, but I do not believe that the `c` standard
would allow this.
<<<<<<<<<
Actually, the C language doesn't explicitly disallow this, so there is
no reason a compiler couldn't do this if the compiler can prove that
the semantics are the same. It is very common, for example, for
compilers to rearrange expressions like the following:
for( i=0; i< j*20/k+m/7; ++i )
{
<< code that does not change the value of k or m>>
}
So that the complex expression is computed once outside of the loop.
>>>>>>
The std calls for the test to be exec'd
as written every time.
<<<<<<
No, it doesn't. The standard calls for the for loop to execute the
number of times specified by the expression. If the expression's value
is static across all iterations of a loop's execution, the compiler
need not recompute that expression on each iteration. GCC, VC++, and
even Borland manage to do this for arithmetic expressions.
>>>>>>
The compiler knows _nothing_ about
what strlen() does (until link time when it might inline).
<<<<<<
This is one area where the C language standard *does* say something.
And what it says is that it's okay for compilers to assume appropriate
semantics for C standard library functions and substitute in-line code
for those functions, should they choose (i.e., no linking involved at
all). Both GCC and VC++ do this all over the place. I believe that
Borland does it, too.
>>>>>>
`c` is a fairly low-level language, with precise effects.
<<<<<<
C may be a fairly low-level language, but don't get the impression the
semantics are precisely specified. If they were, we wouldn't have so
many versions of the language where they've tried to specify the
semantics better. And there are some areas (e.g., involving sequence
points) where the language *explicitly* says it doesn't specify what
happens. That's not very precise.
>>>>>>>
If you don't want strlen() run each time, you can certainly
hoist it out of the loop yourself:
<<<<<<<
Of course, this is good advice and great programmers never write code
like this. The point I'm making however, is that lazy programmers
figure the compiler takes care of everything for them and they don't
have to worry about issues like this. Code movement (e.g., moving
strlen out of a loop like this one) is a "commodity" optimization these
days. There's no execuse for compilers not doing this kind of work.
It's not an impressive optimization at all, which is why I'm amazed
that a compiler would generate code like this.
Now if you *really* want to see some impressive code generation, run
GCC with the /O3 option. The code isn't "safe" under all conditions
(i.e., you have to know what you're doing when you use this option),
but it can do some incredible things. I once saw GCC take a function
that was passed a constant parameter, that called a different function
with that same parameter, and replace the function call with the
constant that the two (nested) function calls would have computed. That
was quite impressive (especially as these were non-trivial functions,
involving standard library calls, and the like).
Of course, as bad as the code is for the 80x86 that these compilers
generate, don't even get me started about how GCC performs on the
PowerPC. That code is UGLY :-(
Cheers,
Randy Hyde
k=strlen(s) ;
for (i=0; i<k; ++i) {}
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/13/2005 4:19:32 AM
|
|
>>>>>
I'm in the habit of manually moving function calls out of loops
wherever possible. My C code is generally hand-optimised[0] as I write
it.
<<<<<
This is a lot of what I'm trying to teach in the examples that I'm
creating. However, it took me by surprise that VC++ did *not* pull this
function call out of the loop. This is a relative straight-forward
optimization given the other types of optimizations that VC++ is doing.
This whole point came up because I'm working on Volume II of my "Write
Great Code" series, in which I go in and show people the kind of code
their compilers are generating when they pull stunts like this. I'd
actually written a paragraph explaining how decent compilers could
detect something like this. I had to modify the paragraph when I
couldn't find a compiler that did what I expected :-)
On a different note, another problem I see with compilers is that it is
very difficult to direct the optimization throughout a C program
without doing a lot of the manual optimizations yourself. Compiler
optimizations are a bit too "coarse-grained" for me. That is, you can
tell the compiler things like "optimize for space" or "optimize for
speed" (and a few gradations inbetween), but there's nothing like a
human being using their brain to determine, on an instruction by
instruction basis, whether it's better to save space or speed. Yep, I
understand that some compilers provide pragmas that let you control
certain optimizations on a line-by-line basis, but unless you actually
see the machine code for each line, it's difficult to determine when
you should use those pragmas. To me, this is the main reason compilers
will *never* do a super great job - they can't make the decisions, on a
line-by-line basis, that a human being can.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/13/2005 4:19:35 AM
|
|
>>>>>>>
Well, you don't name a compiler, so we can't check,
<<<<<<<
This particular example was compiled with VC++ with the /O2 option. It
produced the best code of the three compilers I tried (GCC, VC++,
Borland) for this particular example (all with /O2, or equivalent).
>>>>>>>>>
but one thing to try
would be to place your own version of strlen (which is a very simple
routine) in the same file marked "inline". The reason is that yes,
induction variables are a common optimization, and if the compiler had
"inlined" strlen, it probally would have found that.
<<<<<<<<<
I don't see your point. The compiler replaced the call to strlen with
an in-line code sequence already. Who knows how particular compilers
operate (?), but I suspect that it would be capable of doing a better
job on the code it specifically in-lined versus a function of my own
that it in-lined.
BTW, here is the exact code sequence I was working with (it's not great
C code, I wrote this example to demonstrate some problems with calling
functions to process zero-terminated strings, mainly having to
recompute a string length multiple times -- I had no idea, though, that
the compiler would generate code that computed the string length *this*
many times):
#include <stdlib.h>
size_t mystrcspn( char *src, char *cset )
{
char ch;
int i;
size_t len = 0;
len = 0;
for( ;; )
{
ch = src[ len ];
if( ch == '\0' ) break;
for( i=0; i < strlen( cset ); ++i )
{
if( ch == cset[i] ) break;
}
if( ch == cset[i] ) break;
++len;
}
return len;
}
int main( int argc, char **argv )
{
int i;
char localStr[256];
strcpy( localStr, "hello a world" );
i = mystrcspn( localStr, "a" );
printf( "i=%d\n", i );
return 0;
}
Here's the assembly code that VC++ cranked out:
TITLE t.c
.386P
include listing.inc
if @Version gt 510
..model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
; COMDAT ??_C@_0O@FEO@hello?5a?5world?$AA@
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
; COMDAT ??_C@_01FNLH@a?$AA@
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
; COMDAT ??_C@_05LFEK@i?$DN?$CFd?6?$AA@
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
; COMDAT _mystrcspn
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT _main
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _mystrcspn
; COMDAT _mystrcspn
_TEXT SEGMENT
_src$ = 8
_cset$ = 12
_mystrcspn PROC NEAR ; COMDAT
; File t.c
; Line 12
mov eax, DWORD PTR _src$[esp-4]
push ebx
push ebp
xor ebp, ebp
mov bl, BYTE PTR [eax]
push esi
; Line 13
test bl, bl
push edi
je SHORT $L872
mov esi, DWORD PTR _cset$[esp+12]
$L836:
; Line 14
mov edi, esi
or ecx, -1
xor eax, eax
xor edx, edx
repne scasb
not ecx
dec ecx
je SHORT $L867
$L839:
; Line 16
cmp bl, BYTE PTR [edx+esi]
je SHORT $L872
mov edi, esi
or ecx, -1
xor eax, eax
inc edx
repne scasb
not ecx
dec ecx
cmp edx, ecx
jb SHORT $L839
$L867:
; Line 18
cmp bl, BYTE PTR [edx+esi]
je SHORT $L872
mov ecx, DWORD PTR _src$[esp+12]
; Line 19
inc ebp
mov bl, BYTE PTR [ecx+ebp]
test bl, bl
jne SHORT $L836
$L872:
pop edi
; Line 21
mov eax, ebp
pop esi
pop ebp
pop ebx
; Line 22
ret 0
_mystrcspn ENDP
_TEXT ENDS
PUBLIC _main
PUBLIC ??_C@_0O@FEO@hello?5a?5world?$AA@ ; `string'
PUBLIC ??_C@_01FNLH@a?$AA@ ; `string'
PUBLIC ??_C@_05LFEK@i?$DN?$CFd?6?$AA@ ; `string'
EXTRN _printf:NEAR
; COMDAT ??_C@_0O@FEO@hello?5a?5world?$AA@
; File t.c
_DATA SEGMENT
??_C@_0O@FEO@hello?5a?5world?$AA@ DB 'hello a world', 00H ; `string'
_DATA ENDS
; COMDAT ??_C@_01FNLH@a?$AA@
_DATA SEGMENT
??_C@_01FNLH@a?$AA@ DB 'a', 00H ; `string'
_DATA ENDS
; COMDAT ??_C@_05LFEK@i?$DN?$CFd?6?$AA@
_DATA SEGMENT
??_C@_05LFEK@i?$DN?$CFd?6?$AA@ DB 'i=%d', 0aH, 00H ; `string'
_DATA ENDS
; COMDAT _main
_TEXT SEGMENT
_localStr$ = -256
_main PROC NEAR ; COMDAT
; File t.c
; Line 24
sub esp, 256 ; 00000100H
; Line 28
mov ecx, DWORD PTR ??_C@_0O@FEO@hello?5a?5world?$AA@+4
mov eax, DWORD PTR ??_C@_0O@FEO@hello?5a?5world?$AA@
mov edx, DWORD PTR ??_C@_0O@FEO@hello?5a?5world?$AA@+8
mov DWORD PTR _localStr$[esp+260], ecx
mov DWORD PTR _localStr$[esp+256], eax
mov ax, WORD PTR ??_C@_0O@FEO@hello?5a?5world?$AA@+12
; Line 29
lea ecx, DWORD PTR _localStr$[esp+256]
push OFFSET FLAT:??_C@_01FNLH@a?$AA@ ; `string'
push ecx
mov DWORD PTR _localStr$[esp+272], edx
mov WORD PTR _localStr$[esp+276], ax
call _mystrcspn
; Line 30
push eax
push OFFSET FLAT:??_C@_05LFEK@i?$DN?$CFd?6?$AA@ ; `string'
call _printf
; Line 31
xor eax, eax
; Line 32
add esp, 272 ; 00000110H
ret 0
_main ENDP
_TEXT ENDS
END
>>>>>>>>>>>>>>
You named two not particularly good compilers, gcc and vc++ (opps, now
I have inflamed the gcc crowd !). I'd be more interested in what the
Intel vector compiler came up with.
<<<<<<<<<<<<<<
I've named the two compilers *most* people use. You are now guilty of
exactly the point I'm making - people make claims for compilers in
general. In your case, when a flaw is pointed out in a particular
compiler, the response is almost always (naturally) "well, get a better
compiler!" My argument is that, while a different compiler may handle a
particular situation better than other compilers, I've yet to see a
compiler that is universally good for all inputs. And it is this
"universal" set of optimizations that HLL/optimizer proponents tend to
claim for compiler technology. Yes, some compilers are better than
others. But keep in mind:
1. Those better compilers are not the ones most people use. And most
people aren't in a position to use those better compilers (their use
might be cost prohibitive, for example). HLL/optimizer proponents don't
qualify their statements by saying things like "using a special
compiler, certain common sequences get compiled to machine code as good
as a human would produce." No, they simply say "today's compilers
produce code ever bit as good as an assembly programmer."
2. All compilers have certain things they're good at, and certain
things they are not so good at. VC++ and GCC, despite your claims that
they are bad, *do* compile certain sequences to really good machine
code. The problem is, they inject some really bad translations in
there, as well. And I've found this principle to be true for all
compilers.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/13/2005 4:19:43 AM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> No, it doesn't. The standard calls for the for loop to
> execute the number of times specified by the expression. If
No, `c` ain't my beloved FORTRAN. The for() loop is a slight
restatement of a while() loop, at least according to K&R.
> the expression's value is static across all iterations of
> a loop's execution, the compiler need not recompute that
> expression on each iteration. GCC, VC++, and even Borland
> manage to do this for arithmetic expressions.
They simplify and reduce the expression. They still do
a test before executing the loop. That test is required
by K&R App A "c reference manual" 9.6
> <<<<<< C may be a fairly low-level language, but don't get
> the impression the semantics are precisely specified. If
> they were, we wouldn't have so many versions of the language
> where they've tried to specify the semantics better. And
> there are some areas (e.g., involving sequence points)
> where the language *explicitly* says it doesn't specify
> what happens. That's not very precise.
Sure it is. It means you cannot rely upon something you
wanted to rely upon. Most people go away unhappy.
> The point I'm making however, is that lazy programmers figure
> the compiler takes care of everything for them and they
> don't have to worry about issues like this. Code movement
> (e.g., moving strlen out of a loop like this one) is a
> "commodity" optimization these days. There's no execuse
> for compilers not doing this kind of work. It's not an
> impressive optimization at all, which is why I'm amazed
> that a compiler would generate code like this.
Are you advocating for lazyiness?
`c` was originally designed and written as a portable
assembler. In that spirit, `c` compilers should perform no
optimization that the programmer could. After all, people
could be interested in side-effects or performing the work
as stated, not as solved.
If people want some optimizing language, they should choose
one with that goal, like FORTRAN or PASCAL. But _nnooo_,
they've heard `c` is powerful and want to use it. Well,
it is powerful, but will blow up in beginners hands.
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/13/2005 2:39:29 PM
|
|
On Wed, 13 Apr 2005 04:19:32 +0000 (UTC)
"randyhyde@earthlink.net" <spamtrap@crayne.org> wrote:
> >>>>>>>>>
> IANA 'c' pgmr, but I do not believe that the `c` standard
> would allow this.
> <<<<<<<<<
> Actually, the C language doesn't explicitly disallow this, so there is
> no reason a compiler couldn't do this if the compiler can prove that
> the semantics are the same. It is very common, for example, for
> compilers to rearrange expressions like the following:
>
> for( i=0; i< j*20/k+m/7; ++i )
> {
> << code that does not change the value of k or m>>
> }
>
> So that the complex expression is computed once outside of the loop.
The compiler might not know that "strlen" always computes the same value
when you give it the same input. GCC has an attribute keyword for this
kind of functions, "pure" or similar.
> ...
|
|
0
|
|
|
|
Reply
|
Johannes
|
4/13/2005 7:22:12 PM
|
|
randyhyde@earthlink.net wrote:
> Well, you don't name a compiler, so we can't check,
> <<<<<<<
> This particular example was compiled with VC++ with the /O2 option. It
> produced the best code of the three compilers I tried (GCC, VC++,
> Borland) for this particular example (all with /O2, or equivalent).
>
>
> but one thing to try
> would be to place your own version of strlen (which is a very simple
> routine) in the same file marked "inline". The reason is that yes,
> induction variables are a common optimization, and if the compiler had
> "inlined" strlen, it probally would have found that.
> <<<<<<<<<
> I don't see your point. The compiler replaced the call to strlen with
> an in-line code sequence already. Who knows how particular compilers
> operate (?), but I suspect that it would be capable of doing a better
> job on the code it specifically in-lined versus a function of my own
> that it in-lined.
Because most compilers process "inline" at the intermediate code level.
That means that the routine that is inlined can get woven into the code,
and then optimizations occur after that. For example:
void max(int a, int b) { if (a > b) return a; else return b; }
...
for (i = 0; i < 10; i++) { q = max(c, d); }
When inlined, becomes:
for (i = 0; i < 10; i++) { int x; if (c > d) x = c; else x = d; q = x; }
Then all the invariant and other optimizations come into play.
>
> You named two not particularly good compilers, gcc and vc++ (opps, now
> I have inflamed the gcc crowd !). I'd be more interested in what the
> Intel vector compiler came up with.
> <<<<<<<<<<<<<<
>
> I've named the two compilers *most* people use. You are now guilty of
> exactly the point I'm making - people make claims for compilers in
> general. In your case, when a flaw is pointed out in a particular
> compiler, the response is almost always (naturally) "well, get a better
> compiler!" My argument is that, while a different compiler may handle a
> particular situation better than other compilers, I've yet to see a
> compiler that is universally good for all inputs. And it is this
> "universal" set of optimizations that HLL/optimizer proponents tend to
> claim for compiler technology. Yes, some compilers are better than
> others. But keep in mind:
You are comparing against a freeware compiler. You got what you paid for.
If you paid for, say, the Intel vector compiler and got poor results,
I would understand.
But for a *free* compiler, gcc is a pretty damm good deal.
>
> 1. Those better compilers are not the ones most people use. And most
> people aren't in a position to use those better compilers (their use
> might be cost prohibitive, for example). HLL/optimizer proponents don't
> qualify their statements by saying things like "using a special
> compiler, certain common sequences get compiled to machine code as good
> as a human would produce." No, they simply say "today's compilers
> produce code ever bit as good as an assembly programmer."
No, I am not going to hold compilers to the *least common denominator*.
You got GCC for free, now that does not mean you get to say that all
compilers suck because of that. Come on.
>
> 2. All compilers have certain things they're good at, and certain
> things they are not so good at. VC++ and GCC, despite your claims that
> they are bad, *do* compile certain sequences to really good machine
> code. The problem is, they inject some really bad translations in
> there, as well. And I've found this principle to be true for all
> compilers.
>
> Cheers,
> Randy Hyde
>
Again, the two compilers you are using are gcc and VC++. A free compiler,
and a compiler that is so bad that it is legendary. From this, it is
patently absurd to draw conclusions about *ALL* compilers.
Instead of beating up two low end compilers, what say you stick a
crowbar in that wallet fattened by your books, buy a decent compiler,
and tell us about that.
|
|
0
|
|
|
|
Reply
|
Scott
|
4/13/2005 7:22:16 PM
|
|
Mark Gibson <spamtrap@crayne.org> wrote:
> A full-blown VAX instruction set implemented in hardware,
> not firmware. The busses would have to be on the wide
> side so we're looking at at least a six-layer mobo and
> an expensive chipset in addition to a pricey CPU.
This sounds like an Alpha.
> I'm hoping my new AMD 64-bit CPU might come close.
I very much doubt it. A patch upon a patch, even if
they're clever patches. The AMD K8 is impressive,
however, and it's on-die MMU (no Northbridge) should
help reduce latency a great deal.
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/13/2005 8:25:41 PM
|
|
On Tue, 12 Apr 2005 17:07:13 +0000 (UTC), "randyhyde@earthlink.net"
<spamtrap@crayne.org> wrote:
<snip>
> Compiler optimizers alternately amaze me and confound me. <snip>
I agree with you there.
> Some of my favorite examples are:
>
> for( i=0; i<strlen( s ); ++i )
> {
> ... // no code that modifies s
> }
>
the content of s if an array; if a pointer neither the buffer it
points to _or_ the pointer itself to point somewhere else. Including
via another pointer, or a potential store in e.g. a called function.
> Several good compilers are smart enough to replace strlen(s) with
> in-line code that computes the length directly (though they tend to
> emit a slow scasb instruction rather than the faster discrete sequence
> of instructions). Unfortunately, no compiler I've seen will compute the
> length outside the loop, shove that value in a variable, and use that
> value rather than recomputing the length on each pass. C'mon! Loop
> induction is a problem compiler writers solved a long time ago.
> Granted, dealing with aliases (i.e., pointers to character arrays, like
> strings) is a difficult problem for optimizers to deal with, but when
> the body of the loop contains no other character pointer references at
> all, it should be possible for the compiler to move the strlen function
> call outside the loop.
>
Somewhat unfortunate example. C allows _any_ object to be aliased as
characters, to access the underlying but in general platform or even
compiler dependent representation. Thus a store through _any_ pointer
in the loop body which can't be proven distinct from s[0..?] kills it.
Of course the arguably more idiomatic C way of writing this, except in
the extremely rare case you actually want clobber semantics, is:
for( i = 0; s[i] /* != '\0' */; ++i ) etc.
which does not need that optimization.
C99 -- when implemented/used -- has a new feature 'restrict' pointers
whose target is promised to be unaliased, allowing the optimizations
that follow from that. This makes life somewhat easier on the compiler
writer by putting the responsibility, and some of work, back on the
programmers -- who you already said, and again I agree, are too often
falling down on the job they have now. Oh, well.
- David.Thompson1 at worldnet.att.net
|
|
0
|
|
|
|
Reply
|
Dave
|
4/18/2005 6:11:46 AM
|
|
Dave Thompson wrote:
>
> > Some of my favorite examples are:
> >
> > for( i=0; i<strlen( s ); ++i )
> > {
> > ... // no code that modifies s
> > }
> >
> >
> Somewhat unfortunate example. C allows _any_ object to be aliased as
> characters, to access the underlying but in general platform or even
> compiler dependent representation. Thus a store through _any_ pointer
> in the loop body which can't be proven distinct from s[0..?] kills
it.
When I said "no code that modifies s", I meant it. No way, no how. No
references to s. No references to any functions (that might modify s as
a side effect), nada. MSVC *knows* the semantics of strlen, because it
translated this function call to a discrete sequence of machine
instructions (i.e., using scasb).
>
> Of course the arguably more idiomatic C way of writing this, except
in
> the extremely rare case you actually want clobber semantics, is:
> for( i = 0; s[i] /* != '\0' */; ++i ) etc.
> which does not need that optimization.
The point is not that a human couldn't rewrite the code to optimize it.
Indeed, that's exactly the project I'm working on right now (explaining
how one can write such HLL code to begin with). My gripe is that
compilers do such a great job of translating all these different
constructs to machine code and then fall flat on their faces on some
code sequences that they should handle without problem.
>
> C99 -- when implemented/used -- has a new feature 'restrict' pointers
> whose target is promised to be unaliased, allowing the optimizations
> that follow from that. This makes life somewhat easier on the
compiler
> writer by putting the responsibility, and some of work, back on the
> programmers -- who you already said, and again I agree, are too often
> falling down on the job they have now. Oh, well.
Yep. Sort of like GCC's "/O3" option, when can produce "unsafe" code
and the programmer has to take more of the responsibility for the
result.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/18/2005 9:20:54 AM
|
|
Johannes@aioe.org wrote:
> > So that the complex expression is computed once outside of the
loop.
>
> The compiler might not know that "strlen" always computes the same
value
> when you give it the same input. GCC has an attribute keyword for
this
> kind of functions, "pure" or similar.
Perhaps, in general, this statement is true. In the specific case I'm
giving, however, MSVC *does* know exactly what this function does
because it replaces the function call with in-line code (allowed by the
C standard). Given that it's smart enough to do this, one would expect
it to be smart enough to enlist code motion to move that test for
strlen outside the loop.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/18/2005 9:20:57 AM
|
|
Scott Moore wrote:
>
> Because most compilers process "inline" at the intermediate code
level.
> That means that the routine that is inlined can get woven into the
code,
> and then optimizations occur after that. For example:
>
> void max(int a, int b) { if (a > b) return a; else return b; }
>
> ..
>
> for (i = 0; i < 10; i++) { q = max(c, d); }
>
> When inlined, becomes:
>
> for (i = 0; i < 10; i++) { int x; if (c > d) x = c; else x = d; q =
x; }
>
> Then all the invariant and other optimizations come into play.
Okay, my point exactly...
> >
> > I've named the two compilers *most* people use. You are now guilty
of
> > exactly the point I'm making - people make claims for compilers in
> > general. In your case, when a flaw is pointed out in a particular
> > compiler, the response is almost always (naturally) "well, get a
better
> > compiler!" My argument is that, while a different compiler may
handle a
> > particular situation better than other compilers, I've yet to see a
> > compiler that is universally good for all inputs. And it is this
> > "universal" set of optimizations that HLL/optimizer proponents tend
to
> > claim for compiler technology. Yes, some compilers are better than
> > others. But keep in mind:
>
> You are comparing against a freeware compiler. You got what you paid
for.
> If you paid for, say, the Intel vector compiler and got poor results,
> I would understand.
>
> But for a *free* compiler, gcc is a pretty damm good deal.
I'm not questioning the *value* of a free compiler like GCC or even the
value of a commercial compiler like MSVC. What I'm saying is that
people are led to believe that compilers such as these produce
infailable machine code of very high quality (and, they *usually* do).
Therefore, there is no need to optimize their own code (by doing
things, for example, like moving function calls to strlen outside of a
loop if the calculation is loop invariant).
>
> >
> > 1. Those better compilers are not the ones most people use. And
most
> > people aren't in a position to use those better compilers (their
use
> > might be cost prohibitive, for example). HLL/optimizer proponents
don't
> > qualify their statements by saying things like "using a special
> > compiler, certain common sequences get compiled to machine code as
good
> > as a human would produce." No, they simply say "today's compilers
> > produce code ever bit as good as an assembly programmer."
>
> No, I am not going to hold compilers to the *least common
denominator*.
> You got GCC for free, now that does not mean you get to say that all
> compilers suck because of that. Come on.
No, I'm not saying "all compilers suck." What I'm saying is that it is
amazing that every compiler I have access to has its own idiosyncrasies
that cause it to fall flat on its face in certain instances. The
example I'm giving is one where MSVC doesn't do particuarly well.
>
> Again, the two compilers you are using are gcc and VC++. A free
compiler,
> and a compiler that is so bad that it is legendary. From this, it is
> patently absurd to draw conclusions about *ALL* compilers.
Show me a compiler that produces great code under *ALL* circumstances.
Your defense is exactly the problem I'm talking about. When confronted
with examples of bad code generation, the apologists in the crowd
always come back with "well, you're just using the wrong compiler"
without giving an example of a compiler that works under all
circumstances. Making statements like "well, have you tried the Intel
vectorizing compiler" is a weak comeback. No doubt, other compilers
will handle the simple for loop I've given in a manner I would expect.
That doesn't mean those same compilers don't fall on their faces
elsewhere.
>
> Instead of beating up two low end compilers, what say you stick a
> crowbar in that wallet fattened by your books,
You really know nothing about the economics of authoring books, do you?
Let me give you a hint, you don't make much money as the author of a
typical book.
> buy a decent compiler,
> and tell us about that.
I'm still waiting for you to post the code from a compiler you feel
does a whole lot better. If you have access to such a compiler, I'll
be more than happy to send you code to run through it. But I'm not
going to pay thousands of dollars for a few compiler tools just so I
can find problems with them elsewhere.
As for beating up on "two low end compilers", hey, *these* are the
compilers that *most* people use. These are the ones that programmers
have been taught to believe generate great code by reading comments
such as your's. They're the ones most deserving of being beaten up.
People need to know that they cannot rely on comments like "compilers
generate better machine code than human beings."
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/18/2005 6:42:56 PM
|
|
Robert Redelmeier wrote:
> > execute the number of times specified by the expression. If
>
> No, `c` ain't my beloved FORTRAN. The for() loop is a slight
> restatement of a while() loop, at least according to K&R.
okay...
>
> > the expression's value is static across all iterations of
> > a loop's execution, the compiler need not recompute that
> > expression on each iteration. GCC, VC++, and even Borland
> > manage to do this for arithmetic expressions.
>
> They simplify and reduce the expression. They still do
> a test before executing the loop. That test is required
> by K&R App A "c reference manual" 9.6
What makes you think the test is required?
If this is the case, then most optimizing C compilers are severely
broken. After all, It's not all that uncommon for optimizing compilers
to eliminate the code for a for loop altogether. For example, both GCC
and MSVC will completely eliminate a for loop that computes a constant
result that the compiler can determine at compile-time (assuming, of
course, that you've set the optimization level high enough).
>
> > <<<<<< C may be a fairly low-level language, but don't get
> > the impression the semantics are precisely specified. If
> > they were, we wouldn't have so many versions of the language
> > where they've tried to specify the semantics better. And
> > there are some areas (e.g., involving sequence points)
> > where the language *explicitly* says it doesn't specify
> > what happens. That's not very precise.
>
> Sure it is. It means you cannot rely upon something you
> wanted to rely upon. Most people go away unhappy.
It's precise in its unpreciseness, eh?
>
> > The point I'm making however, is that lazy programmers figure
> > the compiler takes care of everything for them and they
> > don't have to worry about issues like this. Code movement
> > (e.g., moving strlen out of a loop like this one) is a
> > "commodity" optimization these days. There's no execuse
> > for compilers not doing this kind of work. It's not an
> > impressive optimization at all, which is why I'm amazed
> > that a compiler would generate code like this.
>
> Are you advocating for lazyiness?
Quite the opposite. I'm advocating that programmers take more
responsibility for optimizing their own code rather than relying upon
their compilers to handle this stuff for them. OTOH, it's important for
programmers to know what their compilers are capable of doing so they
can determine when it's okay to create a programming language construct
that is easier to read (but seemingly less optimal) and can
realistically expect the compiler to cover up for them. Arguably, for
example, leaving the call to strlen in the for loop is a good idea
(from a readability point of view) because it keeps the calculation of
the length as close to the point of use as possible. Manually moving
the calculation elsewhere in the program and passing in the computed
value adds a small level of indirection to the whole process, making
the program slightly more difficult to read. So there *are* defensible
reasons for wanting to write code in this manner. This techique would
be *very* defensible if one could count on compilers doing
well-understood tasks such as moving loop invariant calculations
outside of a loop. Given that code motion of this manner is a
well-understood optimization, it's surprising that a compiler such as
MSVC doesn't do this.
>
> `c` was originally designed and written as a portable
> assembler. In that spirit, `c` compilers should perform no
> optimization that the programmer could. After all, people
> could be interested in side-effects or performing the work
> as stated, not as solved.
Well, compiler vendors beg to disagree. In their opinions, people use
C/C++ because of its reputation as a fast language. More research has
probably gone into optimizing C machine code output than any other
programming language in history.
>
> If people want some optimizing language, they should choose
> one with that goal, like FORTRAN or PASCAL. But _nnooo_,
> they've heard `c` is powerful and want to use it. Well,
> it is powerful, but will blow up in beginners hands.
In theory, FORTRAN and Pascal programs *should* be optimizable to a
better result than an equivalent C program. In practice, as I just
mentioned, more research has gone into optimizing C than these other
languages (though FORTRAN is probably in second place, not too far
behind). But that's still orthogonal to the real issue -- people have
been told that optimizing compilers do such a great job that human
coders can't compete. Yet when you look at the state of the art in
commonly-used compilers, this just isn't the case. The response always
seems to be "well then you should be using a different compiler." You
never hear the argument "If you're using the *right* compiler and you
write your HLL code in a careful fashion then *much* of the time the
compiler produces code as good as a human assembly programmer."
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/18/2005 6:43:00 PM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
>> a test before executing the loop. That test is required
>> by K&R App A "c reference manual" 9.6
>
> What makes you think the test is required?
The words "; the second specifies a test, made before each iteration,
such that the loop is exited when the expression becomes 0;"
That sounds like a requirement to me.
> If this is the case, then most optimizing C compilers are
> severely broken.
Getting in trouble from taking shortcuts is very common.
The compiler may be standards compliant only at -O0 .
> It's precise in its unpreciseness, eh?
Exactly!
> Quite the opposite. I'm advocating that programmers take
> more responsibility for optimizing their own code rather than
> relying upon their compilers to handle this stuff for them.
Always good.
> a programming language construct that is easier to read (but
"Easier to read" is a value judgement. People have different
values. Compilers have even more different ones.
> Arguably, for example, leaving the call to strlen in the
> for loop is a good idea (from a readability point of view)
> because it keeps the calculation of the length as close to
> the point of use as possible.
But it means something different. What happens if this nice
proggie is multithreaded, and other threads change strlen()?
Then the `for` semantics is essential. [But watch for fireworks
when strlen() get smaller].
> Manually moving the calculation elsewhere in the program
> and passing in the computed value adds a small level
> of indirection to the whole process, making the program
> slightly more difficult to read.
Vanishlingly so if k = strlen(s) ; is immediate before the
`for` loop. It makes it extremely clear what is going on.
One of the problems with `c` is that people like to overload
lines so that it begins to look like APL. I'm guilty too,
but I know it's because of semicolonophobia.
> it's surprising that a compiler such as MSVC doesn't do this.
Perhaps because strlen() is modifiable? It is not a reserved word.
> Well, compiler vendors beg to disagree. In their opinions, people
> use C/C++ because of its reputation as a fast language.
Of course a portable assembler is going to be fast. And loose.
> people have been told that optimizing compilers do such
> a great job that human coders can't compete.
I think you've address this well in "The Great Debate".
In a knutshell, the complier helps the `c` newbie write much
faster code than the ASM newbie (mostly buffered libcalls).
However, the master `c` programmer is whipped by the ASM master.
People stick with `c` for other reasons (maintainability, portability,
availability of `c` novices to sacrifice to it).
> never hear the argument "If you're using the *right* compiler
> and you write your HLL code in a careful fashion then *much*
> of the time the compiler produces code as good as a human
> assembly programmer."
And this is a good argument for understanding the quirks of
compilers. The best way I know is to look at their ASM output.
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/18/2005 7:46:01 PM
|
|
Robert Redelmeier wrote:
> randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> >> a test before executing the loop. That test is required
> >> by K&R App A "c reference manual" 9.6
> >
> > What makes you think the test is required?
>
> The words "; the second specifies a test, made before each iteration,
> such that the loop is exited when the expression becomes 0;"
>
> That sounds like a requirement to me.
No. It is not a requirement. Language specifications are pretty good
about specifying semantics and leaving the actual code generation up to
the compiler's implementor. For example, is a compiler writer forced to
compare the value one against zero in the following for loop:
for( ;1; )
And what happens in the canonical infinite loop in C?
for(;;)
The statement you quote above discusses the C *source* language, not
the code that the compiler generates.
And another thing you might consider is that compiler optimization was
in its infancy when K&R was written, and they probably weren't even
thinking about it at the time, or they might have been a bit more
precise in their book describing the C language. Finally, note that
K&R is *not* C as we know it today. The ANSI spec is a *lot* clearer on
the semantics of optimizations that can be performed.
C compilers do eliminate the for loop. Entirely in some cases. Consider
the following code:
int main( int argc, char **argv )
{
int i;
char array[4];
for(i=0; i<4; ++i)
array[i] = 0;
printf( "%d %d\n", array[0], array[3] );
return 0;
}
Here's the x86 assembly that MSVC emits for the body of the main
function:
; Line 9
xor eax, eax
mov DWORD PTR _array$[esp+4], eax
; Line 11
movsx ecx, BYTE PTR _array$[esp+7]
movsx edx, al
push ecx
push edx
push OFFSET FLAT:??_C@_06CMFP@?$CFd?5?$CFd?6?$AA@ ; `string'
call _printf
Whoa! Where did the for loop go? Well, the compiler was smart enough to
realize that writing a dword containing zero to the array variable did
all the work (much more efficiently) of the for loop. This type of
optimization is *hardly* particular to MSVC. Most decent compilers can
pull tricks like this.
In cases where tricks like this aren't possible, compilers can still
use loop induction variable optimization to completely change the type
of test they perform in the for loop. Consider the following C code:
#include <stdlib.h>
struct
{
char padding [8];
int anInt;
} aStruct[4];
int main( int argc, char **argv )
{
int i;
for(i=0; i<4; ++i)
aStruct[i].anInt = i;
printf( "%d %d\n", aStruct[0].anInt, aStruct[3].anInt );
return 0;
}
Here's the x86 code that MSVC emits:
; Line 13
xor ecx, ecx
mov eax, OFFSET FLAT:_aStruct+8
$L837:
; Line 14
mov DWORD PTR [eax], ecx
add eax, 12 ; 0000000cH
inc ecx
cmp eax, OFFSET FLAT:_aStruct+56
jl SHORT $L837
; Line 16
mov eax, DWORD PTR _aStruct+44
mov ecx, DWORD PTR _aStruct+8
push eax
push ecx
push OFFSET FLAT:??_C@_06CMFP@?$CFd?5?$CFd?6?$AA@ ; `string'
call _printf
Well, you can see that the for loop was emitted to this assembly
output. But note that nowhere is there a test for "i<4". The test for
the for loop checks to see if a pointer (held in EAX) exceeds an
array's bounds. Again, this is a *typical* induction variable
optimization that most modern compilers will do. Believe me, if the
specs *ever* prevented this type of optimization, the compiler writers
would have been all over the specification design (actually, they have
been, but for other issues).
>
> > If this is the case, then most optimizing C compilers are
> > severely broken.
>
> Getting in trouble from taking shortcuts is very common.
> The compiler may be standards compliant only at -O0 .
The compiler may not be compliant at all. MSVC, for example, is famous
for skirting the rules. In this particular case, however, MSVC (Gas,
Borland, and others) is well within the specs to skip with the loop
test if it is unnecessary.
>
> > It's precise in its unpreciseness, eh?
>
> Exactly!
Well, then you have a strange definition of preciseness.
Me thinks you've moved *way* to far to the defensive side here,
unwilling to admit that you overstated things a bit.
>
> > Quite the opposite. I'm advocating that programmers take
> > more responsibility for optimizing their own code rather than
> > relying upon their compilers to handle this stuff for them.
>
> Always good.
>
> > a programming language construct that is easier to read (but
>
> "Easier to read" is a value judgement. People have different
> values. Compilers have even more different ones.
The common consensus in most software engineering texts is that the
closer you move a computation to the point where the result of that
computation is used, the better. People have done a lot of research on
this, so I'm willing to take their word over a debate in an assembly
language programming newsgroup on USENET (the pinnacle of truth!).
>
> > Arguably, for example, leaving the call to strlen in the
> > for loop is a good idea (from a readability point of view)
> > because it keeps the calculation of the length as close to
> > the point of use as possible.
>
> But it means something different. What happens if this nice
> proggie is multithreaded, and other threads change strlen()?
> Then the `for` semantics is essential. [But watch for fireworks
> when strlen() get smaller].
Then the programmer will have to protect the execution of that loop.
Note that the process that interrupts the for loop could also be
interrupting the strlen calculation itself. If such multithreaded
applications are pouncing on each other's strings, they're going to
break. Moving the strlen calculation out of the loop may actually help
*improve* the situation (not fix it, but make the problem less likely
to occur) because you're only exposed during the strlen function once
rather than on each iteration of the loop. And strlen is *not* thread
safe (at least, the version that MSVC compiles into a scasb
instruction). Let's look at the x86 code that MSVC emits for the for
loop in question (gets and putch are added to prevent the compiler from
optmizing away the code):
#include <stdlib.h>
int main( int argc, char **argv )
{
int i;
char s[256];
gets( s );
for( i=0; i<strlen(s); ++i )
{
putch( s[i] );
}
return 0;
}
Here's the output x86 code:
_s$ = -256
_main PROC NEAR
; File t.c
; Line 5
sub esp, 256
; Line 9
lea eax, DWORD PTR _s$[esp+256]
push esi
push edi
push eax
call _gets
; Line 10
lea edi, DWORD PTR _s$[esp+268]
or ecx, -1
xor eax, eax
add esp, 4
xor esi, esi
repne scasb
not ecx
dec ecx
je SHORT $L845
$L835:
; Line 12
movsx ecx, BYTE PTR _s$[esp+esi+264]
push ecx
call _putch
add esp, 4
lea edi, DWORD PTR _s$[esp+264]
or ecx, -1
xor eax, eax
inc esi
repne scasb
not ecx
dec ecx
cmp esi, ecx
jb SHORT $L835
$L845:
pop edi
; Line 14
xor eax, eax
pop esi
; Line 16
add esp, 256
ret 0
_main ENDP
Because scasb is interruptible, this code is *not* thread safe. If the
compiler is going to emit thread unsafe code that computes the string
length, why would it fail to do other optimizations based on the belief
that such optmizations would fail in a multi-threaded environment?
>
> > Manually moving the calculation elsewhere in the program
> > and passing in the computed value adds a small level
> > of indirection to the whole process, making the program
> > slightly more difficult to read.
>
> Vanishlingly so if k = strlen(s) ; is immediate before the
> `for` loop. It makes it extremely clear what is going on.
Not vanishingly so. "for(i=0;i<strlen(s);++i)}" is a bit easier to read
and comprehend than
k=strlen( s );
for( i=0; i<k; ++i )
There's less cruft to deal with in the former example and it requires
less mental processing. There is also the case of someone having to
read the declaration for the k variable and figure out what it's used
for. This may seem trivial in an isolated example such as this one, but
when you have a large program full of constructs like this, it has a
big impact on readability.
>
> One of the problems with `c` is that people like to overload
> lines so that it begins to look like APL. I'm guilty too,
> but I know it's because of semicolonophobia.
Not sure I follow what you mean.
Yes, it takes *work* to write readable C code. By default, it's much
easier to write difficult to read code. That's why it helps if you can
count on the compiler to handle some obvious things (like moving a loop
invariant calculation out of a for loop) so you can keep the code as
readable as possible. This has nothing to do with laziness and
everything to do with thinking about the poor soul who has got to read
your code when you're done with it.
>
> > it's surprising that a compiler such as MSVC doesn't do this.
>
> Perhaps because strlen() is modifiable? It is not a reserved word.
This has nothing to do with moving the code that computes strlen (see
the previous example) out of the loop. Whether strlen is computed
in-line, a function is called, whatever, the calculation *can* be moved
out of the loop as the value of s does not change.
BTW, although strlen is not a keyword in C, it is a *special*
identifier that the compiler is allowed to recognize and treat
specially (as MSVC and other compilers certainly do).
>
> > Well, compiler vendors beg to disagree. In their opinions, people
> > use C/C++ because of its reputation as a fast language.
>
> Of course a portable assembler is going to be fast. And loose.
In 1971 the definition of C was loose. It's been tightened up *just* a
bit since then.
>
> > people have been told that optimizing compilers do such
> > a great job that human coders can't compete.
>
> I think you've address this well in "The Great Debate".
>
> In a knutshell, the complier helps the `c` newbie write much
> faster code than the ASM newbie (mostly buffered libcalls).
> However, the master `c` programmer is whipped by the ASM master.
> People stick with `c` for other reasons (maintainability,
portability,
> availability of `c` novices to sacrifice to it).
Beginning programmers are going to write lousy code; that's to be
expected. The problem with the "great debate" is that it *falsely*
gives HLL programmers a "security blanket" and lets them think that
they don't have to worry about optimization at all. All the time they
argue about how great their compiler is doing without really knowing
what's going on behind their backs.
A *good* C programmer, who also happens to know assembly language, and
write some *damn* good C code by hand optimizing their C statements to
produce good machine code output (e.g., as has been claimed for the
Linux Kernel). My complaint about this for loop example is that this
is an optimization one should *expect* a compiler to do (and some
compilers *will* do it; this isn't the most difficult concept in
compiler optimization theory). The point being is that a good C
programmer will find it difficult to find a common set of optimizations
they can count on, so they can move their C source files from compiler
to compiler without worrying about degenerate behavior. In Write Great
Code, Volume II, for example, I have to tell the programmers that they
need to sacrifice a little readability and manually watch for loop
invariant calculations because under some circumstances, compilers
won't do the job for them. Again, this for loop example is rather
trivial. It's easy enough, however, to create slightly more complex
examples where the readability takes a big hit because you've got to
move a loop invariant calculation of out a (deeply nested, for example)
loop.
>
> > never hear the argument "If you're using the *right* compiler
> > and you write your HLL code in a careful fashion then *much*
> > of the time the compiler produces code as good as a human
> > assembly programmer."
>
> And this is a good argument for understanding the quirks of
> compilers. The best way I know is to look at their ASM output.
And that's what a large part of my new book is all about.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/18/2005 9:39:02 PM
|
|
randyhyde@earthlink.net wrote:
> And another thing you might consider is that compiler optimization was
> in its infancy when K&R was written, and they probably weren't even
> thinking about it at the time, or they might have been a bit more
> precise in their book describing the C language.
Absolutely untrue. Code hoisting, inducition variables, data graphs, virtually
ALL of the modern optimizations were present before K&R. See for example David
Gries et all from the 1960s.
|
|
0
|
|
|
|
Reply
|
Scott
|
4/18/2005 11:11:15 PM
|
|
randyhyde@earthlink.net wrote:
>>
>>But for a *free* compiler, gcc is a pretty damm good deal.
>
>
> I'm not questioning the *value* of a free compiler like GCC or even the
> value of a commercial compiler like MSVC. What I'm saying is that
> people are led to believe that compilers such as these produce
> infailable machine code of very high quality (and, they *usually* do).
> Therefore, there is no need to optimize their own code (by doing
> things, for example, like moving function calls to strlen outside of a
> loop if the calculation is loop invariant).
>
I would never imply that VC++ or GCC produce infailable machine code.
In my opinion, based on looking at the output in assembly, and the
results on benchmarks, that VC is not good at all, and GCC, while better,
is hardly ideal.
> I'm still waiting for you to post the code from a compiler you feel
> does a whole lot better. If you have access to such a compiler, I'll
> be more than happy to send you code to run through it. But I'm not
> going to pay thousands of dollars for a few compiler tools just so I
> can find problems with them elsewhere.
Well, you picked two compilers, one that is free, and another that
might as well be free (VC++) since it is fairly well tied up to microsoft
offerings.
I *imagine* Intels own compiler is better, but I'm not about to buy
the compiler, for the simple reason that I don't program in C.
In fact, I am not particularly impressed with the optimizability of
C in general. The idea of C was originally that it was supposed to be
a simple compiler that left most optimization up to the programmer
(for example, the i++ operator performs what most optimizing compilers
already did with i = i+1). We both agree that C is no longer a
low optimization language, but what that says is that people will put
optimization effort into whatever language is in demand, regardless of
the merits of the idea.
>
> As for beating up on "two low end compilers", hey, *these* are the
> compilers that *most* people use. These are the ones that programmers
> have been taught to believe generate great code by reading comments
> such as your's. They're the ones most deserving of being beaten up.
> People need to know that they cannot rely on comments like "compilers
> generate better machine code than human beings."
> Cheers,
> Randy Hyde
>
Compilers generate better code than *most* programmers all of the time,
and better code than expert programmers *most* of the time. Average
programmers don't know as much about optimizing the assembly code as
the compiler does, for the simple reason that average programmers
today don't know assembly, or have only a passing familarity with it.
Of course expert assembly programmers can beat a compiler on a section
of code. But that takes time and effort, and most experts reasonably
conclude that the compiler is better for most code, with only a few
sections hand optimized.
We have been around this before. The real problem here is that you
were an expert in assembly in the 1980s, when everyone still used
assembly. Now the train left, everyone uses high level languages, and
assembly language knowledge, unsuprisingly, is dwindling.
You and I actually have the same background, and agree on most things.
However, at the end of the 1980's I embraced high level languages,
and you became a critic of them.
The good 'ole days are gone, Randall, and all the pining that things
have got worse is not going to sway programmers who turn out applications
far larger than could ever have been produced with assembly languages.
|
|
0
|
|
|
|
Reply
|
Scott
|
4/18/2005 11:11:20 PM
|
|
Scott Moore wrote:
> >
>
> I would never imply that VC++ or GCC produce infailable machine code.
> In my opinion, based on looking at the output in assembly, and the
> results on benchmarks, that VC is not good at all, and GCC, while
better,
> is hardly ideal.
Well, as you are the compiler optimization "expert". Why don't you post
some code from a compiler that you feel does a better job? I, for one,
would like to see some additional data points.
>
> Well, you picked two compilers, one that is free, and another that
> might as well be free (VC++) since it is fairly well tied up to
microsoft
> offerings.
>
> I *imagine* Intels own compiler is better,
And this is *exactly* the point I'm making.
For a couple of decades, now, people have been suckered by the
statement "compiler optimizations are so good that they produce better
machine code than human assembly programmers."
Granted, it is *very* easy to find a few examples where compilers do a
spectactular job (and I'm talking about compilers like MSVC and GCC,
which you seem to think do a horrid job). But when you start looking at
large sets of compiler inputs and outputs, you begin to find that
examples where the compilers are absolutely brilliant tend to be
matched by examples where the compilers do some of the stupidest
things.
Whenever this fact is pointed out to the "let the compiler optimize for
you" proponents, the response is almost universally "well, you should
be using a better compiler." I've been hearing this line for over 15
years now. When pressed, though, the "proponent" will say something
like "I *imagine* Intels own compiler is better". IOW, their statements
are based on assumptions, heresay, or someone else's opinion rather
than personal experience.
Now I have no doubt that there is some compiler out there that will do
a *much* better job on this particular example that I'm griping about
right now. Indeed, I had *hoped* someone would post code I could use.
Or, at least, someone could point out a good reason why the code can't
be moved out of the loop (because I sure can't see a reason why).
> but I'm not about to buy
> the compiler, for the simple reason that I don't program in C.
So, then, why are you making comments about the quality of compilers
when you don't have the experience to back those statements up? Sure,
you're repeating stories you've heard elsewhere (OH! Microsoft is bad.
They write bad code. Their compilers *must* generate horrible code).
You're on shaky ground here.
> In fact, I am not particularly impressed with the optimizability of
> C in general.
We certainly agree that the C language is not particularly optimizable.
Pascal, for example, is much easier to optimize. OTOH, more research
has gone into optimizing C than any other language I'm aware of, and
other than FORTRAN it's leaps and bounds above everything else in terms
of the work that has gone into creating optimizing compilers. FORTRAN's
up there too, but a lot more work has gone into C (/C++) for obvious
reasons.
> The idea of C was originally that it was supposed to be
> a simple compiler that left most optimization up to the programmer
> (for example, the i++ operator performs what most optimizing
compilers
> already did with i = i+1).
Ritchie denies that this was the reason for the ++ operator (and other
so-called "optimized" operators such as "+="). He claims they were
stuck in the language for convenience. Maybe he was lying, I don't
know. But I tend to believe the language designer in these matters.
What would he have to gain by lying about it?
> We both agree that C is no longer a
> low optimization language, but what that says is that people will put
> optimization effort into whatever language is in demand, regardless
of
> the merits of the idea.
Exactly.
And given all the research that has gone into creating optimizing C
compilers, I would have expected this one example to have produced
better machine code via the application of these well-known techniques.
> Compilers generate better code than *most* programmers all of the
time,
Quite frankly, because *most* programmers aren't very good :-(.
> and better code than expert programmers *most* of the time.
Depends. Is the "expert" programmer *trying* to create good code, or
are they just hacking stuff out? Based on the code I've been looking at
lately, I would not say "most of the time." "Some of the time",
definitely, but not "most of the time."
The other issue, and this is the crucial point I want to make, is that
the quality of a compiler's output is *highly* dependent upon the input
you feed it. An expert C programmer, who understands how compilers
operate and optimize code, can write their C source code in a manner
that will produce *very good* machine code *most* of the time (the
strlen example at hand is a good example of a failure; in my case I
guess I knew a little too much about compiler optimization and I
expected the compiler to deal with that issue). Very carefully written
C code *can* produce code that is almost as good as hand-written
assembly language. Indeed, that's the premise of a book I'm currently
working on. However, it *takes* an expert programmer to help the
compiler produce code that is better than expert programmers most of
the time :-)
> Average
> programmers don't know as much about optimizing the assembly code as
> the compiler does,
Which is while I feel there is a market for a book that explains this
kind of stuff; so those average programmers can become expert
programmers.
> for the simple reason that average programmers
> today don't know assembly, or have only a passing familarity with it.
One doesn't really need to be an expert assembly programmer to do this.
The programmer certainly needs to know machine organization well and
they *do* need a "passing familiarity" with assembly language to be
able to understand what the compiler is doing with their code, but
learning things like "compilers don't handle code motion real well when
you put a strlen function call in a for loop..." are easy enough to
learn without needing to know anything about assembly language.
> Of course expert assembly programmers can beat a compiler on a
section
> of code. But that takes time and effort, and most experts reasonably
> conclude that the compiler is better for most code, with only a few
> sections hand optimized.
My experience is a bit different. I find that if I just write large
sections of assembly language code, the result is often faster and
shorter than the comparable optimized HLL code. This is without me even
thinking about writing the best possible code (certainly no cycle
counting or other draconian measures). Writing code in this manner
almost always yields sub-optimal assembly code and the compiler
certainly beats me for some small sequences. Overall, the hand-written
code wins, though.
I stopped counting cycles when the Pentiums first came out and it was
obvious that counting cycles was a complete waste of time because the
cycles counts for a given instruction were going to vary widely
depending on the processor executing the instructions. In theory, this
should have been a big advantage for compilers (after all, with a
compiler option you can recompile for a specific CPU). In reality,
though, developers don't produce a large number of different builds for
different CPUs, so compiler generated code suffers from the same
problem.
>
> We have been around this before. The real problem here is that you
> were an expert in assembly in the 1980s, when everyone still used
> assembly.
Actually, I still consider myself an expert today :-) Whether or not a
majority of people still use assembly is irrelevant. BTW, I also
consider myself an expert C programmer. I written just about as many
lines of C as I have assembly over the years, and about 1/3 to 1/2 that
number of lines of Pascal.
> Now the train left, everyone uses high level languages, and
> assembly language knowledge, unsuprisingly, is dwindling.
And your point is?
>
> You and I actually have the same background, and agree on most
things.
> However, at the end of the 1980's I embraced high level languages,
> and you became a critic of them.
Hmmmm...
I guess you don't know me very well. I use C/C++ all the time. The vast
majority of the programming I've done in the past decade has been in C
(and Flex and Bison :-)). In the decade before that, most of the work I
did was in Pascal. The difference between you and I is that I refuse
to become an apologist for HLLs. People still need to know assembly.
The code written by new programmers over the past decade is terrible.
Largely because they've been taught that performance doesn't matter and
there is no need to worry about optimizing their code. Why bother, when
the side-effects of Moore's law (actually, observeration) suggest that
CPUs will be twice as fast in two years anyway? Go back and read the
article that this thread is based upon. Here's the link:
<http://www.onlamp.com/pub/a/on�lamp/2004/05/06/writegreatcode�.html>
You'll notice that this article is *not* suggesting a return to
programming applications in assembly language. Rather, it is suggesting
that programmers should study assembly language in order to learn how
to write better HLL code. The conclusion sums it up best:
>>>>
To write great code requires one to write efficient code. Writing
efficient code requires good algorithm choices and a good
implementation of those algorithms. The best implementations are going
to be written by those who've mastered assembly language or fully
understand the low-level implementation of the high-level language
statements they're choosing. This doesn't mean that we'll return to the
days when major commercial applications were written entirely in
assembly language. However, to reverse the trend of software running
slower and slower even though CPUs are running faster and faster is
going to require programmers to begin considering the low-level
implications of the code that they write.
<<<<<
You've had the benefit of working on computers in the days when
everything was programmed in assembly. Therefore, *you* understand
what's going to happen when you place certain statements into a HLL
program (with respect to the code the compiler will generate). Most
newer programmers are ignorant of this process and, therefore, will
often choose really bad HLL statements to solve a given problem,
causing the compiler to generate really bad machine code. No matter how
great compiler technology becomes, optimizers aren't going to be able
to over come bad input. And that's why programmers should still learn
assembly language; so they have an idea of what the compiler is going
to do to their HLL code. That simple fact is what I've been pushing for
the better part of a decade now.
> The good 'ole days are gone, Randall, and all the pining that things
> have got worse is not going to sway programmers who turn out
applications
> far larger than could ever have been produced with assembly
languages.
Well, there is one issue. The crazy acceleration of CPU speeds in the
1990s has come to a grinding halt. No longer can programmers count on
(a misinterpretation of) Moore's Law to bail them out. In the past,
people have complained that although CPUs have gotten faster, software
has not gotten faster. Well, guess what? If programmers keep writing
code the way they have in the past decade, software is going to start
running *slower* because CPUs speed aren't increasing as rapidly as
they have in the past (indeed, I have an article coming out in EDN
magazine in a few months discussing this very phenomenon). While this
doesn't imply that people are going to have to start writing their
applications in assembly language, it does imply that people are going
to have to start watching how they write their code in the future. And
*knowing* assembly language is going to be one of the most important
pieces of knowledge programmers can possess when they need to start
worring about how to write great code, even in a HLL.
I guess I could say that "the good old days of getting away with
sloppiness are now coming to an end."
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/19/2005 1:09:26 AM
|
|
randyhyde@earthlink.net wrote:
> Scott Moore wrote:
> Show me a compiler that produces great code under *ALL* circumstances.
> Your defense is exactly the problem I'm talking about. When confronted
> with examples of bad code generation, the apologists in the crowd
> always come back with "well, you're just using the wrong compiler"
> without giving an example of a compiler that works under all
> circumstances.
I'd like to see the counterexample of a human assembly language
programmer that produces great code under *ALL* circumstances! I've
never met one yet.
> People need to know that they cannot rely on comments like "compilers
> generate better machine code than human beings."
Actually, I find that compilers *do* tend to generate better machine
code than human beings writing raw assembly language. While the loops
may not be optimal, and the reuse of registers *could* be done better
than most compilers, I find that most assembly language programmers
*don't* actually do any better, and further, most assembly language
programmers do a very poor job at error checking and error handling.
Rather than focusing in on a particular for loop that a particular
compiler doesn't handle well, it might be more useful to look at
programs more holistically and evaluate overall correctness,
functionality and usability as well as raw speed of individual components.
Assembly language has its place, but that place doesn't happen to be
every place.
Ed
|
|
0
|
|
|
|
Reply
|
Ed
|
4/19/2005 2:15:17 AM
|
|
Ed Beroset wrote:
> randyhyde@earthlink.net wrote:
>>
> > Show me a compiler that produces great code under *ALL*
circumstances.
> > Your defense is exactly the problem I'm talking about. When
confronted
> > with examples of bad code generation, the apologists in the crowd
> > always come back with "well, you're just using the wrong compiler"
> > without giving an example of a compiler that works under all
> > circumstances.
>
> I'd like to see the counterexample of a human assembly language
> programmer that produces great code under *ALL* circumstances! I've
> never met one yet.
But here's the deal: compilers are basically deterministic. Feed 'em
the same input and you're going to get the same output. Humans can
adjust, IF NEED BE.
>
> > People need to know that they cannot rely on comments like
"compilers
> > generate better machine code than human beings."
>
> Actually, I find that compilers *do* tend to generate better machine
> code than human beings writing raw assembly language.
Having spent a fair amount of time analyzing compiler output recently,
I would simply suggest that this statement is true *only* if you feed
the compiler *very* good source code to begin with. The compiler is not
going to make up for dubious programming techniques. Even when fed some
pretty good input, I've seen commonly-used compilers produce some
bone-headed code. As I've said in other posts: sometimes the code is
brilliant, sometimes it is stupid. On the average, it's probably better
than average, but a good assembly programmer can beat the code without
resorting to cycle counting and what-not.
The other disadvantage of a compiler is that it cannot make
optimization decisions on a statement by statement basis (at least, not
without a *lot* of work on the programmer's part and a great set of
pragmas). A compiler, for example, is not going to know that in a
certain section of the program it should optimize for space while in a
different section of the program it needs to optimize for speed. Most
optimization settings are global. And if you go in and tweak the system
(e.g., via pragmas), the code is just as difficult to write and
maintain, and is just as non-portable (to other compilers) as assembly
code.
> While the loops
> may not be optimal, and the reuse of registers *could* be done better
> than most compilers, I find that most assembly language programmers
> *don't* actually do any better,
Classic optimizations like register allocation, instruction scheduling,
et. al., are almost *always* done better by machine. Yes, compilers
will do a better job of this. This is not where an assembly language
programmer wins out over a compiler. As you point out below, it is the
holistic approach, that is "grokking the machine" that separates
assembly programmers and compilers.
> and further, most assembly language
> programmers do a very poor job at error checking and error handling.
And HLL programmers do a whole lot better? :-) Granted, some languages
(like Pascal) help out a lot here, but then, for people who are
interested in better error detection and recovery, consider using HLA.
This is a different matter altogether. It's more a function of the fact
that assembly programming is largely done today by hackers who have
little respect for reasonable software engineering concepts. Look at
all the people who try and claim that type checking doesn't belong in
assembly language, for example. OTOH, most of the people who fall into
this category don't quite make my list of programmers who produce
better code than compilers.
>
> Rather than focusing in on a particular for loop that a particular
> compiler doesn't handle well, it might be more useful to look at
> programs more holistically and evaluate overall correctness,
> functionality and usability as well as raw speed of individual
components.
Of course. And this is the place where assembly *wins big*. Counting
cycles is anachronistic and compilers do a much better job of that. But
HLL abstractions hide too much of the underlying machine and someone
who is not well-versed in assembly language (so they understand what
the compiler is doing with their HLL code) don't have a clue what HLL
statements are good and bad when writing their code.
Ed, you've programmed assembly for many years. You have the experience
to know how to write good HLL code based on that knowledge. Whether
it's concious or subconscious, your programming style takes into
consideration the operation of the compiler. This is not something most
newer programmers can do, as they've never learned (much less mastered)
assembly language. They write terrible code that the compiler
translates into equally terrible machine code. Yes, a great C
programmer, who knows how compilers work, and produce a source file
that a good compiler will translate into excellent machine code. That,
however, is not the typical case in most of the C code I've evaluated
on the internet.
>
> Assembly language has its place, but that place doesn't happen to be
> every place.
It's place is in the mind of every practicing programmer, so they know
what the hell their compilers are doing with the HLL code they write
:-).
Once in a while, it's even useful for writing applications.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/19/2005 3:22:54 AM
|
|
Since I am one of the old folks, I just have to jump in. I started in
Honeywell 201 EasyCoder in 1972. I also did Cobol for a long time after
that assignment (USAF). I also wrote any assembler and other low level
language (BPL for Burroughs) when it was needed to do what Cobol could not
accomplish. Then I wrote code in CI's C in the 80's for PC/XT clones.
Last year Michael Abrash wrote a multipart article about using assembly and
optimizing it for games/video code. He wrote a sequence that was slower
when an unneeded multiple was removed. Not even Intel could tell him why
without running some special hardware/software that could emulate the CPU
and find out it was a pipe stall situation. Intel's compiler is supposed to
be the best of any on the market, but most of us have to use Microsoft's.
I like assembly, but I always like it more the less I am tasked to write in
it. I have found that I prefer 'C' and assembler roughly in inverse
proportion to how much my current tasks require their use. The IBM PC/XT
with the 8088 had a simple optimization algorithm. The shorter the code -
the faster it was. There were so many wait states on the memory that it was
the primary factor controlling speed.
I don't think that assembly will ever return in the world of PCs. I can
always hope. I would get code output with Cobol listings so I could
optimize the assembler code by using better statement sequences. I had
limits on time and especially size when writing code for the Air Force.
They had rules that batch jobs could not exceed specific sizes. I think
most of these limits were based upon what was easy to measure. Luckily we
know today that virtual memory computers don't care unless bad design or
implementations cause too many pages to be accessed too frequently.
Good design and good coding style provides two bonuses - better
maintainability and faster, smaller code. I don't think you can do good
design unless you really understand the hardware including the instruction
set.
"randyhyde@earthlink.net" <spamtrap@crayne.org> wrote in message
news:1113879432.237910.260870@g14g2000cwa.googlegroups.com...
>
> Ed Beroset wrote:
>> randyhyde@earthlink.net wrote:
>>>
>> > Show me a compiler that produces great code under *ALL*
> circumstances.
>> > Your defense is exactly the problem I'm talking about. When
> confronted
>> > with examples of bad code generation, the apologists in the crowd
>> > always come back with "well, you're just using the wrong compiler"
>> > without giving an example of a compiler that works under all
>> > circumstances.
>>
>> I'd like to see the counterexample of a human assembly language
>> programmer that produces great code under *ALL* circumstances! I've
>> never met one yet.
>
> But here's the deal: compilers are basically deterministic. Feed 'em
> the same input and you're going to get the same output. Humans can
> adjust, IF NEED BE.
>
>>
>> > People need to know that they cannot rely on comments like
> "compilers
>> > generate better machine code than human beings."
>>
>> Actually, I find that compilers *do* tend to generate better machine
>> code than human beings writing raw assembly language.
>
> Having spent a fair amount of time analyzing compiler output recently,
> I would simply suggest that this statement is true *only* if you feed
> the compiler *very* good source code to begin with. The compiler is not
> going to make up for dubious programming techniques. Even when fed some
> pretty good input, I've seen commonly-used compilers produce some
> bone-headed code. As I've said in other posts: sometimes the code is
> brilliant, sometimes it is stupid. On the average, it's probably better
> than average, but a good assembly programmer can beat the code without
> resorting to cycle counting and what-not.
>
> The other disadvantage of a compiler is that it cannot make
> optimization decisions on a statement by statement basis (at least, not
> without a *lot* of work on the programmer's part and a great set of
> pragmas). A compiler, for example, is not going to know that in a
> certain section of the program it should optimize for space while in a
> different section of the program it needs to optimize for speed. Most
> optimization settings are global. And if you go in and tweak the system
> (e.g., via pragmas), the code is just as difficult to write and
> maintain, and is just as non-portable (to other compilers) as assembly
> code.
>
>
>> While the loops
>> may not be optimal, and the reuse of registers *could* be done better
>
>> than most compilers, I find that most assembly language programmers
>> *don't* actually do any better,
>
> Classic optimizations like register allocation, instruction scheduling,
> et. al., are almost *always* done better by machine. Yes, compilers
> will do a better job of this. This is not where an assembly language
> programmer wins out over a compiler. As you point out below, it is the
> holistic approach, that is "grokking the machine" that separates
> assembly programmers and compilers.
>
>> and further, most assembly language
>> programmers do a very poor job at error checking and error handling.
>
> And HLL programmers do a whole lot better? :-) Granted, some languages
> (like Pascal) help out a lot here, but then, for people who are
> interested in better error detection and recovery, consider using HLA.
>
> This is a different matter altogether. It's more a function of the fact
> that assembly programming is largely done today by hackers who have
> little respect for reasonable software engineering concepts. Look at
> all the people who try and claim that type checking doesn't belong in
> assembly language, for example. OTOH, most of the people who fall into
> this category don't quite make my list of programmers who produce
> better code than compilers.
>
>>
>> Rather than focusing in on a particular for loop that a particular
>> compiler doesn't handle well, it might be more useful to look at
>> programs more holistically and evaluate overall correctness,
>> functionality and usability as well as raw speed of individual
> components.
>
> Of course. And this is the place where assembly *wins big*. Counting
> cycles is anachronistic and compilers do a much better job of that. But
> HLL abstractions hide too much of the underlying machine and someone
> who is not well-versed in assembly language (so they understand what
> the compiler is doing with their HLL code) don't have a clue what HLL
> statements are good and bad when writing their code.
>
> Ed, you've programmed assembly for many years. You have the experience
> to know how to write good HLL code based on that knowledge. Whether
> it's concious or subconscious, your programming style takes into
> consideration the operation of the compiler. This is not something most
> newer programmers can do, as they've never learned (much less mastered)
> assembly language. They write terrible code that the compiler
> translates into equally terrible machine code. Yes, a great C
> programmer, who knows how compilers work, and produce a source file
> that a good compiler will translate into excellent machine code. That,
> however, is not the typical case in most of the C code I've evaluated
> on the internet.
>>
>> Assembly language has its place, but that place doesn't happen to be
>> every place.
>
> It's place is in the mind of every practicing programmer, so they know
> what the hell their compilers are doing with the HLL code they write
> :-).
> Once in a while, it's even useful for writing applications.
> Cheers,
> Randy Hyde
>
|
|
0
|
|
|
|
Reply
|
David
|
4/19/2005 6:22:01 AM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> The statement you quote above discusses the C *source*
> language, not the code that the compiler generates.
Uhm ... I thought a standard was supposed to describe
with the machine did as a result of source statements.
> And another thing you might consider is that compiler
> optimization was in its infancy when K&R was written,
As others have posted, many optimizations were already being
routinely done. Cycles were too precious. As a student, many of my
jobs took ~10x longer to compile than to run. When I got to work,
I very rarely compiled anything, but had jobs that ran for hours.
> and they probably weren't even thinking about it at the time,
> or they might have been a bit more precise in their book
> describing the C language. Finally, note that K&R is *not*
> C as we know it today. The ANSI spec is a *lot* clearer on
> the semantics of optimizations that can be performed.
Then why does the ISO/IEC 9899:1999 standard (C99) still have:
[for] "behaves as follows: The expression expression-2 is
the controlling expression that is evaluated before each
execution of the loop body." [6.8.5.3] ?
What section specifically permits eliminating exp2 evaluation?
I didn't see anything under "Optimization".
> And what happens in the canonical infinite loop in C? > > for(;;)
Nicely covered in C99 at 6.8.5.3
> The compiler may not be compliant at all. MSVC, for example,
> is famous for skirting the rules.
This was my point. And particularly as it relates to ASM.
`c` seems to devolved away from being "a portable asm".
> Well, then you have a strange definition of preciseness.
No, precision is knowing something sharply.
Accuracy is knowing it "truthfully":
http://people.hofstra.edu/geotrans/eng/ch6en/meth6en/accuracyprec.html
I take precision also applying to knowing what you don't know
with precise and sharp boundaries. The first thing to learn
is what you don't know.
> Me thinks you've moved *way* to far to the defensive side
> here, unwilling to admit that you overstated things a bit.
??? what am I defending? I'm no compiler writer, nor do I even
have aspirations to use the accursed things. I merely naively
mention that if I see something in a standard, and somebody
claims to follow it, then I expect it is actually followed.
Especially in something as allegedly precise as `c`.
Or perhaps you argue for "an optimizing assembler"?
Even with fancy x86 hardware schedulers, I don't think
they actually drop unneeded instructions.
> Not vanishingly so. "for(i=0;i<strlen(s);++i)}" is a bit
> easier to read and comprehend than
> k=strlen( s );
> for( i=0; i<k; ++i )
A matter of opinion. Personally I prefer the second.
> There's less cruft to deal with in the former example and
> it requires less mental processing.
Perhaps because I'm not a long-experience `c` programmer,
but I find the complex semantics of the `for()` construct
relatively complex to parse. Somewhat like the `?` operator.
k=... has clarative value more than the indirection costs.
> There is also the case of someone having to read the
> declaration for the k variable and figure out what it's
Yes, and `k` is a bad var name. Even `limit` would be better
>> One of the problems with `c` is that people like to overload
>> lines so that it begins to look like APL. I'm guilty too,
>> but I know it's because of semicolonophobia.
> Not sure I follow what you mean.
What I mean is that people tend to write long lines in `c`
rather than more, shorter lines. Do as much as possible
in one statement, rather than one single thing.
> My complaint about this for loop example is that this is
> an optimization one should *expect* a compiler to do (and
My point is that one shouldn't expect a compiler to perform
_any_ optimization that the programmer could by writing
better code. Especially not for `c` which claimed to be
"a portable assembler".
> The point being is that a good C programmer will find it
> difficult to find a common set of optimizations they can
> count on, so they can move their C source files from compiler
> to compiler without worrying about degenerate behavior.
Exactly. So the source has to be idiot-compiler proof.
> this for loop example is rather trivial. It's easy enough,
> however, to create slightly more complex examples where the
> readability takes a big hit because you've got to move a loop
> invariant calculation of out a (deeply nested, for example) loop.
I don't see that as a readability hit, especially if the
constants are well-named. It becomes a small subsection of
the code:
/* calculate geometry and color adjustment factors */
/* apply geom & col factors to copy of framebuffer */
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/19/2005 2:22:43 PM
|
|
Robert Redelmeier wrote:
> randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> > The statement you quote above discusses the C *source*
> > language, not the code that the compiler generates.
>
> Uhm ... I thought a standard was supposed to describe
> with the machine did as a result of source statements.
It describes the *semantics* desired, not the code to be generated. As
long as the generated code produces the specified semantics, exactly
*what* code the compiler generates is up to the implementor.
>
> > And another thing you might consider is that compiler
> > optimization was in its infancy when K&R was written,
>
> As others have posted, many optimizations were already being
> routinely done. Cycles were too precious. As a student, many of my
> jobs took ~10x longer to compile than to run. When I got to work,
> I very rarely compiled anything, but had jobs that ran for hours.
What does that have to do with semantics vs. code generation?
As for why the early C compilers didn't optimize too well, consider the
limited machine resources available at the time. Yes, optimizations
were routinely done on big iron running FORTRAN H or PL/I, at that
time. It was not the case for the original C compiler (which is what we
are discussing here).
>
> > and they probably weren't even thinking about it at the time,
> > or they might have been a bit more precise in their book
> > describing the C language. Finally, note that K&R is *not*
> > C as we know it today. The ANSI spec is a *lot* clearer on
> > the semantics of optimizations that can be performed.
>
> Then why does the ISO/IEC 9899:1999 standard (C99) still have:
> [for] "behaves as follows: The expression expression-2 is
> the controlling expression that is evaluated before each
> execution of the loop body." [6.8.5.3] ?
Strong emphasis on the word "behaves".
You do understand what the term "semantics" means, right?
>
> What section specifically permits eliminating exp2 evaluation?
> I didn't see anything under "Optimization".
Uh, the specifications don't have to explicitly *allow* something.
Generally, it's the case that they would *disallow* something if it
were important to do so. Does the specification explicitly allow dead
code elimination, for example?
>
> > And what happens in the canonical infinite loop in C? > > for(;;)
>
> Nicely covered in C99 at 6.8.5.3
>
> > The compiler may not be compliant at all. MSVC, for example,
> > is famous for skirting the rules.
>
> This was my point. And particularly as it relates to ASM.
> `c` seems to devolved away from being "a portable asm".
C never was a portable assembler. The fact that C introduced some bit
manipulation operations that were rare in HLLs of its time gave people
the impression that it was a "bit-banging language" and, therefore, an
assembly language. It is not. It is a high-level language. Granted,
lower-level than, say, Pascal. But still high-level. The "C is a
portable assembly" is a myth, perpetuated by those who are looking for
another reason to marginalize assembly.
Today, of course, even C is being marginalized. The big push today
isn't "assembly vs. HLLs," but "C vs. interpreted scripting languages."
I find that progression quite natural, in the historical context of
cheap computing. Alas, the lack of ever increasing CPU speeds is going
to bring this progression to an end.
>
> > Well, then you have a strange definition of preciseness.
>
> No, precision is knowing something sharply.
> Accuracy is knowing it "truthfully":
>
http://people.hofstra.edu/geotrans/eng/ch6en/meth6en/accuracyprec.html
Who said anything about truthfulness? Your definition of precisioness,
IMO, lacks depth (i.e., "precision"). Accuracy has nothing to do with
it.
>
> ??? what am I defending? I'm no compiler writer, nor do I even
> have aspirations to use the accursed things. I merely naively
> mention that if I see something in a standard, and somebody
> claims to follow it, then I expect it is actually followed.
When you make claims that the standards don't allow implementors to
achieve better results by eliminating redundant calculations, you are
reading *far* too much from those standards.
>
> Especially in something as allegedly precise as `c`.
C is not a precise language. Even the latest standards have several
areas where things are undefined. If the language definition were truly
precise (and such language definitions exist for other languages), no
such holes would exist.
> Or perhaps you argue for "an optimizing assembler"?
Certainly I do. But that is a different topic.
> Even with fancy x86 hardware schedulers, I don't think
> they actually drop unneeded instructions.
???
>
> > Not vanishingly so. "for(i=0;i<strlen(s);++i)}" is a bit
> > easier to read and comprehend than
>
> > k=strlen( s );
> > for( i=0; i<k; ++i )
>
> A matter of opinion. Personally I prefer the second.
A matter of research. Software engineering, of course, is empirically
based and, as such, *imprecise*. But the majority of people in tests
found the former version easier to read. And it wasn't a question of
asking them what they preferred. Instead, the researchers measured
things like time and comprehension on several programs across several
programmers and based their findings on their measurements. No doubt,
people would say something like "I prefer the second form" and then
turn in better results for the first form. The important thing to
realize, of course, is that "majority" does not equal "all". Some
people really do better with the second version. But if you want to
write code that is more easily read by the majority of the people out
there, you like to keeo your calculations as *close* to their usage as
possible. Old-time assembly programmers may prefer the version above,
because they recognize the inherent costs of calculation strlen on each
loop iteration (even if the compiler *should* be moving that
calculation outside the loop). But old-time assembly programmers, or
even programmers who would recognize (and be bothered by) this
inefficiency are not particularly common today.
>
> > There's less cruft to deal with in the former example and
> > it requires less mental processing.
>
> Perhaps because I'm not a long-experience `c` programmer,
The concept transcends languages.
> but I find the complex semantics of the `for()` construct
> relatively complex to parse.
I agree. The for loop was one of the big mistakes in original design of
the C programming language. A definite loop, such as those in Pascal
and FORTRAN, would have been much better.
> Somewhat like the `?` operator.
C's terseness, and the readability problems with it, are legendary. Of
course, you can "fix" this problem using something like:
#define ifx(x,t,f) ((x)?(t):(f))
And then write code like "ifx(a==b, 0, 1)" which should be a familiar
concept to anyone who has ever used a spreadsheet. Of course, expect
all the "C is a pure language and cannot be touched" types to holler
about how bad it is that someone would even suggest that a language
construct in C should be modified :-)
> k=... has clarative value more than the indirection costs.
Again, research and common sense indicates otherwise. If
"k=strlen(s);" is okay, then why not "m=strlen(s);" followed by "k=m;"
and then "n=strlen(s);" followed by "m=n;" and "k=m;" and so on. Using
your "take the limit as..." analogy, it's quite clear that there is a
cost associated with each level of indirection added here and the
*lowest* cost (i.e., easiest to read) occurs when you simply use
strlen.
>
>
> > There is also the case of someone having to read the
> > declaration for the k variable and figure out what it's
>
> Yes, and `k` is a bad var name. Even `limit` would be better
You completely missed the point. Using the best name in the world
(which would actually be "strlen" in this case) doesn't change the fact
that someone has got to read over the definition and mentally process
it. That takes time that could be put to better use figuring out
something else in the program.
>
> >> One of the problems with `c` is that people like to overload
> >> lines so that it begins to look like APL. I'm guilty too,
> >> but I know it's because of semicolonophobia.
>
> > Not sure I follow what you mean.
>
> What I mean is that people tend to write long lines in `c`
> rather than more, shorter lines. Do as much as possible
> in one statement, rather than one single thing.
I've looked at a lot of C code on the internet. Other than "printf"
and, perhaps, some boolean expression in "if" and other statements, I
don't really find this to be the case. Sure, you can find *some*
outrageously complex statements in any given C program of sufficient
size, but I don't find this to be the case in most programs.
Of course, this is another reason people should learn assembly
language. When they learn to think in terms of the semantically simple
instructions that the CPU can execute, they tend to write HLL programs
with simplified expressions and constructs. Just a thought.
>
> > My complaint about this for loop example is that this is
> > an optimization one should *expect* a compiler to do (and
>
> My point is that one shouldn't expect a compiler to perform
> _any_ optimization that the programmer could by writing
> better code.
Your point is well taken. Programmers *should* take the personal
responsibility for optimizing their own code. But for the past decade
and a half, they've been taught that they don't have to do this. People
*expect* the compilers to do the optimization for them. Unfortunately,
compilers have a limited capacity to optimze code and often fall flat
on their faces (the current for loop example is a good one).
We can probably divide source code constructs into three generic
groups:
1. Concepts that no compiler/optimizer is going to correct and the
programmer must take the initiative in writing good code. This would
include proper algorithm selection (e.g., no compiler is going to
substitute a quick sort for a bubble sort), appropriate choice of
application architecture, and so on.
2. Things that compilers/optimizers *ought* to do, but you can't count
on. This would include things like in-line expansion of functions like
strlen, compile-time calculation of function results (run GCC with
"/O3" some time and check out the results), automatic optimization
based on type inferences, global (and cross-module) optimizations, and
so on.
3. Things that every compiler/optimizer *should* do. These would be
traditional optimizations like moving loop invariant calculations,
induction variables, dead code elimination, live/dead value analysis,
and so on.
My current complaint is that moving the strlen code out of that for
loop is an optimization that should be in class (3), something a smart
programmer should be able to count on being done. Looks like it really
belongs in class (2) given the examples I seen to date.
> Especially not for `c` which claimed to be
> "a portable assembler".
Especially for C, as more research has gone into optimizing the output
of C/C++ compilers than any other language. If we can't expect to get
good code out of a C compiler (after all this research), it's pretty
hard to expect to get great code out of other compilers. True, some
language (e.g., FORTRAN) are inherently easier to optimize than C (C is
one of the worst languages for this), but a *lot* of work has gone into
creating optimizing C compilers. And in the real world, when people
talk about how compilers take care of optimization for you, they're
generally talking about programs written in C. So, yes, it *is*
reasonable to expect a C compiler to produce good code if you're going
to tout the party line that "optimizers generate code that is as good
as a human assembly programmer."
>
> > The point being is that a good C programmer will find it
> > difficult to find a common set of optimizations they can
> > count on, so they can move their C source files from compiler
> > to compiler without worrying about degenerate behavior.
>
> Exactly. So the source has to be idiot-compiler proof.
Which brings us back to "The Great Debate". Once you have to take chare
of manually optimizing your code, because the "idiot compilers" out
there can't do the job for you, you've lost a good number of the
benefits of using a HLL in the first place. Optimization is hard. It is
time consuming. And it is often not portable. The fact that the source
language is C rather than assembly doesn't change this fact.
>
> > this for loop example is rather trivial. It's easy enough,
> > however, to create slightly more complex examples where the
> > readability takes a big hit because you've got to move a loop
> > invariant calculation of out a (deeply nested, for example) loop.
>
> I don't see that as a readability hit, especially if the
> constants are well-named. It becomes a small subsection of
> the code:
> /* calculate geometry and color adjustment factors */
> /* apply geom & col factors to copy of framebuffer */
Until that process is repeated throughout your code. Which is what is
going to happen when you go in and manually optimize it.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/19/2005 5:20:49 PM
|
|
Robert Redelmeier wrote:
> randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
>
>>and they probably weren't even thinking about it at the time,
>>or they might have been a bit more precise in their book
>>describing the C language. Finally, note that K&R is *not*
>>C as we know it today. The ANSI spec is a *lot* clearer on
>>the semantics of optimizations that can be performed.
>
> Then why does the ISO/IEC 9899:1999 standard (C99) still have:
> [for] "behaves as follows: The expression expression-2 is
> the controlling expression that is evaluated before each
> execution of the loop body." [6.8.5.3] ?
>
> What section specifically permits eliminating exp2 evaluation?
> I didn't see anything under "Optimization".
Look at section 4 and section 5.1.2.3. Conformance is defined in
terms of the input and output of the program, not in terms of
code generated by the compiler.
--
Thomas M. Sommers -- tms@nj.net -- AB2SB
|
|
0
|
|
|
|
Reply
|
T
|
4/19/2005 5:22:02 PM
|
|
In article <1113925963.844105.67500@f14g2000cwb.googlegroups.com>
spamtrap@crayne.org "randyhyde@earthlink.net" writes:
[These articles are getting longer and longer, so apologies in
advance for gratuitous snipping...]
> Robert Redelmeier wrote:
[..]
> > Or perhaps you argue for "an optimizing assembler"?
>
> Certainly I do. But that is a different topic.
Heaven help us! The one and only reason that I like writing in
assembler is that the assembler should generate _exactly_ what I
tell it to -- good or bad. And whilst I have no doubt that a
really smart assembler might rewrite my code better (for some
definition thereof) _I_ want the final say...
[..]
> > > Not vanishingly so. "for(i=0;i<strlen(s);++i)}" is a bit
> > > easier to read and comprehend than
> >
> > > k=strlen( s );
> > > for( i=0; i<k; ++i )
> >
> > A matter of opinion. Personally I prefer the second.
Personally, I would write:
for (k = strlen (s), i = 0; i < k; ++i)
{
...
which my (perhaps twisted) brain finds perfectly readable and
describes exactly what I'd like the compiler to do. Or use a
different loop construct altogether, like:
while (*s)
{
...
++s;
}
[..]
> > > My complaint about this for loop example is that this is
> > > an optimization one should *expect* a compiler to do (and
> >
> > My point is that one shouldn't expect a compiler to perform
> > _any_ optimization that the programmer could by writing
> > better code.
>
> Your point is well taken. Programmers *should* take the personal
> responsibility for optimizing their own code. But for the past decade
> and a half, they've been taught that they don't have to do this.
Perhaps then this is the root cause of the problem: get better
teachers (present company excepted of course!). Students should
be taught and encouraged to write "good" code and not to rely on
their compiler/assembler to make good their shortcomings.
> People
Students? As a RL programmer I expect no such thing.
> *expect* the compilers to do the optimization for them. Unfortunately,
> compilers have a limited capacity to optimze code and often fall flat
> on their faces (the current for loop example is a good one).
Perhaps their expectations are too high?
[..]
> > > The point being is that a good C programmer will find it
> > > difficult to find a common set of optimizations they can
> > > count on, so they can move their C source files from compiler
> > > to compiler without worrying about degenerate behavior.
> >
> > Exactly. So the source has to be idiot-compiler proof.
>
> Which brings us back to "The Great Debate". Once you have to take chare
> of manually optimizing your code, because the "idiot compilers" out
> there can't do the job for you, you've lost a good number of the
> benefits of using a HLL in the first place. Optimization is hard. It is
> time consuming. And it is often not portable. The fact that the source
> language is C rather than assembly doesn't change this fact.
A HLL is no excuse for creating sloppy code -- IMHO of course.
The benefits of using a HLL are twofold: (a) readable, and by
consequence readily maintainable, code and (b) a reduction in
development time (compared to scratch-writing all asm, for
example). If the HLL syntax/semantics can describe precisely
what you want to achieve, fine; if not, you have to go to a lower
level to spell it out. One has to learn -- or be taught -- to
select the right tool for the job at hand; querying a database
and writing a device driver require different tools. In either
case one can write efficient or inefficient code, but one should
never have to rely on the tool to transform sloppiness into
adequacy.
Just my 2p
Pete
--
"We have not inherited the earth from our ancestors,
we have borrowed it from our descendants."
|
|
0
|
|
|
|
Reply
|
spamtrap
|
4/19/2005 8:29:42 PM
|
|
T.M. Sommers <tms@nj.net> wrote:
>> What section specifically permits eliminating exp2 evaluation?
>> I didn't see anything under "Optimization".
>
> Look at section 4 and section 5.1.2.3. Conformance is
> defined in terms of the input and output of the program,
> not in terms of code generated by the compiler.
Yes, section 4.3 says a program is conforming if it works.
Nothing about the compiler (conforming implementation 4.6).
And [5.1.2.3]:
"In the abstract machine, all expressions are evaluated as
specified by the semantics. An actual implementation need not
evaluate part of an expression if it can deduce that its value is
not used and that no needed side effects are produced (including
any caused by calling a function or accessing a volatile object)."
Which basically says "it's OK to eliminate expressions so long
as it works". The onus is entirely on the compiler to
judge what are "needed side effects".
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/19/2005 9:27:33 PM
|
|
randyhyde@earthlink.net <spamtrap@crayne.org> wrote:
> Does the specification explicitly allow dead
> code elimination, for example?
Yes, 5.1.2.3.3 -- but there is a risk in dead code elimination
of changing cache alignment and producing undesireable side effects.
> C never was a portable assembler.
Dennis Ritchie apparently thought of it as such.
> assembly language. It is not. It is a high-level language. Granted,
The scale of high vs low level is subject to context.
> If "k=strlen(s);" is okay, then why not "m=strlen(s);" followed
> by "k=m;" and then "n=strlen(s);" followed by "m=n;" and
> "k=m;" and so on. Using your "take the limit as..." analogy,
> it's quite clear that there is a cost associated with each
> level of indirection added here and the *lowest* cost (i.e.,
> easiest to read) occurs when you simply use strlen.
Certainly the lowest indirection cost. But an increased cost
in parsing the complex "for()". Additional indirect of your
'reductio ad absurdam' m&n doesn't help parsing the for(),
and just adds cost.
> You completely missed the point. Using the best name in the world
> (which would actually be "strlen" in this case) doesn't change
> the fact that someone has got to read over the definition and
> mentally process it. That takes time that could be put to better
> use figuring out something else in the program.
Use very short-term [human] memory. The for() has to be
parsed using it anyways. But placing k=strlen() anyplace
but immediately before the loop would incur a huge cost.
> I've looked at a lot of C code on the internet. Other
> than "printf" and, perhaps, some boolean expression in
> "if" and other statements, I don't really find this to be
> the case. Sure, you can find *some* outrageously complex
> statements in any given C program of sufficient size,
> but I don't find this to be the case in most programs.
I am subjected to `c` in the Linux kernel. Formulae I can
take -- they have to be long. When I'm lucky, the lines just
are long. When not, the indirection becomes circular :)
> Of course, this is another reason people should learn
> assembly language. When they learn to think in terms of the
> semantically simple instructions that the CPU can execute,
> they tend to write HLL programs with simplified expressions
> and constructs. Just a thought.
Oh, I fully agree.
> Your point is well taken. Programmers *should* take the
> personal responsibility for optimizing their own code. But
> for the past decade and a half, they've been taught that
> they don't have to do this. People *expect* the compilers
> to do the optimization for them. Unfortunately, compilers
We cannot be responsible for unreasonable expectations,
unless we work to fulfill them!
> So, yes, it *is* reasonable to expect a C compiler to
> produce good code if you're going to tout the party line
> that "optimizers generate code that is as good as a human
> assembly programmer."
But I don't tout that party line.
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
4/19/2005 10:05:18 PM
|
|
randyhyde@earthlink.net wrote:
> Ed Beroset wrote:
>
>>randyhyde@earthlink.net wrote:
>>
>>>Show me a compiler that produces great code under *ALL*
>
> circumstances.
>
>>
>>I'd like to see the counterexample of a human assembly language
>>programmer that produces great code under *ALL* circumstances! I've
>>never met one yet.
>
> But here's the deal: compilers are basically deterministic. Feed 'em
> the same input and you're going to get the same output. Humans can
> adjust, IF NEED BE.
True. Compilers are not only generally produce better code, but they do
so more consistently, as well!
>>>People need to know that they cannot rely on comments like
>
> "compilers
>
>>>generate better machine code than human beings."
>>
>>Actually, I find that compilers *do* tend to generate better machine
>>code than human beings writing raw assembly language.
>
> Having spent a fair amount of time analyzing compiler output recently,
> I would simply suggest that this statement is true *only* if you feed
> the compiler *very* good source code to begin with.
I think it has more to do with what you define as "good." If your
criteria for "good" are solely related to, say, code size or code speed,
it might skew things toward hand-crafted assembly code (and not
coincidentally, those are exactly the sorts of situations for which
assembly is still very relevant), but if your criteria include things
like "low bug density" or "superior error handling" or "inexpensive
maintenance" then things are decidedly shifted toward the HLL end of the
spectrum.
> The compiler is not
> going to make up for dubious programming techniques.
Nor is the assembler! Bad programmers produce bad code.
> Even when fed some
> pretty good input, I've seen commonly-used compilers produce some
> bone-headed code.
The question is really, "is it good enough?" Donald Knuth has famously
said that "premature optimization is the root of all evil." For
example, if you have lightning-fast keyboard handling code, who really
cares? A 4-GHz x86 processor is so astonishingly fast compared to human
typing speed, that it just doesn't really matter.
> As I've said in other posts: sometimes the code is
> brilliant, sometimes it is stupid. On the average, it's probably better
> than average, but a good assembly programmer can beat the code without
> resorting to cycle counting and what-not.
Could beat, perhaps, but this advantage is theoretical. In real life,
this potential of assembly language code "beating" the compiler is
rarely realized simply because it's too time-consuming to do so. There
are exceptions, of course -- frequently used and time-sensitive routines
are good candidates for writing in assembly language. Cryptographic
code is an example from my own work. Even there, however, (in embedded
systems) I find that it simply doesn't make economic or engineering
sense to write much in assembly language these days.
>>Assembly language has its place, but that place doesn't happen to be
>>every place.
>
>
> It's place is in the mind of every practicing programmer, so they know
> what the hell their compilers are doing with the HLL code they write
> :-).
> Once in a while, it's even useful for writing applications.
We agree on that! It's useful to know, but not very useful to actually
use -- sort of like learning how to take square roots on paper.
Ed
|
|
0
|
|
|
|
Reply
|
Ed
|
4/20/2005 12:44:39 AM
|
|
spamt...@crayne.org wrote:
> In article <1113925963.844105.67500@f14g2000cwb.googlegroups.com>
> spamtrap@crayne.org "randyhyde@earthlink.net" writes:
> [..]
> > > Or perhaps you argue for "an optimizing assembler"?
> >
> > Certainly I do. But that is a different topic.
>
> Heaven help us! The one and only reason that I like writing in
> assembler is that the assembler should generate _exactly_ what I
> tell it to -- good or bad. And whilst I have no doubt that a
> really smart assembler might rewrite my code better (for some
> definition thereof) _I_ want the final say...
Clearly, any assembler that did optimizations would have to offer you
line by line control over whether the optimizations would take place.
Some optimizations, like instruction scheduling, could be done *much*
better by the compiler/assembler behind your back (do you really want
to rewrite your code for the umpteen different rules that apply to the
umpteen different processors out there?). Likewise, optimizations like
aligning target labels (especially loops) on decent boundaries by
substituting "larger" instructions upstream is something that is better
done by machine.
Things like dead code elimination, constant propagation, live/dead
variable analysis, and so on, *could* be done. I'd bet they'd be more
acceptable as suggestions for the programmer to manually add, though.
Register allocation would be a tough nut to crack. Most programmers
don't want the assembler messing with their choice of registers, even
if the assembler could produce better code by studying what's going on.
Just my observations, having seen this discussion go through many
phases over the past decade or so.
> >
> > Your point is well taken. Programmers *should* take the personal
> > responsibility for optimizing their own code. But for the past
decade
> > and a half, they've been taught that they don't have to do this.
>
> Perhaps then this is the root cause of the problem: get better
> teachers (present company excepted of course!).
"Teachers" doesn't necessarily imply instructors in this context. The
"teachers" pushing this philosophy are usually peers, magazine
articles, books, etc. While the university establishment is just as
guilty of perpetuating this trend, they certainly are the only one.
Just witness this thread, for example...
> Students should
> be taught and encouraged to write "good" code and not to rely on
> their compiler/assembler to make good their shortcomings.
Students, perhaps.
But advanced programmers should be able to take advantage of compiler
facilities to write more readable code when they know that the compiler
will rearrange things in an efficient manner. The problem, of course,
is that you can't count on such techniques being (optimizably) portable
across compilers.
>
> > People
>
> Students? As a RL programmer I expect no such thing.
>
> > *expect* the compilers to do the optimization for them.
Unfortunately,
> > compilers have a limited capacity to optimze code and often fall
flat
> > on their faces (the current for loop example is a good one).
>
> Perhaps their expectations are too high?
After a couple of decades of being told "compilers generate machine
code that is every bit as good as a human assembly language
programmer," what would you expect?
> >
> > Which brings us back to "The Great Debate". Once you have to take
chare
> > of manually optimizing your code, because the "idiot compilers" out
> > there can't do the job for you, you've lost a good number of the
> > benefits of using a HLL in the first place. Optimization is hard.
It is
> > time consuming. And it is often not portable. The fact that the
source
> > language is C rather than assembly doesn't change this fact.
>
> A HLL is no excuse for creating sloppy code -- IMHO of course.
Of course it isn't. Yet people (students and otherwise) have come to
believe that compiler technology will take care of them and they don't
have to worry about writing great code. And yes, I believe that in the
absence of explicitly producing great code, you wind up with sloppy
code. You don't get great code by accident, you have to work at it.
Failure to do so results in the production of low-quality code.
> The benefits of using a HLL are twofold: (a) readable, and by
> consequence readily maintainable, code and (b) a reduction in
> development time (compared to scratch-writing all asm, for
> example).
Yes and no. If you hand optimize HLL code, it's going to take longer to
write and be less readable. This is especially true if the compiler
you're using doesn't have a great optimizer and you have to go to great
lengths to convince the compiler to produce great code. The current for
loop in this thread is a trivial example of the problem.
Ideally, an advanced programmer should be able to *count* on certain
types of optimizations so they can design and implement their
applications in a readable and maintainable fashion and not have to
worry about the low level efficiency of the code the compiler produces.
Compilers are just not there yet. Of course, the big argument today is
not that compilers won't produce great code, but that "processors are
so fast nobody cares anymore." Alas, the lag in increasing processor
speeds is going to hurt those who continue to believe that.
> If the HLL syntax/semantics can describe precisely
> what you want to achieve, fine; if not, you have to go to a lower
> level to spell it out. One has to learn -- or be taught -- to
> select the right tool for the job at hand; querying a database
> and writing a device driver require different tools. In either
> case one can write efficient or inefficient code, but one should
> never have to rely on the tool to transform sloppiness into
> adequacy.
>
> Just my 2p
And a good 2p it is, too :-)
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/20/2005 1:19:56 AM
|
|
Ed Beroset wrote:
> randyhyde@earthlink.net wrote:
>
> > The compiler is not
> > going to make up for dubious programming techniques.
>
> Nor is the assembler! Bad programmers produce bad code.
The difference, however, is that the bad machine code is generally more
obvious in the assembly language program. In the HLL code, the HLL
abstractions hide what's going on.
>
> > Even when fed some
> > pretty good input, I've seen commonly-used compilers produce some
> > bone-headed code.
>
> The question is really, "is it good enough?"
> Donald Knuth has famously
> said that "premature optimization is the root of all evil."
Actually, the quote is due to CAR Hoare. Knuth just quoted him.
You might want to read:
http://c2.com/cgi/wiki?PrematureOptimization
I've got a pretty good quote on this subject coming out in an EDN
article in a couple of months. The author (rightly) points out that
what people considered "optimization" when Tony Hoare wrote this paper
is quite a bit different than what we consider "optimization" today.
See
http://www.cookcomputing.com/blog/archives/000084.html
for details.
> For
> example, if you have lightning-fast keyboard handling code, who
really
> cares? A 4-GHz x86 processor is so astonishingly fast compared to
human
> typing speed, that it just doesn't really matter.
This is a straw man argument. Obviously, interpreted PERL is just fine
for many applications. Yes, the speed of today's CPUs lets people get
away with a lot of slop that they couldn't 15 years ago.
But as programs get larger, they get *uniformly* slower. Waiting for
keystrokes is irrelevant. Waiting for some search function that
recomputes a key's length after each character is bad.
>
> > As I've said in other posts: sometimes the code is
> > brilliant, sometimes it is stupid. On the average, it's probably
better
> > than average, but a good assembly programmer can beat the code
without
> > resorting to cycle counting and what-not.
>
> Could beat, perhaps, but this advantage is theoretical. In real
life,
> this potential of assembly language code "beating" the compiler is
> rarely realized simply because it's too time-consuming to do so.
IOW, programmers are too lazy to write the code efficiently. Therein
lies the fundamental problem. And it has nothing to do with assembly
vs. HLLs. Optimizing in a HLL is a lot of work, it's difficult, and
it's time consuming. The result is not as maintainable. So people fall
back to the old "optimizers take care of this for me" or "CPUs are fast
enough already, who cares?" The problem with this attitude is that it
invariably leads to people writing slower and slower code, especially
as systems get larger and larger. The past 15 years of software
engineering have shown this.
> There
> are exceptions, of course -- frequently used and time-sensitive
routines
> are good candidates for writing in assembly language. Cryptographic
> code is an example from my own work. Even there, however, (in
embedded
> systems) I find that it simply doesn't make economic or engineering
> sense to write much in assembly language these days.
I think you're really missing something here. This is *not* a thread
about "we should write everything in assembly language." This is a
thread about "compiler optimizers aren't living up to their promise."
Programmer's have to take the responsibility for optimizing their code
because the compiler's just aren't doing the job for them. Sometimes,
that optimization may require dipping into assembly language.
Hopefully, they can stick in their HLL for most work. But the bottom
line is that it's the *optimization*, not the choice of language, that
has the biggest impact on the effort required and the
readability/maintainability of the result.
> > It's place is in the mind of every practicing programmer, so they
know
> > what the hell their compilers are doing with the HLL code they
write
> > :-).
> > Once in a while, it's even useful for writing applications.
>
> We agree on that! It's useful to know, but not very useful to
actually
> use -- sort of like learning how to take square roots on paper.
>
Amen.
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/20/2005 4:24:03 AM
|
|
randyhyde@earthlink.net wrote:
> Ed Beroset wrote:
>
>>randyhyde@earthlink.net wrote:
>
>
>>>The compiler is not
>>>going to make up for dubious programming techniques.
>>
>>Nor is the assembler! Bad programmers produce bad code.
>
>
> The difference, however, is that the bad machine code is generally more
> obvious in the assembly language program. In the HLL code, the HLL
> abstractions hide what's going on.
That's incorrect. Because HLL code is more readable generally, mistakes
are easier to find, too, whether they are design errors or coding errors.
>>Donald Knuth has famously
>>said that "premature optimization is the root of all evil."
>
> Actually, the quote is due to CAR Hoare. Knuth just quoted him.
Right you are. In any case, the sentiment remains.
>>For
>>example, if you have lightning-fast keyboard handling code, who
>
> really
>
>>cares? A 4-GHz x86 processor is so astonishingly fast compared to
>
> human
>
>>typing speed, that it just doesn't really matter.
>
>
> This is a straw man argument. Obviously, interpreted PERL is just fine
> for many applications. Yes, the speed of today's CPUs lets people get
> away with a lot of slop that they couldn't 15 years ago.
No, you misunderstand. It's not that the speed of today's CPU lets
people "get away with slop" -- it's that "optimization" of something
beyond what is technically sensible is poor engineering. The "slop" is
in thinking that because a compiler doesn't produce optimal code for a
for loop, that it's therefore inferior to hand-coded assembly. The
context of the code is important, as are the criteria for judging
"inferior" vs. "superior."
> But as programs get larger, they get *uniformly* slower. Waiting for
> keystrokes is irrelevant. Waiting for some search function that
> recomputes a key's length after each character is bad.
Why do you assume it's bad? In fact, automatic text completion,
available in many programmers' editors, does exactly that. Every
keystroke adds to a key's length and the lookup is done when the person
at the keyboard pauses for a moment. Far from being bad, it's a useful
feature, and does NOT slow down the application such that it's
noticeable to the human typist. That's *good* design.
>>this potential of assembly language code "beating" the compiler is
>>rarely realized simply because it's too time-consuming to do so.
>
> IOW, programmers are too lazy to write the code efficiently.
It's not a choice between "write assembly code by hand" or "write
inefficient code" -- that's a false dichotomy.
> Therein lies the fundamental problem.
Rhetorical excess? ;-)
>>systems) I find that it simply doesn't make economic or engineering
>>sense to write much in assembly language these days.
>
> I think you're really missing something here. This is *not* a thread
> about "we should write everything in assembly language." This is a
> thread about "compiler optimizers aren't living up to their promise."
Compiler optimizers usually do an adequate job. Could they do more?
Probably, but 97% of the time it doesn't matter. That's my point.
Ed
|
|
0
|
|
|
|
Reply
|
Ed
|
4/20/2005 11:09:03 AM
|
|
Ed Beroset wrote:
> >
> >
> > The difference, however, is that the bad machine code is generally
more
> > obvious in the assembly language program. In the HLL code, the HLL
> > abstractions hide what's going on.
>
> That's incorrect. Because HLL code is more readable generally,
mistakes
> are easier to find, too, whether they are design errors or coding
errors.
Your comment is orthogonal to this discussion. We're not talking about
incorrect code. HLL abstractions hide the quality of the code being
generated, so the programmer doesn't see the gaffes the compiler is
committing (and therefore, doesn't realize that they should do
something different). This is true *regardless* of the programmer's
expertise level. When viewed in assembly, the inefficiency becomes more
obvious (at least, to someone who can read the assembly output).
>
> >>Donald Knuth has famously
> >>said that "premature optimization is the root of all evil."
> >
> > Actually, the quote is due to CAR Hoare. Knuth just quoted him.
>
> Right you are. In any case, the sentiment remains.
But do read Charles Cook's commentary. He has some interesting comments
about what CAR Hoare *really* said on this subject.
> >
> >
> > This is a straw man argument. Obviously, interpreted PERL is just
fine
> > for many applications. Yes, the speed of today's CPUs lets people
get
> > away with a lot of slop that they couldn't 15 years ago.
>
> No, you misunderstand. It's not that the speed of today's CPU lets
> people "get away with slop" -- it's that "optimization" of something
> beyond what is technically sensible is poor engineering.
If code today were written to that level of optimization, we wouldn't
be having this discussion.
> The "slop" is
> in thinking that because a compiler doesn't produce optimal code for
a
> for loop, that it's therefore inferior to hand-coded assembly. The
> context of the code is important, as are the criteria for judging
> "inferior" vs. "superior."
It isn't a question of whether it's inferior or superior, the better
code is always superior. The question is whether you're willing to
accept inferior code on economic (rather than technical) grounds.
Don't confuse technical and economic arguments here.
>
> > But as programs get larger, they get *uniformly* slower. Waiting
for
> > keystrokes is irrelevant. Waiting for some search function that
> > recomputes a key's length after each character is bad.
>
> Why do you assume it's bad? In fact, automatic text completion,
> available in many programmers' editors, does exactly that. Every
> keystroke adds to a key's length and the lookup is done when the
person
> at the keyboard pauses for a moment. Far from being bad, it's a
useful
> feature, and does NOT slow down the application such that it's
> noticeable to the human typist. That's *good* design.
You're right, it's good *design*. It was designed that way, as opposed
to being whatever the compiler generated for you behind your back. You
do see the difference, do you not?
> > IOW, programmers are too lazy to write the code efficiently.
>
> It's not a choice between "write assembly code by hand" or "write
> inefficient code" -- that's a false dichotomy.
Where did this statement say anything about assembly? It *is* possible
to write efficient code in HLLs, you know.
> >
> > I think you're really missing something here. This is *not* a
thread
> > about "we should write everything in assembly language." This is a
> > thread about "compiler optimizers aren't living up to their
promise."
>
> Compiler optimizers usually do an adequate job.
One could argue that if you turned optimizations off the compilers
still do an adequate job. One could claim that you could run your
programs in an interpreted language like PERL and that would be
adequate too.
The problem is that people who decide to write code that is "just
adequate" often fall short of the mark. Far short.
> Could they do more?
> Probably, but 97% of the time it doesn't matter. That's my point.
And that's the attitude that leads people to write sloppy code. "Who
cares? Compilers produce adequate code 97% of the time. No need to
worry about optimization." And as the Widipedia article I referenced
points out, it's too late and too difficult to go back and improve the
situation once the software is written.
Cheers,
Randy Hyde
|
|
0
|
|
|
|
Reply
|
randyhyde
|
4/20/2005 5:00:36 PM
|
|
randyhyde@earthlink.net wrote:
> Ed Beroset wrote:
>
>
>>>
>>>The difference, however, is that the bad machine code is generally
>
> more
>
>>>obvious in the assembly language program. In the HLL code, the HLL
>>>abstractions hide what's going on.
>>
>>That's incorrect. Because HLL code is more readable generally,
>
> mistakes
>
>>are easier to find, too, whether they are design errors or coding
>
> errors.
>
> Your comment is orthogonal to this discussion. We're not talking about
> incorrect code.
You're being loose with the term "bad code." In my world, bad code is
incorrect code. That's why the context of the code is important. Is it
the innermost loop of a mathematically-intensive Finite Element Analysis
(FEA) program or a delay loop in a screen saver? It makes a difference!
>>>keystrokes is irrelevant. Waiting for some search function that
>>>recomputes a key's length after each character is bad.
>>
>>Why do you assume it's bad? In fact, automatic text completion,
>>available in many programmers' editors, does exactly that. Every
>>keystroke adds to a key's length and the lookup is done when the
>
> person
>
>>at the keyboard pauses for a moment. Far from being bad, it's a
>
> useful
>
>>feature, and does NOT slow down the application such that it's
>>noticeable to the human typist. That's *good* design.
>
>
> You're right, it's good *design*. It was designed that way, as opposed
> to being whatever the compiler generated for you behind your back. You
> do see the difference, do you not?
I usually type with the computer in front of me, not behind me, and I've
read the manuals and, in many cases, the generated code of my compilers.
So it's not really possible for it to generate code "behind my back."
If an apprentice carpenter hits his thumb with a hammer, I'd call that
a fault of the apprentice carpenter and not the tool.
"Know what you're doing" is free advice, and worth every penny you paid
for it!
More practical optimization advice would be as follows:
0. understand, thoroughly, the problem to be solved
1. seek an efficient algorithm for the problem you're trying to solve
2. determine measurments which will assure that your program is "fast
enough" by whatever criteria
3. implement carefully, understanding the ramifications of data
structure choices, or library calls, for example
4. measure and compare against the criteria from #2
5. stop when you have correct code which satifies the criteria
Knowledge useful for following this advice includes:
1. the assembly language for the target platform
2. thorough knowledge of your tools (compilers, linkers, emulators,
build tools, profilers, librarians, source repositories)
3. in depth understanding of the problem to be solved
4. at least a basic understanding of data structures and algorithms
5. an understanding of how to test software
6. practice in estimating how long things take (both computer things
and your time in writing software)
That's not meant to be an exhaustive list, or even directed at you,
Randy. It's also not the only way to do things, but it's the way I've
found useful and have honed over the years. An optimization of the
optimization process, if you like. Just like code optimizations, there
are many ways to do it, and many definitions of "optimal."
>>>IOW, programmers are too lazy to write the code efficiently.
>>
>>It's not a choice between "write assembly code by hand" or "write
>>inefficient code" -- that's a false dichotomy.
>
> Where did this statement say anything about assembly?
It was in the part you snipped:
>> this potential of assembly language code "beating" the compiler is
>> rarely realized simply because it's too time-consuming to do so.
Your response was "IOW, programmers are too lazy to write the code
efficiently."
Your incorrect paraphrase is an example of a false dichotomy; a logical
error.
>>Could they do more?
>>Probably, but 97% of the time it doesn't matter. That's my point.
>
> And that's the attitude that leads people to write sloppy code.
No, that's the attitude that leads people to be on the lookout for the
3% that matters instead of wasting their time on the 97% that doesn't.
Ed
|
|
0
|
|
|
|
Reply
|
Ed
|
4/20/2005 8:18:52 PM
|
|
randyhyde@earthlink.net wrote:
>
> It isn't a question of whether it's inferior or superior, the better
> code is always superior. The question is whether you're willing to
> accept inferior code on economic (rather than technical) grounds.
> Don't confuse technical and economic arguments here.
Such decisions should be made for neither technical nor economic
reasons, but for engineering reasons, and engineering reasons
always involve both technique and economics. Ignore economics
and your project is every bit as likely to fail as if you ignored
technique. So yes, sometimes you must accept 'inferior' code for
economic reasons.
--
Thomas M. Sommers -- tms@nj.net -- AB2SB
|
|
0
|
|
|
|
Reply
|
T
|
4/21/2005 4:09:41 AM
|
|
|
77 Replies
165 Views
(page loaded in 0.803 seconds)
|