Tunes Philosophy (was: A few ideas)

Francois-Rene Rideau rideau@ens.fr
Sat, 6 Apr 1996 00:38:52 +0200 (MET DST)


>:JVS
>>:Fare

> The way I see things is as follows:

> 1. The terms 'HLL' & 'LLL' are merely conveniences:
   Hum. That they be convenient proves they are not meaningless,
even though the limit between them be fuzzy.

> whenever someone
> is programming *anything* (s)he is merely tweaking vectors or
> channelling flow of information in a sort of giant "vector space".
   Yes. But then, there are several different much different
ways to tweek those vectors. I don't feel quite the same when doing
numerical analysis, symbolic algebra, or robot control.

> We are dealing with an integrated whole.
   Unhappily, the whole is not quite integrated in existing systems
(how could it be, using unexpressive low-level static languages like C).

> Whether you say:
> a = 1   OR   MOV AX,1  is merely a matter of _perspective_.
   Here, let me disagree. Surely, in a given context,
you might know that the conventions are such that indeed,
your "a = 1" would be compiled to "MOV AX,1".
   Now, when you consider not the static context,
where the program is perfect, fixed, unmodifiable, compiled and optimized
for the i386,
but the dynamic context, where the program is part of a project,
evolving, modifiable, in source form, portable to any architecture,
then you see how these are completely different.
   Sometimes, it is really "MOV AX,1" that you want,
because the next instruction is "OUT DX,AX", and that's the only way.
But most of the time, the more abstract form "a = 1" allows the compiler
to co-optimize this instruction with former ones: imagine you then
compute "f(a)" which could be partially evaluated to f(1) and such,
if the *independently* determined function f makes it efficient.
By writing "MOV AX,1", you preclude such further optimization.
Of course, in some cases, when you don't care about further optimization,
when the program is not part of a longer project, etc,
"MOV AX,1" *might* be most useful solution.
   But my point is that there is quite a difference between these
instructions. Moreover the 1 in MOV AX,1 is always a 16-bit pattern.
Even in C, "a = 1" could be of various sizes, perhaps determined
externally by a macro or template. And in other languages,
the 1 could be in some interval, or of arbitrary precision,
or a complex number, or the unit of any algebra,
which precisely might be *dynamically* determined.
   Of course if by "a = 1" you *only meant* what "MOV AX,1" means,
then I admit it was indeed the same thing,
but you must then admit you take it in a very restricted context.


> 2. In order to achieve a stable programming environment (whatever the
> so-called "level"), we need:
>     2.1 Independence from the underlying machine BUT
>     2.2 the ability to continually monitor performance (and even
>         to a degree predict performance)
>     2.3 Minimum complexity, and thus
>     2.4 Robust code.
   Firstly, let's see that we can generalize 2.1 by high-level
and 2.2 by low-lvel; then we must admit that these are opposite
tendencies, and you can't have all of both in a given *program*,
at least in the usual meaning
[I assume "monitoring" means being able to tweak and modify things,
not just looking at how long its takes for the program to run].
   However, Tunes supports the concept that this "usual meaning" is
due to the nasty habit of having programs be both
the specification (in most poorly expressive language, constraintwise)
and implementation (in not-so-richly expressive languages, constructionwise).
The programmer is thus forced to make a compromise betweens those
opposite trends, so with available programming tools,
anything you gain in abstraction, you lose it in efficiency, and conversely.
Of course, you can write two, ten, five hundreds, one million programs
for doing the "same" thing, each in different languages,
so as to have the "right compromise" in any given situation;
but then you have no tool to guarantee any consistency,
between those programs; no one can give you any checkable
warranty about those uncountably many programs being "identical",
all the more when most (low-level) representations will have
validity conditions, unexpressible in the implementation language,
out of which they do not denote the same thing anymore.
   Now, there is no reason why this stupid programming practice
must continue. It was the only sensible way to do things,
in time when computer memories were too tight
to hold more than the implementation,
when computer resources were just enough to straightforwardly translate
some human-readable symbolic code into machine code.
But now that era of programming pioneering is ended.
Machines have enough resources to allow consistent large scale
meta-programming, and this is the way they should go,
and all the time before they do is lost.
Here is the next computing revolution.
The internet is the medium of fast (humanwise) world-wide communication.
So it vehiculates information, not noise,
which is what consistency means,
we *need* such metaprogramming environment.


