[HN Gopher] A Case for Asynchronous Computer Architecture
       ___________________________________________________________________
        
       A Case for Asynchronous Computer Architecture
        
       Author : mahami
       Score  : 29 points
       Date   : 2021-11-28 06:12 UTC (2 days ago)
        
 (HTM) web link (avlsi.csl.yale.edu)
 (TXT) w3m dump (avlsi.csl.yale.edu)
        
       | boibombeiro wrote:
       | Memory cells are the thing that uses the vast majority of power
       | in a CPU. And they are used everywhere, cache, uOP cache, BTB,
       | etc.
       | 
       | Async CPU solved a problem that would have marginal benefit in a
       | metric we care about
       | 
       | Also, I imagine, they would need to be implemented assuming the
       | worst timing delay from the processes. They can't be binned like
       | modern CPUs.
        
         | IshKebab wrote:
         | That doesn't sound right? Dynamic power is consumed by toggling
         | wires, and memory cells are going to be one of the places where
         | toggling is rare because you can't access all memory all the
         | time.
         | 
         | Am I missing something?
        
           | hypertele-Xii wrote:
           | Volatile memory consumes constant power to remember its
           | value. Processing circuits only consume power when activated.
           | And it's difficult to get the memory bandwidth saturated in a
           | way that keeps all circuits busy. Computers do work in
           | bursts; Then they wait for data. And practically all
           | classical computer science data structures trash cache, like
           | linked lists and OOP in general.
        
       | bob1029 wrote:
       | Having a common clock reference (per core) is essential for
       | reducing latency between components. If you have to poll or await
       | some other component arbitrarily, there will necessarily be extra
       | overhead and delays in these areas. There will also need to be
       | extra logic area dedicated to these activities. Make no mistake,
       | just because there's no central clock, doesnt mean you are
       | magically off the hook. You still need to logically serialize the
       | instruction stream(s).
       | 
       | Even for low power applications, you would probably use less
       | battery getting the work done quickly in a clocked CPU and then
       | falling back to a lower power state ASAP. Allowing the pipeline
       | effects to take hold in a modern clocked CPU should quickly
       | offset any relative overhead. Heterogenous compute architecture
       | is also an excellent and proven approach.
       | 
       | Certainly, there are many things that happen in a CPU that should
       | not necessarily be bound by a synchronous clock domain (e.g.
       | ripple adder). But, for these areas where async cpu a clear win,
       | would we actually see any gains in practice using real software?
       | Feels like there's a lot of other strategic factors that wash out
       | any specific wins.
        
         | saurik wrote:
         | My understanding--which seems to coincide with this article and
         | which Wikipedia seems to agree with (not that that necessarily
         | means much for this)--is that in an asynchronous circuit
         | latency would be lower, not higher, as the clock is required to
         | wait for the worst-case performance while a clock-less system
         | can proceed immediately once only the required inputs have
         | arrived (or even attempt to speculate on partial inputs,
         | something which would offer no value if you would have to end
         | up waiting for the next tick anyway).
        
           | blagie wrote:
           | This is correct. It happens at multiple levels.
           | Oversimplified:
           | 
           | * An async add operation takes variable time based on the
           | number of carries, whereas a sync one is set to the worst-
           | case.
           | 
           | * The clock for an ALU is set for the worst-case even when
           | doing something faster (e.g. an ADD rather than a NAND)
           | 
           | * If you have multiple logic stages handled in one clock
           | cycle, the problem is compounded. The clock is set by the
           | slowest stage for all components in the system.
           | 
           | * If your system is doing nothing, you're still clocking it.
           | Clocks are adjusted, but not at a nanosecond-by-nanosecond
           | level.
           | 
           | All-in-all async gives a nice power boost and a nice
           | performance boost (not enough of a boost to displace an
           | entrenched ecosystem, mind you, but a nice boost
           | nonetheless).
        
         | baybal2 wrote:
         | Clock distribution eats a lot of power at gigahertz
         | frequencies, and a lot of gates.
         | 
         | > If you have to poll or await some other component
         | arbitrarily, there will necessarily be extra overhead and
         | delays in these areas.
         | 
         | You don't poll. You have a lot of small input-clocked domains
         | which work at a speed with which data comes.
        
       | fivelessminutes wrote:
       | This seems to be from 20 years ago, the most recent citation was
       | from 2000 and it describes a MIPS chip built on a 1998 process.
        
         | mikeurbach wrote:
         | We had the pleasure of hosting Dr. Manohar at a CIRCT weekly
         | discussion session earlier this year. He presented much more
         | recent work if anyone is interested. The talk and discussion
         | was recorded here:
         | https://sifive.zoom.us/rec/play/Bg99_niHh9OG_8uE_nhaz6otxvA0...
         | 
         | EDIT: talk begins around 7 minutes.
        
         | matja wrote:
         | And not even a mention of AMULET
         | (https://en.wikipedia.org/wiki/AMULET_microprocessor)
        
           | nickdothutton wrote:
           | Came here to say this.
        
         | mahami wrote:
         | Yes, but I thought that it could be interesting to look at
         | research on the topic from 20 years ago to compare it with
         | present progress.
        
           | dgellow wrote:
           | Could you add the publication year in the title of your
           | submission?
        
           | blagie wrote:
           | Asynchronous would work better, but we're unlikely to get
           | there -- too big a change.
           | 
           | It's like:
           | 
           | * having ECC everywhere
           | 
           | * having a single display standard (as opposed to
           | HDMI/DisplayPort/USB-C/DVI/VGA/...)
           | 
           | * some kind of architecture where a single bad expansion card
           | (USB, PCIe, etc.) can't crash a whole computer
           | 
           | ... and so on
           | 
           | On one hand, no brainer. On the other hand, it hasn't
           | happened.
           | 
           | NVidia is breaking ground on the move to SIMD/MIMD-style
           | architectures, as predicted at the same time, and only
           | because it gives a 30x boost in performance. Async will
           | probably net us a 50% performance boost or something.
        
       | Const-me wrote:
       | Modern clocked processors don't account for worst-case timings.
       | Instead, instructions take variable count of clock cycles to
       | complete.
       | 
       | In some sense they're already asynchronous, despite clocked.
        
         | twoodfin wrote:
         | Can you write more about this or provide some examples? Of
         | course, memory access has had variable timing "forever", but
         | the idea that other functional units can vary their timings for
         | instructions is new to me.
        
           | Const-me wrote:
           | A good source of that info is https://www.uops.info/
           | 
           | For instance, on my CPU which is AMD Zen 3, the idiv
           | instruction (it computes integer division and modulo) takes
           | between 9 and 19 cycles for 64-bit version:
           | https://www.uops.info/html-instr/IDIV_R64.html#ZEN3 That's
           | for the operand already in a register i.e. no RAM access
           | involved.
           | 
           | Whether it takes 9 cycles, 19 cycles, or something in
           | between, depends on the arguments of the instruction, i.e. on
           | the numbers being divided.
           | 
           | Same applies to quite a few other instructions: floating
           | point divisions (divps, divpd), floating point square root
           | (sqrtps, sqrtpd), even 64-bit integer multiplication (imul).
           | 
           | It's not just the math. Jumps, branches and function calls
           | take very different count of cycles depending mostly on two
           | things: predicted or not, and the state of micro-ops cache at
           | the target address. Albeit these effects are very hard to
           | measure reliably, depends on the code too much, probably for
           | this reason uops.info doesn't have latency figures for
           | jmp/call/etc.
        
         | nynx wrote:
         | Certainly, modern CPUs are pipelined, but each clock cycle is
         | still the worse-case time for all steps in the pipeline.
        
           | Const-me wrote:
           | > each clock cycle is still the worse-case time for all steps
           | in the pipeline
           | 
           | The pipeline takes variable count of clocks to complete an
           | instruction. The number depends on the instruction, input
           | data of the instruction, and quite a few other things. In
           | some exotic cases it even depends on power state, e.g. some
           | Intel CPUs took ~20k cycles to power on their AVX pieces,
           | during that window AVX instructions are much slower.
           | 
           | If for any reason the pipeline is unable to deliver the
           | result by the end of the clock, CPUs don't delay the clock,
           | they continue running the clock. You simply gonna get the
           | result on some later clock cycle.
        
             | nynx wrote:
             | That's exactly what I mean.
        
       | IshKebab wrote:
       | Does this mean that the chip isn't clocked? Doesn't that give you
       | a complete metastability nightmare? How does it work?
        
         | blagie wrote:
         | No metastability nightmare.
         | 
         | One way to do this is to have each component have an output
         | clock, which raises when it's output is known stable. If an
         | adder has no carries, that takes 1ns. If it has each possible
         | carry, it takes 2ns. You have a second clock propagating
         | backwards to know when the next stage is ready for it's next
         | input.
         | 
         | You still have timing. It's just set to when a component is
         | ready with output, or ready to receive input.
         | 
         | Everything goes faster and uses less power.
        
       | baybal2 wrote:
       | I will raise an import distinction: asynchronous logic != dynamic
       | logic.
       | 
       | There can be dynamic synchronous logic, and vice versa.
       | 
       | Dynamic vs. static determines whether the circuit as such needs
       | to be driven by any constant pacing input, whether embedded
       | clock, or external clock, vs. not needing it to arrive to a
       | settled state (to latch.)
       | 
       | If you are to speak strictly, asynchronous vs. synchronous
       | determines whether that pacing input is external, or recovered
       | from input.
        
       ___________________________________________________________________
       (page generated 2021-11-30 23:01 UTC)