On Nov 13, 2007 1:56 PM, Roy J. Tellason <rtellason at verizon.net> wrote:
Well, my admittedly limited experience with stuff is
that the "main"
processor isn't doing much of anything while it's waiting for I/O to complete
anyhow, or at least that's what my perception has been. Now I'll be the
first to admit that my perceptions are very much skewed toward the 8-bit
micro and crudely-done DOS-based end of things, so maybe I just need to get
a good hard look at how some other stuff is done.
If the processor isn't doing other things while waiting for I/O to
complete, it's either a case where 1) the OS or computer architecture
doesn't allow such things, 2) the application would not be helped by
doing other things during I/O, 3) cross machine compatibility
prevented it from being implemented or 4) the programmer was too lazy
to implement it.
It the case of MS-DOS (the term DOS is insufficiently specific) it
could be any of the four. Interrupt driven I/O or DMA were not
available on all MS-DOS machine to all devices. If it was available,
it wasn't too terribly difficult to implement non-blocking I/O by
difficult to setting up a transfer and doing other things while the
transfer completed.
Most multitasking operating systems implement blocking and
non-blocking I/O as system calls. Blocking I/O usually only blocks
the calling process. The transfer is set up and a task switch is
executed to transfer control to another process. Each time the
process reawakens, it checks to see if the I/O is complete. If not it
executes as task switch.
I would assume that Multics is set up this way as well. Each time a
process request I/O, the CPU tells the I/O processors what to do and
then transfers control to another process.
So aside from computationally-intensive tasks what
else is there for it to do?
Whatever another process wants it to do. If no other process wants
anything to be done, then it will execute the idle process. What the
idle process does is OS dependent. It might do housekeeping tasks, it
might make das blinkenlights show pretty patterns, or it might halt
the processor until the next interrupt.
> In any processor with pipelining, instruction
look-ahead and caching,
> branch prediction and all of those other little gimmicks that make
> execution faster, the idea of interposing interrupts that bollix up
> all of the above is pure insanity.
Yet that's still how it is done. You just try to execute as few
interrupts as possible by making transfers larger. Although you have
to watch out because SOME operating systems will default to 1
interrupt per word transferred. Watch your key presses, because
there's probably and interrupt AND a task switch every time you press
one.
Not that it matters that much anyway since a modern processor on
non-trivial code is spending 90% of its cycles waiting for memory.
A few thousand cycles for an interrupt is nothing...
I'm basing that number on FLOPs per cycle for typical medium sized
(64MB working set) scientific computing applications. Spending a lot
of time optimizing (transposing arrays when necessary to make memory
accesses ordered, precaching the correct things at the correct time,
choosing not to cache the correct things at the correct time) you can
get that down to 65% of the time waiting on memory. It sound like a
lot of work for minimal gain, but please realize the difference
between 90% waiting and 65% waiting is a factor of 3.5 in execution
speed.
Ah, the good old days when processor and memory operated at nearly the
same speed.
Maybe not so good when you consider that loading a 16 bit word on an
8086 took 10 times longer than loading a half kilobit cache line does
now.
--
Eric