> 3. If we intend to produce a system which works and is stable in a
> variety of different environments, we need some common ground from
> which to move.
   This "ground", to be, can only be the HLL. Because people
just don't care if the computer does it with "mov ax,1",
with "a = 1", with "movw 1,%d0", with "(let ((a 1)) ...)" or anything.
What they want is that database to work,
this symbolic function to be integrated,
this sample to be analyzed,
this robot to be controlled.
   And these are *high-level* specifications (so high-level,
they sometimes cannot find perfect formalization),
not low-level ones.

> Below this "ground level" things might work
> differently in different systems,
   I completely agree.

> but above it we would have
> completely reproducible performance regardless of the system,
   Whatever you do, unless you drastically slow down the faster computer,
you can't reproduce the same performance on somebody's plain old Apple ][
(or HP48) as on somebody else's latest 330 MHz dual AXP computer.
You may enforce performance *warranties* (subject to hardware failure),
that will be valid assuming the according resources can be reserved to you,
but don't expect "reproducible performance". Don't wish it either,
because reproducible is never compatible with optimal
(though sometimes quite preferrable).

> with
> the caveat that we would be able to use primitive instructions ON
> this level to determine the feasibility (space and/or time
> constraints) of any action, if required. This is my "SYMBolic
> Assembly Language level" (let's call it "SYMBAL").
   This, I agree, should be an option to the programmer,
that has strong support. However, it should still be an option,
because most people just don't care about warranties,
that never speed up code, and only slow down compilation.
Also, please not that on computers with several levels of
dynamically controlled caches from the ALU to persistent memory
(registers, first, secondary and soon tertiary RAM caches, DRAM, I/O, disk),
the performance of a single instruction is meaningless (varies
from half a CPU cycle to several milliseconds needed to fetch data through
all these levels of cache).
Of course, if you can make some assumptions or precise predictions
about the behavior of the various caches, and frequency of fetches
from outer caches to inner ones,
then you might be able to predict the overall performance
of tight loops, and even cooperative-multithreaded code,
which might help optimizing code.
Actually, performance control becomes very interesting in the context
of embedded chips, where timings are much more important, yet simple,
to know and warranty.
   Of course, only high-level symbolic tools, able to do complicated
code manipulations, can be used to "monitor performance" that precisely,
and then, you can use them to mostly program in high-level.


> Now you might argue that one could simply use e.g. C (or Scheme, or
> whatever) as our SYMBAL.
   I won't. Firstly, C is a stupid language to me,
Scheme an exclusively high-level one.
However, I'll say that over a reflective language like Scheme
(as better than it as the LLL will be better than FORTH),
and with help of proper meta-primitives,
it is possible to develop extensions towards the low-level for Scheme,
so that you could control things down to the kth bit of any register
at some stage of CPU pipelining (now would one want to go that far
is another question).


> My _feeling_ is however that
> we would end up doing so many ASM hacks (whatever the system) in order
> to achieve the above goals, that it would be best to define things
> afresh.
   If you mean by using C/Scheme as a l


> We would also then not have the temptation to use features of
> eg C, just "because they are there", and we would not see things in
> the light of the peculiarly skewed architecture of e.g. C. I am not
> saying that we have to re-invent the wheel just for the hell of it,
> but what I am saying is that the wheel *must* be re-invented if
> all systems at present use square wheels (as I believe they do)!!
   I agree with this, but perhaps not with what round wheels really are.


> What are these square wheels? My partial list:
>
> 3.1 Featuritis. By this I mean bunging in a whole lot of "pretty"
> features, without due consideration as to their impact. Apparently
> innocuous "fundamental" architectural decisions (come on chaps, lets
> have the following data types char, int, UINT, long int etc) may have
> a massive impact on performance and complexity e.g. in the extreme 
> case if we choose ten data types and have 100 functions that can each 
> accept two arguments, each argument being of any type [perhaps a 
> rather silly and extreme example] then we have 100*10*10 = 10 000 
> cases to account for, if we had just 3 data types we would have < 10% 
> of these to consider.. A zillion different ways of e.g. accessing 
> files may give you a lot of pseudopower in the short term, but cripple 
> you in the long term due to costs of documenting all these frills, and 
> unwanted  interaction between the frilly bits! We need to ask the 
> question:
> "What are the absolute minimum requirements for our SYMBAL, in order
> to get full functionality?", and add NOTHING MORE. The answers we
> get to this question may be very surprising!
> 
> 3.2 The microprocessor as slave-master.
> Here, I mean that our ideas of how a system should function are subtly
> (and sometimes, not-so-subtly) influenced or dictated by the processor
> we use/are familiar with. It is not only the uP that has this effect:
> cf design cockups such as the 640K, and leaving out an inverting 
> buffer in the serial port of the original IBM-PC. A particular example 
> is the use of words of a particular width. The natural tendency is to 
> say,
> "Hooray, we now have 32 bit registers, let's design everything about
> a 32-bit word" (or whatever). Surely we should define the 
> "granularity" [or whatever] that we need in order to implement a real-
> life system, and THEN use the available material optimally to 
> implement this? Sure, we may find that 32 bit words ARE cool (or 80 
> bit, or whatever), but I see this sort of thing as a fundamental 
> design requirement that is glossed over. It is NOT difficult to 
> implement 32 bit words on an 8 or 16 bit microprocessor, working from 
> the start; it _is_ rather tricky to go back and rewrite your whole 
> system (or live with a cripple) when you discover that your design 
> philosophy is fatally flawed. Or am I being silly?
> 
> 3. No/poor timing. (Timeout as opposed to timin')!
> On most systems (especially those with virtual memory managment) one
> often has _no idea_ how long e.g. a particular disk access or memory
> write or whatever is going to take. You may think that I am going
> completely over the top in desiring this, but I think not, I think
> that we have come to accept this as a part of computer life, which
> is in my mind unacceptable. I think that timing is _vital_, and will
> become even more vital when/if we start using parallel systems more
> extensively (more or less inevitable as we push the limit in terms
> of cramming more transistors onto increasingly warm silicon)! I do
> not mean that we need absolute precision in timing, but it's nice
> to know whether something will take 1 microsecond or two seconds!


> 4. Poor/no parallelism. (piss-poor parallelism)!
   [Yes, but note that this contradicts your *requirement* of
performance control, as only trivial parallel algorithm can
be thus controlled, though statistical models may sometimes allow
fair monitoring]


> 5. DISgraceful degradation!
> My opposite of graceful degradation [!]. NO task should be able
> to crash the whole system. Period. (Try tinkering above 2GB in Win95,
> try even _looking_ at win 3.11 a bit skew).
> But even more than that, I think that the tendency is often to
> tack some sort of primitive "what do we do with the error stubs now
> that we've written the REAL code" approach on, rather than perhaps
> designing the whole system around the exceptions/errors that can
> possibly occur!! Particular attention to stack overflows, attempted
> writes to forbidden areas, even loading the wrong bloody register
> with the "wrong" value - anyone who has played around with ASM under
> Win3.11 will know why my teeth are ground down to stubs).


> 6. No "quantized damage"
> Related to (5) above. I believe we need to define a primitive unit
> of "damage quantization" : if a total cockup occurs, damage is
> limited to that unit, come-what-may (i.e. all communication with
> that unit is via data streams, so the worst that can happen is that
> the stream is corrupted/stops flowing). [This doesn't of course
> protect us from bloody silly stream handling in the communicating
> process.. closely related to the concept of building the system
> around errors that might occur]. 
> 
> But I don't know enough about your Scheme [etc]. Maybe it does 
> all this?
> 
> [You will appreciate that _I_ am biased by my previous experiences,
> especially under Win=Loss & Dos, so I would appreciate comment].



>>    That we all agree to, I think, except perhaps for the term
>> "high-level weenies". Most people rightfully don't have time
>> to bother about the low-level,
>> and we the OS hackers are here to relieve them from that hassle.
>>    What if motor-car hackers decided that every car-driver
>> should be able to repair their car and fine-tune the motor ?
>> Are standard car-drivers "weenies" ?
>>    What if cordon-bleus required every one to cook as well as they ?
>
> A major part of the problem is the (in my mind totally unnecessary)
> distinction between "people who don't have time to bother about the
> lower level" and "OS hackers". As I mentioned above, this is a matter
> of _perspective_. I see no reason why, in our system, _anyone_ should
> not pick up a languagetool, and click on some code to view it as
> one of: 1. native assembler, 2. SYMBAL 3. tinyC 4. miniPascal 
> 5. newFortran 6. SCHEMing, or whatever!
> [and it is SO STRUCTURED that in EACH CASE it is legible and clearly
> annotated - perhaps I'm dreaming].
> Do you call in a cordon-bleu chef every time you want to boil an egg?
> Do you need a qualified mechanic to check your radiator water?
> There is a difference between being "relieved from hassle" and being
> a vegetative blob.
>
>> Are bad cooks "weenies" ?
> Yes.
   Are you a specialist of everything ?
Do you think everyone should become a specialist of everything ?
Do you think this is feasible ?
Do you think this is useful ?
   No, nobody can ever become a universal specialist,
and efforts in that direction are altogether vain and harmful.
It is specialization of each one in a particular field
that makes civilization. The time when everyone did most everything
by himself (which at that time, would be mostly hunting, cooking) is ended.
Instead of losing energy in each activity's overhead,
people specialize hence reduce the overhead/production ratio,
and allowing civilization improvements.
   Even if all computer users actually were somehow specialized
in low-level things, this would be a harmful thing that we should fight.
People should know the general principles of the techniques,
so they be aware of dangers, and know how to survive, and who to call
in case of a problem. But apart from that, the technicians should arrange
so that normal people *need* know as little as possible (while never, of
course, *forbidding* them to know), and relieve them from useless hassle
which is just another kind of overhead that reduces their productivity
in their own particular field. Surely, at a given time,
for a given of technology, there might be more or less to know
   As for cooking, microwave cooking is a great progress,
so you can have elaborate food by just putting something inside,
turning two knobs, and pushing a button;
ten years ago in France, you'd have to cut things in pieces,
put it on the oven with grease, and see that it doesn't burn;
I don't tell you how women spend hours everyday just to cook on
a wood-fire, in underindustrialized countries --
and with overpopulation, timber is getting rare.
Sure, no need to be a genius to boil an egg, to check the radiator,
to delete files from disk. But any second that technology saves me
by relieving me from doing this is a second I can spend on tasks
where I can be much more useful.
   If Galileo Galilei had to hunt for deers in the forest
(which doesn't require exquisite skills), or even just cook everyday food
with the technology of his time, and take care of (horse) cars,
I doubt he would ever have had time to found modern physics.
Any minute that he was retained by stupid tasks
(like being tried by the christian church, also),
was lost to mankind as new wonderful discoveries that were delayed,
perhaps indefinitely.
   So, there *is* a neat distinction between people who like
computers for the fun of it (like you and me), and the average people
who see it merely as a tool, that we proficient people should make
as easy to him as possible, in the same way as he chef cook makes
food more agreeable to us, as them agriculturers made food more available,
etc. Being able to focus on specialized things we like is not becoming
a vegetative blob, but ceasing to be one.

   It's important to me how computer problems
are treated with an approach derived from a general philosophy of life.
Computers are not heterogeneous to life, but are part of it.
This is at the heart of the Tunes project, to me,
and is why the name Tunes refer to Utility,
which is an eminently moral concept.

[Last technical note: Scheme being much more expressive than C,
I doubt you can "view" a complex enough Scheme program
as a program in any kind tinyC (or full C),
without losing most of its semantics]
--    ,        	                                ,           _ v    ~  ^  --
-- Fare -- rideau@clipper.ens.fr -- Francois-Rene Rideau -- +)ang-Vu Ban --
--                                      '                   / .          --
Join the TUNES project for a computing system based on computing freedom !
		   TUNES is a Useful, Not Expedient System
WWW page at URL: "http://www.eleves.ens.fr:8080/home/rideau/Tunes/"