home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / arch / 9227 < prev    next >
Encoding:
Text File  |  1992-09-04  |  7.5 KB  |  162 lines

  1. Newsgroups: comp.arch
  2. Path: sparky!uunet!cis.ohio-state.edu!news.sei.cmu.edu!firth
  3. From: firth@sei.cmu.edu (Robert Firth)
  4. Subject: Re: Scientists as Programmers
  5. Message-ID: <1992Sep4.151001.9886@sei.cmu.edu>
  6. Organization: Software Engineering Institute
  7. References: <1992Aug31.195540.13074@ctr.columbia.edu> <1992Sep1.115849.13522@relay.nswc.navy.mil> <Btx4vF.Jx6@mentor.cc.purdue.edu>
  8. Date: Fri, 4 Sep 1992 15:10:01 GMT
  9. Lines: 151
  10.  
  11. In article <Btx4vF.Jx6@mentor.cc.purdue.edu> hrubin@pop.stat.purdue.edu (Herman Rubin) writes:
  12.  
  13. >What is relevant is
  14. >the translating of the problem to be computed into the collection of bits
  15. >which the machine can understand to accomplish the task.  This involves
  16. >
  17. >    Knowing the algorithmic processes which can be applied, their
  18. >    strengths and weaknesses, and what happens to them on the particular
  19. >    machine when they are translated using the available languages.
  20.  
  21.  
  22. Whether scientific programmers need to understand the hardware is a
  23. debateable topic, but on the issue of fact that Dr Rubin raises, please
  24. let me add my firm support to his assertion that most programmers,
  25. scientific or otherwise, in fact do not understand the machinery
  26. beneath their feet.  Allow me to relate a story from my own experience,
  27. which is perhaps of some relevance to the issue of machine and system
  28. architectures.
  29.  
  30. The problem to be solved was this: you are writing a compiler for a
  31. language that has separately compiled units, which I'll call "modules".
  32. A module may declare types, procedures, variables &c.  It may also
  33. include a body of executable code called "initialisation code".  The
  34. rules of the language are: first, that all initialisation code must
  35. be executed, once only, before the "main program" runs; and, secondly,
  36. that if module A references or "imports" module B, then the initialisation
  37. code of B must be executed before that of A.  Circular imports, of course,
  38. are forbidden.
  39.  
  40. What is the appropriate codegeneration strategy to deal with this?  Well,
  41. back in the bad old days, when programmers were amateurs trained in
  42. English literature, biochemistry or quantum mechanics (as was the case
  43. with the first programming team of which I was a member), we had a pretty
  44. simple-minded and straightforward way to do this.  We would create a
  45. separate code section, something like
  46.  
  47.     .PSECT INIT,GBL,EXE,PIC,RO
  48.  
  49. and decide that all initialisation code would go in that section.  So, if
  50. a module had some initialistaion code, we'd spit out the .PSECT directive,
  51. then the code, and then restore the status quo ante.
  52.  
  53. At link time, we'd inspect the import lists, carefully squirrelled away in
  54. auxiliary files, construct a total module order consistent with the partial
  55. order of the import graph, and proffer the object modules to the linker in
  56. that order.  The linker would obligingly concatenate all the initialisation
  57. code into the one Psect; we'd then top and tail it with two tiny hand-written
  58. modules that put a procedure entry at the top and an exit at the bottom;
  59. and, somewhere in the startup code, we'd make sure there was a call to the
  60. init code before we entered the main program.
  61.  
  62. Simple, and efficient.  Note that this obeys the rules, ensures that all
  63. the init code is executed, once only and in the right order, and with the
  64. overhead of a single procedure call.  Moreover, the code is contiguous,
  65. and if we have a clever system, we can mark that whole Psect as a cluster,
  66. to be paged as a unit, and even mark it to be resident on program load.
  67. After it's executed, of course, it will obligingly page itself out pretty
  68. quickly (or we can even do that by hand), and disappear from main store,
  69. ne'er to be found again.
  70.  
  71. The way we arrived at this scheme was pretty simple, too: we worked
  72. backwards.  First, visualise what you want to happen at run time; next,
  73. design the structures that must exist inside the machine to make it
  74. happen; finally, distribute the work of creating those structures among
  75. the compiler, codegenerator, linker, loader &c so that each does the
  76. right and appropriate thing.
  77.  
  78. As I said, that was in the bad old days.  Welcome to the worse new days,
  79. for here is how the same problem was solved by a team of trained
  80. professionals, working for a real company, writing a real, for-profit
  81. compiler that people were expected to pay for.  I was there; I saw it.
  82.  
  83. The initialisation code of a module was converted into a closed procedure
  84.  
  85.     procedure A_Init
  86.     begin
  87.        ...stuff...
  88.     end
  89.  
  90. and emitted along with the rest of the code in a single section.  If the
  91. module A called module B, then the initialisation of B was invoked by
  92.  
  93.     procedure A_Init
  94.     begin
  95.        call B_Init
  96.        ...stuff...
  97.     end
  98.  
  99. Of course, at this point, A didn't actually know whether B contained any
  100. initialisation code, but it called the procedure anyway.  Hence, a module
  101. with no init code had to declare a procedure with a null body, just in
  102. case.
  103.  
  104. Now, you are wondering, what if two modules import B, won't the init code
  105. be called twice?  Yes, and this was solved by a Cunning Ruse:
  106.  
  107.     Init_Done: Boolean := False
  108.  
  109.     procedure A_Init
  110.     begin
  111.        if not Init_Done then
  112.           Init_Done := True
  113.           call B_Init
  114.           ...stuff...
  115.        end
  116.     end
  117.  
  118. So, if a module was imported 648 times, then the init code was called 648
  119. times, and on the last 647 calls, it did nothing.
  120.  
  121. This scheme is evidently correct, since - good grief Moriarty - the call
  122. graph of the Init_Code procedures is isomorphic to the import graph of
  123. the modules.  But look at the cost: not one procedure call for each
  124. module with init code; not even one call per module, but one call for
  125. every ARC of the import graph!  That's a lotta calls.  Moreover, that
  126. code is scattered through the whole core image.  That's a lotta page
  127. faults.  And those tiny static Boolean variables Init_Done are also
  128. scattered through the data section, so double those page faults.
  129.  
  130. Now, these people were not fools - they were PhD's in computer science
  131. and some of the brightest folk you could meet.  And this was not a cheap
  132. and cheerful hack; it was supposed to be an industrial strength optimising
  133. compiler with register tweaking, loop scrunching, dead code eulogisation,
  134. you name it...  So why, then, did they implement this simple feature in
  135. the most grotesquely inefficient way imaginable, with a design one would
  136. expect a developmentally-challenged tree sloth to be able to pick to
  137. pieces in ten seconds?
  138.  
  139. I believe the answer is this: these people had between them about 30 years'
  140. eduucation in academic computer science.  They knew about stacks, queues,
  141. lambda calculi, invariants, NP-completeness; they could use words like
  142. "isomorphic" over morning coffee.  And, in all that time, they had never
  143. been taught to visualise *what really happens when real code runs on
  144. real machines*.
  145.  
  146. This problem is pervasive.  Each generation sees a new and more monstrous
  147. bloat in the size and cycle consumption of what I still think of as basic
  148. system software - device drivers, editors, compilers, linkers.  And the
  149. reason the programmers are so profligate of resources is that they have
  150. never been taught that resources matter - they are told that, in computer
  151. science, "everything is virtual", and all resources are infinite and free.
  152. There is no technical perception of the machine as a real engine, with
  153. finite capability, and no aesthetic perception that economy of means is
  154. one of the cardinal qualities of good engineering.
  155.  
  156. This must be changed.  Or real companies, with real problems, will continue
  157. to hire english majors, biochemists and quantum mechanics to write their
  158. programs; because, as a senior member of one such company told me: "It is
  159. cheaper to train than to re-train."
  160.  
  161. Robert Firth
  162.