[HN Gopher] A CPU is a compiler
       ___________________________________________________________________
        
       A CPU is a compiler
        
       Author : signa11
       Score  : 132 points
       Date   : 2023-03-23 08:20 UTC (14 hours ago)
        
 (HTM) web link (outerproduct.net)
 (TXT) w3m dump (outerproduct.net)
        
       | mhh__ wrote:
       | Intel made a processor with a GC in hardware once
        
         | moonchild wrote:
         | so did sun -
         | https://web.archive.org/web/20061230133753im_/http://researc...
         | 
         | and david bacon (et al) - https://files.catbox.moe/bipg79.pdf
        
           | pjmlp wrote:
           | And Xerox PARC, TI, Rational, Azul, Danny Hillis, and plenty
           | others.
        
             | moonchild wrote:
             | Azul did GC in software; they only had hardware assistance
             | for barriers and such like. (Can't speak to the rest.)
        
               | pjmlp wrote:
               | Sure but it wouldn't run anywhere else.
        
         | Gordonjcp wrote:
         | Linn (the hifi people, not the drum machine people) made a CPU
         | called "Rekursiv" (because they like odd spelling like that)
         | which had objects and GC implemented in hardware, on a couple
         | of very large custom chips on VMEBus boards. These were
         | horrendously expensive and were to be plugged into a Sun 3 box,
         | making it all quite breathtakingly spendy.
         | 
         | When Sun brought out their SPARC hardware the language they run
         | was ported to that, and ran about four times faster clock-for-
         | clock.
         | 
         | You can gain some measure of the Rekursiv's success from the
         | fact that the only complete machine known to still exist can be
         | found on the bottom of the Forth and Clyde Canal, somewhere
         | around the Possil Road Aqueduct.
        
           | mschaef wrote:
           | I can't imagine the thought process by which a niche Hi-Fi
           | company decides the best way to automate their production
           | system is to custom develop a totally new class of CPU...
           | which is why I am glad there are at least a few people in the
           | world that make the attempt.
           | 
           | (This whole thing also reminds me of the Intel 432... had
           | some similar properties)
        
           | Traubenfuchs wrote:
           | > because they like odd spelling like that
           | 
           | The founders parents fled from Austria during Nazi times. In
           | Austria we speak German. The English word "recursive" is
           | "rekursiv" in German.
        
             | Gordonjcp wrote:
             | Ja, genau. Actually, his parents were Polish but moved to
             | Austria.
             | 
             | Fascinating guy.
        
           | CyberDildonics wrote:
           | What does it mean to have "objects" implemented in hardware?
        
           | klelatti wrote:
           | Goodness! Did you have a hand in placing that machine there?
        
             | mlatu wrote:
             | here is a writeup:
             | 
             | https://www.slideshare.net/sebrose/rekursiv
        
               | klelatti wrote:
               | Thanks!
        
             | Gordonjcp wrote:
             | Not me, no, but I know some of the dramatis personae from
             | way back then.
        
       | JoeAltmaier wrote:
       | I'm not sure where in that article the re-write-microcode feature
       | lies? That is, modern CPUs can write microcode for instruction
       | sequences, not just single opcodes. Which is almost exactly what
       | a compiler is, if you substitute 'op code sequence' for 'source
       | code sequence'.
        
       | ethanwillis wrote:
       | It's all just specific instances of the post correspondence
       | problem!!
        
       | titzer wrote:
       | Nice comparison. I think register renaming is more like doing SSA
       | renaming on a trace than register allocation, though.
        
       | uconnectlol wrote:
       | ... unfortunately.
        
       | uticus wrote:
       | Domain was previously elrond.net (redirects to outerproduct.net).
       | Previous submission to HN is a jewel:
       | 
       | "Why no one should use AT&T syntax ever, for any reason, under
       | any circumstances"
       | 
       | https://news.ycombinator.com/item?id=26122532
        
         | AnimalMuppet wrote:
         | A _jewel_? Um... I 'd call it a rant, myself. Not even a very
         | well-grounded rant.
        
           | mshockwave wrote:
           | same...I feel weird because I learned AT&T syntax since day
           | 1. And even with that, I think Intel syntax is just another
           | way of writing, period. No hard feeling at all. Don't quite
           | understand why the author is so...pissed.
        
         | pjmlp wrote:
         | When down that route once, about 20 years ago, never again.
        
       | nayuki wrote:
       | I can't recall the quote or source, but it went something like: A
       | CPU is a compiler that transforms a serial instruction stream to
       | a wide (acyclic) graph of data dependencies. This refers to
       | concepts like out-of-order execution, superscalar processing,
       | functional unit scheduling, and register renaming.
        
       | nickcw wrote:
       | Chip designers have noticed this similarity in the past have and
       | attempted to push some of the work done by the CPU back into the
       | compiler. Itanium and the Mill CPU both work(ed) like this I
       | believe.
        
         | lanstin wrote:
         | I used to enjoy the Mill CPU videos. Is there some good post-
         | mortem explaining what happened to that project?
        
           | ahartmetz wrote:
           | It is reportedly still alive according to their website, but
           | it's not very convincing.
        
         | terafo wrote:
         | Mill CPU never existed in silicon, so there are questions to
         | that. But IIRC Ivan said that they didn't do anything that
         | compilers didn't do already for DPSs. He specifically mentioned
         | that they don't want to be like Itanic.
        
         | MayeulC wrote:
         | You can argue that it's the RISC approach, to some extent.
        
         | JonChesterfield wrote:
         | All of them. And the compiler engineers try to push work into
         | the CPU.
        
         | tormeh wrote:
         | This will never work due to incentive structure, unless the
         | compiler devs are working for the same company that makes the
         | CPU. Otherwise, compiler devs will target a lowest common
         | denominator and call it a day. And even if the compiler devs
         | perfectly support new CPU instructions, compiler users usually
         | want a single binary that can run on as many CPUs as possible,
         | and so will use the lowest common denominator once again.
         | Currently, your CPU will 99% of the time run basic AMD64
         | instructions, regardless of its capabilities. So Intel and AMD
         | try to make their CPUs really good at running AMD64 code.
        
           | JonChesterfield wrote:
           | It's quite complicated. Sometimes hardware instructions are
           | awkward or redundant enough that compilers ignore them. Or
           | they're broken in hardware and the compiler tries to patch
           | around them. Sometimes there are invariants that are easy for
           | compilers and really annoying for assembly programmers. A
           | given sequence of instructions may execute correctly on
           | multiple (sub)architectures with widely divergent performance
           | behaviour.
           | 
           | The one binary that does minimal to no self modification on
           | boot is popular with users but intrinsically slower. Arm's
           | variable length vector instructions are catering to that.
           | 
           | One binary that is specialised to hardware and expected
           | arguments is the fastest you can do without optimising while
           | the program is starting/running.
           | 
           | However hardware usually changes slower than software.
           | Specifically if a program starts running on a specific x64
           | chip it's likely to stay on that chip until it finishes
           | running. Linux used to patch itself on boot to pick a faster
           | memcpy (may still do).
           | 
           | It seems obvious that fastest for sufficiently long running
           | processes is to ship a compiler IR, specialise first to the
           | hardware and second to patterns in the data. OpenCL/spir-v
           | have a finaliser premise where you lower to a given GPU just
           | before running on it. Specialising on program data is branded
           | JIT compilation. I don't know of anything doing both yet.
        
           | avianes wrote:
           | > unless the compiler devs are working for the same company
           | that makes the CPU
           | 
           | Every CPU manufacturing company have a compile team.
           | 
           | > This will never work
           | 
           | VLIW processors do work, and for a while now. This type of
           | architecture performs better for data-intensive workloads, so
           | you don't see them in the general-purpose world.
           | 
           | But if you are talking about Mill, yes it will never work.
        
             | tormeh wrote:
             | > Every CPU manufacturing company have a compile team
             | 
             | Sure, but that doesn't help when all the binaries are
             | compiled for AMD64 anyway.
        
               | UncleEntity wrote:
               | You can compile your own binaries if max performance is
               | the goal.
               | 
               | Assuming you have access to the source code of course.
        
               | tormeh wrote:
               | Intel and AMD are so good at running AMD64 code that it's
               | often slower to use additional instructions.
        
             | wongarsu wrote:
             | And at least the Intel compiler was/is pretty good at
             | producing a single binary that uses whatever features your
             | CPU has available by switching to different code paths
             | depending on the cpuid flags. At least if your CPU is an
             | Intel CPU, it's more conservative with that on AMD CPUs.
        
             | JonChesterfield wrote:
             | VLIW works _really_ well if you have deterministic memory
             | timings, e.g. DSP/risc style architectures, and you're up
             | for writing a complicated compiler.
        
             | ahartmetz wrote:
             | > But if you are talking about Mill, yes it will never
             | work.
             | 
             | Maybe Mill Computing won't pull it off, but why do you
             | think the approach is bad? It seems sufficiently different
             | from Itanium to not have the _exact_ same problems.
        
               | marcosdumay wrote:
               | They don't have a "deliver at all costs" philosophy and
               | they are creating a new and different CPU architecture
               | from scratch, a task where even teams oriented at
               | delivering at all costs tend to almost always fail.
               | 
               | The architecture itself looks very good. If it was built
               | in a way similar to RISC-V, it would probably become very
               | influential. (But then, I'm not sure you can create
               | something that innovative by the same procedures RISC-V
               | was created.)
        
               | imtringued wrote:
               | The architecture looks like a dead end compared to other
               | novel architecture like the Reduceron which reached 33%
               | of the performance of a single core 2 duo processor core
               | while running on an FPGA with only 90MHz without using
               | pipelining or out of order execution. The catch is that
               | the execution model of the Reduceron is graph reduction
               | which basically means lambda calculus/lazy functional
               | programming languages. The Reduceron's raw arithmetic
               | performance isn't better, but it doesn't matter because
               | lazy evaluation is memory intensive, the more memory
               | intensive the algorithm, the better the Reduceron
               | performs, which is very unlike classical C machines like
               | x86 or ARM or RISC-V where memory intensitivity must be
               | avoided at all costs for good performance. Where the
               | Reduceron does a single graph reduction per clock cycle,
               | a C machine has to do it with several sequential
               | instructions so a massive clock rate advantage isn't
               | worth much.
        
               | avianes wrote:
               | Well, first of all, because it shows no results after +10
               | years. There is definitely no indication that it will
               | work someday.
               | 
               | And above all because there are too many choices that are
               | too specific, outdated and too exotic. (e.g. the split-
               | stream encoding is way too exotic)
               | 
               | I work in a small company that makes processors, and I
               | know from experience that developing a processor is a
               | very complicated subject, you have to go step by step
               | (Mill does not). When you come up with a new design/idea,
               | you try to simulate it, test it and implement it. You
               | don't pile up new ideas without getting feedback on them.
        
       | susam wrote:
       | If we are okay to admit that CPU is a compiler (or an
       | interpreter), can I say that self-printing machine code like
       | https://susam.net/blog/self-printing-machine-code.html is a CPU
       | quine?
        
       | lionkor wrote:
       | They both practically translate and optimize, so yeah, that makes
       | sense.
        
       | nodemaker wrote:
       | Compilers all the way down!
        
       | PaulHoule wrote:
       | An advanced interpreter has many features of a compiler.
       | 
       | For instance there is the kind of simple interpreter that I know
       | how to write off the top of my head which evaluates the nodes of
       | an expression tree which is horribly inefficient.
       | 
       | Then there is something like Python which "compiles" code to
       | bytecode which is then interpreted by a "virtual machine". That
       | kind of system admits very complex optimizations about as far you
       | as can imagine, including compiling some of the bytecode all the
       | way to machine code the way PyPy or the JVM does it.
       | 
       | Note most interpretations of the Intel architectures break
       | complex instructions up into RISC-like "micro-ops", which is a
       | bit like bytecode interpretation.
       | 
       | One of the biggest concerns in a modern CPU is that memory
       | accesses are very slow relative to a CPU cycle so you want to be
       | executing a large number of instructions at a time to hide the
       | latency of memory access. Intel's failed Itanium had the compiler
       | try to explicitly schedule this but it didn't work because the
       | compiler can't know ahead of time (for general purpose code) what
       | is in what level of the cache and what isn't -- and in a worse
       | case scenario this can hang up not only one instruction but many
       | other instructions that depend on the result of that instruction,
       | ether because they really depend on the result or because the CPU
       | gets hung up. The CPU, on the other hand, does know, and can be
       | opportunistic about taking advantage of available parallelism.
        
         | DeathArrow wrote:
         | > The CPU, on the other hand, does know, and can be
         | opportunistic about taking advantage of available parallelism.
         | 
         | Isn't Apple M1 much wider than x86?
        
           | PaulHoule wrote:
           | Like ARM, there are many implementations of the x86. Intel
           | has all the various "creeks" and "lakes", AMD has various
           | implementations and there have been others like Cyrix.
           | 
           | If there's a serious problem w/ the x86 architecture it's
           | that the instructions are variable length from 1 to 14 bytes
           | so if you wanted to build a decoder that fetches, say, 5
           | instructions at a time it would have to read 70 bytes. It has
           | to run very quickly, ideally it doesn't consume a lot of
           | power, so it is going to take up a lot of die area and if you
           | want to make it wider still it is a challenge.
           | 
           | Intel and AMD do really well despite this and the long
           | instructions mean you can build all sorts of acceleration
           | into the CPU which can make up for this (some of why the
           | double-pumped AVX512 is effective on AMD's latest is that
           | even when it s getting work down at AVX256 speeds at the
           | core, it is wasting fewer resources dealing with
           | instructions.)
        
             | CalChris wrote:
             | 15 not 14. _The instruction-size limit of 15 bytes still
             | applies to instructions with a REX prefix._
             | 
             | Section 2.2.1, Intel(r) 64 and IA-32 Architectures Software
             | Developer's Manual
             | 
             | Also, long instructions are infrequent, 96%+ are 7 bytes or
             | less. That's static and dynamic is higher.
        
             | jcranmer wrote:
             | > if you wanted to build a decoder that fetches, say, 5
             | instructions at a time it would have to read 70 bytes
             | 
             | No you don't. Look at a block diagram of (say) Skylake: htt
             | ps://en.wikichip.org/wiki/intel/microarchitectures/skylak..
             | .
             | 
             | What you do is extract up to N instructions from a block of
             | memory (in this case, 16 bytes). If there are fewer than N
             | instructions, well, you can only issue as many as you have;
             | if there are more than N instructions, well, you can only
             | issue N instructions that cycle. Note that most
             | instructions are only a few bytes length; I don't have hard
             | data on the average instruction length of an x86-64
             | instruction in practice, but my guess is it's around 3-4
             | bytes.
             | 
             | The hard part about a variable-length ISA, as I understand
             | it (hardware is not my expertise), is that you have to
             | build essentially a mux that can steer from 16 source
             | places to 5 outputs.
        
               | addaon wrote:
               | > The hard part about a variable-length ISA, as I
               | understand it (hardware is not my expertise), is that you
               | have to build essentially a mux that can steer from 16
               | source places to 5 outputs.
               | 
               | It's not just the mux, it's the control signals for the
               | mux. If your first instruction in your 16-byte window is
               | three bytes long, you can't realistically mux bytes 3-15
               | to the second decoder input, because you don't know that
               | it needs to start decoding at byte 3 until /after/ the
               | first instruction has decoded; so your gate delays would
               | be the sum of the five decoders, plus muxing etc, and
               | we're trying to do this at a single cycle.
               | 
               | The alternative is to have 16 decoders, each decoding
               | what an instruction /would/ be if it started at a given
               | byte. These all complete in parallel, but many of them
               | might produce garbage. So we need to find the first five
               | of these that have non-garbage outputs, and /then/ mux
               | those sixteen possible outputs down to five channels.
               | This is doable (and done), but it's a lot more hardware
               | in both decoders and muxing than you might think at
               | first.
               | 
               | Basically: To decode five instructions per cycle from a
               | fixed-instruction-width stream takes five decoders. To
               | decode up to five instructions per cycle from a variable-
               | instruction-width stream takes number-of-possible-starts
               | decoders and a mess of muxing. There really is a cost
               | here.
               | 
               | The Thumb ISA is left as an exercise for the reader.
        
               | bippingchip wrote:
               | Very nice explanation! It gets very complex very
               | quickly... And then there's of course also the fact you
               | never know if your last bytes in the Ifetch you get from
               | the cache is a full instruction or not. You'll need to
               | keep that around until the next line arrives which will
               | have the rest of that instruction.
               | 
               | And then add to that the complexity of speculative and
               | out of order execution: you will want to very early
               | decide, i.e. (pre)decode, where branch instructions are,
               | in order to make sure your branch prediction unit has the
               | right inputs in time, to decide where to fetch the next
               | instructions from.
               | 
               | And after all that, on a branch mispredict earlier on (or
               | pipeline flush for another reason), you might need to
               | throw almost all of that expensively decoded instructions
               | away and start fetching from elsewhere...
               | 
               | CPUs are fun :)
        
               | Joker_vD wrote:
               | > The alternative is to have 16 decoders, each decoding
               | what an instruction /would/ be if it started at a given
               | byte. These all complete in parallel, but many of them
               | might produce garbage. So we need to find the first five
               | of these that have non-garbage outputs, and /then/ mux
               | those sixteen possible outputs down to five channels.
               | 
               | I believe reading somewhere that that's pretty much how
               | more or less recent Intel processors do that.
        
               | PaulHoule wrote:
               | It all depends how much you want to get that last bit of
               | performance and what you are willing to pay for it in
               | terms of power, die area, all that.
               | 
               | And of course every part of it has to be balanced. It
               | makes no sense to decode instructions faster than the
               | system downstream can handle it, particularly if you are
               | wasting resources to do so.
               | 
               | The reason why Intel has so many different
               | implementations of x86 is to meet the needs of different
               | market segments.
        
               | addaon wrote:
               | Yep. And it's worth saying that, contrary to my previous
               | over-simplification, the trade-offs change once you give
               | up on single-cycle instruction decoding. With a longer
               | pipeline, you can do a split into 16 simple, small pre-
               | decoders, that basically just extract the length of the
               | instruction, /then/ mux on the inputs to just five full
               | decoders. It adds a pipeline stage, but it can be lower
               | area for the same sustained performance.
               | 
               | Trade-offs are everywhere. But certainly fixed width
               | instructions, or variable-width-but-trivial-to-determine-
               | length (Thumb before Thumb2, RISC-V compressed) have real
               | advantages.
        
               | Arrath wrote:
               | > The alternative is to have 16 decoders, each decoding
               | what an instruction /would/ be if it started at a given
               | byte. These all complete in parallel, but many of them
               | might produce garbage. So we need to find the first five
               | of these that have non-garbage outputs, and /then/ mux
               | those sixteen possible outputs down to five channels.
               | This is doable (and done), but it's a lot more hardware
               | in both decoders and muxing than you might think at
               | first.
               | 
               | Well that just sounds hideously complex.
        
               | jcranmer wrote:
               | Length decoding is a finite state machine, and the
               | transition function of finite state machines is
               | associative, which means you can actually compile them
               | into a reduction tree to do it in parallel.
               | 
               | I don't think the x86 decoder is actually a particularly
               | complex state machine (I haven't attempted to actually
               | build it), so it's probably overall far less complex than
               | most people assume it is.
        
         | czx4f4bd wrote:
         | Just a tiny nitpick for clarity, I think you mean PyPy rather
         | than "PyPi". :)
         | 
         | PyPI is the Python Package Index.
         | https://en.wikipedia.org/wiki/Python_Package_Index
         | 
         | PyPy is the Python implementation with JIT.
         | https://en.wikipedia.org/wiki/PyPy
         | 
         | (Yes, it is extremely confusing that there are two Python
         | projects with homophonous, nearly-identical names.)
        
           | actionfromafar wrote:
           | Two pretty large, important projects, too. :-D
           | 
           | There's more than one way to name it! No, that's Raku.
        
           | alexjm wrote:
           | To help me keep the spellings straight, I pronounce them as
           | "pie pea eye" and "pie pie" respectively. That's also the
           | PyPI project's preferred pronunciation.
           | 
           | https://pypi.org/help/#pronunciation
        
           | PaulHoule wrote:
           | Thanks for the correction, I fixed it.
        
         | JoeAltmaier wrote:
         | That simple interpreter is inefficient, sort-of. It's 10X
         | slower than compiling to code. It's 10X faster than ordinary
         | interpreters. A compromise solution in some instances.
        
         | PaulDavisThe1st wrote:
         | > An advanced interpreter has many features of a compiler.
         | 
         | There's a historical line from a CS great (I am not sure who)
         | that goes something like:
         | 
         | When you first start writing software, you will not understand
         | the difference between an interpreter and a compiler. After
         | you've been writing software for a certain amount of time, you
         | will never confuse an interpreter and a compiler. But after
         | you've been writing software for a bit longer than that, you
         | will again not understand what the difference between them
         | really is.
        
         | N1H1L wrote:
         | This is a question that has been at the back of my mind for
         | some time. I may be very wrong.
         | 
         | I always thought of an interpreter as a translator, while a
         | compiler was a translator and optimizer.
         | 
         | So my question - can LLMs do this? They are really good at
         | contextualizing and generating code - so why not build a
         | compiler that is basically an LLM?
        
         | Joker_vD wrote:
         | Surprisingly, there is not that much distance between tree-
         | walking evaluator and (stack-oriented-)bytecode emitter: you
         | just have slightly different accumulator (integer vs. list of
         | bytecodes) with slightly different operations on it
         | (arithmetics vs. appending line "add/sub/etc." to the end of
         | list).
         | 
         | Throw in some more of context tracking (e.g. "did the left-hand
         | side turn out to be a constant" or "are we in the (X+Y)+Z
         | situation?" etc.) and you can start doing optimization such as
         | constant folding and expression-tree rebalancing.
         | 
         | Then you can start emitting chunks of assembly instead of
         | bytecode ("iconst X" turns into "push X", "add" turns into "pop
         | eax; pop ecx; add eax, ecx; push eax" etc). Again, with enough
         | context tracking (for example, what's in what registers), you
         | can emit much less stupid assembly.
        
         | wrycoder wrote:
         | Compilers translate a text to (typically) a lower level,
         | optimized, which is stored for later execution. The length of
         | time the output is stored is arbitrary.
         | 
         | Interpreters operate sequentially in time.
         | 
         | They take the compiler output, combine it with parameters from
         | the world outside the cpu, and sequentially produce results
         | that affect the physical world in some way, even if it's just
         | writing a result to memory.
         | 
         | The interpreter may use the compiled text many times.
         | 
         | At some point, it's interpreters all the way down, at first in
         | object code, then microcode. The ALU itself is a sequential
         | hardware interpreter.
        
       | mmphosis wrote:
       | On the surface a "modern" x86 is an interpreter/compiler. Why
       | can't we jit/compile directly to quecto code?
        
       | hardware2win wrote:
       | Writing compiler in normal, high levels langs is non trivial,
       | 
       | I do wonder how this CPU code looks like
        
         | pjmlp wrote:
         | Depends on what you pick.
         | 
         | ML, Lisp, and Logic derived languages are all relatively easy.
         | 
         | Hence why on my degree their were forbidden for compiler
         | assignments, even though we had a strong ML and Prolog set of
         | lectures in programming languages I and II, LP II.
         | 
         | We were supposed to earn the compiler design assignment, from
         | the professor's point of view.
         | 
         | Although the year I took it, it was about the time Java was
         | being introduced, so doing it with Java, SableCC while not as
         | easy wasn't that harder, specially following alongside the
         | Tiger book.
        
           | kazinator wrote:
           | Wow, that is awful. For compiler writing, you should use a
           | good language for that purpose, so that the hard parts of the
           | program are the actual compilation algorithms, not debugging
           | segfaults in a graph structure or whatever, or wasting time
           | on electricity-and-running-water infrastructural code whose
           | existence should be taken for granted.
           | 
           | There is plenty of "cred" to be earned without that; you can
           | still be pulling your hair out debugging a compiler written
           | in Lisp, find years-old bugs in it and so on.
           | 
           | I don't know anything else about your ex-prof other than what
           | you have in the comment, but based on that, my Ouija board's
           | planchette is edging toward "insufferable asshole".
           | 
           | Mental note: be sure not to be that guy if you ever turn
           | professor.
        
             | pjmlp wrote:
             | Unfortunately universities are full of such folks.
             | 
             | Our Physics III was even worse, it was one of those that
             | was proud of hard it was to go through his final semester
             | exam.
             | 
             | Thankfully they tend to be a minority, I also met several
             | that became an a good example of how teaching should be
             | like.
        
       | alfor wrote:
       | The merging of both compiler (cpu and software) is the main
       | reason of the success of Nvidia.
       | 
       | Make the chip simpler and more parallel (way more cores) Make the
       | compiler smarter to better use the capabilities of the hardware.
       | 
       | Watching Jim Keller interview made me realise how much
       | transistors are wasted because the cpu is trying to predict what
       | the code is going to do.
       | 
       | There is an insane amount of complexity in chips trying to make
       | single threaded code fast when what need the most cpu time in our
       | code is usually parallels problem.
       | 
       | Maybe Triton will break that paradigm and will allow diverse
       | parallels hardware to emerge and be used effectively.
        
         | bhawks wrote:
         | The failure of the Itanium highlights the danger of tilting too
         | much complexity into the software / compiler space. It was very
         | difficult to make a compiler which could generate
         | parallelizable machine code and that lead to very disappointing
         | performance for most software.
        
         | bippingchip wrote:
         | But don't underestimate how much 'middleware' there is in
         | Cuda/CuDNN, NCCL etc. A lot of it is not in the compiler, but
         | much more in hand crafted, carefully optimised libraries.
         | 
         | As an example: there are so many low level ways to run a conv2D
         | kernel on a SIMT machine, but CuDNN will pick the best option
         | for you based on the card you have, and the tensor sizes you
         | are using.
        
       | aaronrobert wrote:
       | Interesting point. CPU designers and compiler experts have worked
       | almost the same way to optimize the execution performance.
        
       | spyremeown wrote:
       | Any recommendations of books on compiler optimizations?
        
         | pjmlp wrote:
         | The tiger books have a couple of them, pick your flavour,
         | 
         | https://www.cs.princeton.edu/~appel/modern/
        
         | kaba0 wrote:
         | Engineering a compiler is quite a good read.
        
       | DeathArrow wrote:
       | Every software is a compiler. It takes mouse clicks and keyboard
       | presses and converts them into machine code.
        
         | kaba0 wrote:
         | No, most software is existing machine code, your clicks only
         | "navigate" inside its control flow. They never create any new
         | code.
        
           | mananaysiempre wrote:
           | This is not terribly hard, though,--Forth implementations
           | have long explored[1] the road from emiting a list of VM
           | instructions ("token threading") to emitting a list of VM
           | instruction implementation entry points ("direct threading",
           | although "indirect threading" arguably fits this as well) to
           | emitting a stream of call instructions targeting said entry
           | points ("subroutine threading") to copying the implementation
           | bodies into the stream ("inline threading").
           | 
           | With sufficient dedication, you can even cut out the bodies
           | from the binary the compiler of your high-level
           | implementation language produced, to piggyback on its target
           | support. Gforth[2] among others does this in the land of
           | Forth, but the more well-known implementation is perhaps the
           | dyngen code generator[3] used in Qemu before the switch to
           | TCG in version 0.10.
           | 
           | Generating machine code isn't difficult, and neither is
           | modifying a (low-level) bytecode generator to do it[4].
           | Generaring _good_ machine code is difficult.
           | 
           | [1] http://www.bradrodriguez.com/papers/moving1.htm
           | 
           | [2] https://www.complang.tuwien.ac.at/forth/gforth/Docs-
           | html/Dyn...
           | 
           | [3] https://gitlab.com/qemu-project/qemu/-/blob/v0.9.1/qemu-
           | tech..., rendered as https://web.archive.org/web/200811200119
           | 49if_/http://bellard...
           | 
           | [4] https://github.com/EarlGray/c4/blob/master/JIT.md
        
       | mhh__ wrote:
       | This is kind of gibberish IMO.
       | 
       | A nice introduction to some similarities but the details and
       | constraints are quite different.
       | 
       | Transmeta however...
        
       | gandalfgeek wrote:
       | If you remember the Transmeta chips from the early 2000s they
       | literally were compilers. Took in x86 binaries but JITed them to
       | an internal RISC instruction set.
        
         | vardump wrote:
         | I think that's how pretty much all of the high-performance
         | desktop & server CPUs operate now.
        
         | Pet_Ant wrote:
         | Was it even possible to write Transmeta-native code?
        
           | mschaef wrote:
           | At least if you were Transmeta. Not sure they ever made the
           | ability publicly available. That would've been fairly
           | contrary to their core message.
        
         | HALtheWise wrote:
         | Nvidia's Denver ARM CPUs do the same thing
        
           | CalChris wrote:
           | Written by pretty much the same people.
        
         | wzdd wrote:
         | The x86-to-vliw transformation was implemented in software. See
         | https://en.wikipedia.org/wiki/Transmeta under "code morphing
         | software". Similar to Rosetta.
        
       | nobody0 wrote:
       | and an interpreter
        
       | uticus wrote:
       | > Branch probability analysis | Branch prediction
       | 
       | > Peephole optimisations, idioms | Idioms
       | 
       | From the software side, what is it exactly that makes it so
       | difficult to write a higher-level language that must be
       | optimized, instead of a language that already exposes the
       | optimizations in a friendly way?
       | 
       | ("higher-level language" meaning c, not python or something)
        
         | JonChesterfield wrote:
         | The literal answer is that compilers are really easy to write
         | when the source and destination language are the same and you
         | don't want any optimisation. E.g. write the x64 machine code
         | out as raw bytes and cat is good enough to turn it into x64
         | machine code.
         | 
         | Difficulty increases as the source and target languages become
         | less similar, as more ambitious performance optimisations are
         | attempted, as more comprehensive type/lint/warning style
         | systems are implemented and as performance constraints on the
         | compiler itself tighten.
         | 
         | So a compiler that takes imprecise scribblings, spots errors in
         | them, and emits asymptotically perfect machine code for
         | heterogenous distributed systems in real time is quite
         | dramatically more complicated than cat.
        
         | Pet_Ant wrote:
         | Well the low-level implementations differ from cpu-to-cpu. Even
         | between Itanium releases the width changes. They don't want to
         | get bound to a single implementation as techniques improve and
         | new approaches are found. Otherwise, each time they discover
         | something new they'd have to release a new ISA and backwards
         | compatibility was the most commercially influential aspect of a
         | chip. Now, it used to be that super-computer were made with
         | custom chips, with custom ISAs, but the advantage of mass
         | consumer parts is too high. So in general the decoupling of
         | implementation and programming language allows for enough
         | wiggle room to allow independent evolution without being
         | rigidly coupled.
        
         | avianes wrote:
         | Not sure what is exactly your thought, since the optimizations
         | you quote don't really takes advantage of any exposed
         | optimization feature of the language.
         | 
         | Are your asking why we could not expose optimization feature
         | (e.g. branch hint to replace branch-prediction) in the
         | programming language ?
         | 
         | Are you asking if it's difficult for a compiler to optimize
         | some type of high-level languages ?
         | 
         | Since "higher-level" language is C in your question, what the
         | "language that already exposes the optimizations in a friendly
         | way" ? Are you thinking the CPU uop as a language ?
        
       ___________________________________________________________________
       (page generated 2023-03-23 23:02 UTC)