Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
What's worked in Computer Science: 1999 vs. 2015 (2015) (danluu.com)
159 points by not_a_boat on March 15, 2024 | hide | past | favorite | 147 comments


I would like to suggest that the classical taxonomy of RISC/CISC dichotomy is basically non-existent nowadays -- namely because both sides have influenced each other. It is well known that CISC has taken a lot of inspirations from RISC designs (such as having a lot more registers in x64), and RISC designs also taken some inspirations from CISC (such as having SIMD/vectorization units). In other words, the line between RISC and CISC has been very fine lately.

Also, at the end of the day, they all turned into μops. If I remember Jim Keller correctly, ARM and x86, they are basically the same in the back nowadays, its just the frontend and their decoding units are different. And that's why he strongly suggested AMD to also adapt Zen design with ARM ISA during his tenure there, oh I think it is called K12.

I think there is another blurry line between superscalar and VLIW architecture, too.


Yep. RISC was interesting when gate budgets for CPU pipelines were seriously limited. It was interesting because before RISC the industry had been merrily spending the gate budget increase on adding lots of use-specific instructions. The RISC people pointed out that if you removed support for all the fancy instructions you had enough gate budget for the ALU to be nicely pipelined, and then you could wind up the clock rate greatly and this was worth much more than the fancy instructions.

For decades now we've had enough gate budget to have nicely pipelined designs with complex instruction sets, so that's what everyone does. RISC solves a problem that no longer exists.


You are not quite right about pipelined design being faster. At least, not without substantial effort.

https://en.wikipedia.org/wiki/R2000_microprocessor

"The R2000 is a 32-bit microprocessor chip set developed by MIPS Computer Systems that implemented the MIPS I instruction set architecture (ISA)..."

"The R2000 was available in 8.3, 12.5 and 15 MHz grades..."

https://en.wikipedia.org/wiki/I386

"The Intel 386, originally released as 80386 and later renamed i386, is a 32-bit microprocessor introduced in 1985..."

"Max. CPU clock rate: 12.5 MHz to 40 MHz"

As you can see, 80386 was released a year earlier than R2000 and was about 1.5 times faster than MIPS implementation from the start.

The critical path is, usually, in addition/subtraction, which should be complete in one cycle in both 80386 and in R2000. To pipeline addition you need a superpipelined CPU, one that has several stages for computation. Even seemingly simple computation of condition codes can make clock cycle 10% longer (SPARC vs MIPS) if your CPU is just simply pipelined.

BTW, some Pentiums did computed 32-bit addition in two cycles, all in name of higher clock frequencies.


Interesting. An R2000 did run programs faster than a 80386, right? This was a few years before my time.

From a quick google now, it looks like the R2000 was about 3x better than the 80386 at Dhrystone MIPS/MHz. I guess an accurate comparison of how the R2000 and 80386 spent they gate budget and what they got in return would involve a lot of detail.

I remember my compsci professor giving us the computer architecture course in about 1997, and he dispaired at how all the clever RISC stuff in the Patterson and Hennessey seemed irrelevant when Intel could just throw money at the implementation (and fab, I guess) and produce competitive chips despite their (allegedly) inferior architecture.


My point is that you cannot get design much faster in terms of clock frequency by just pipelining. Pipeline unrolls state machine and overlaps different executions of the state machines. But the bottleneck, which is addition, is there in all designs and you need additional effort to break it.

(also MIPS has [i]ntelocked [p]ipeline [s]tages - that "IPS" in MIPS; I implemented it, I know - exception in execution should inform other stages about failure)

By the 1997 Intel has already bought Elbrus II design team, lead by Pentkovski [1]. That Pentkovski guy made Elbrus 2 a superscalar CPU with a stack machine front-end. E.g., Elbrus 2 executed stack operations in a superscalar fashion. You can entertain yourself by figuring out how complex or simple can that be.

[1] https://en.wikipedia.org/wiki/Vladimir_Pentkovski

So at the time your professor complained about Intel's inferior architecture being faster, that inferior architecture implementation has a translation unit inside it to translate x86 opcodes into superscalar-ready uops.


I think the Wikipedia page [1] agrees with your main point.

I said pipelining allowed you to increase the clock rate, which isn't the best thing to say.

The wiki page says, "instruction pipelining is a technique for implementing instruction-level parallelism within a single processor. Pipelining attempts to keep every part of the processor busy with some instruction by dividing incoming instructions into a series of sequential steps (the eponymous "pipeline") performed by different processor units with different parts of instructions processed in parallel."

And, "This arrangement lets the CPU complete an instruction on each clock cycle. It is common for even-numbered stages to operate on one edge of the square-wave clock, while odd-numbered stages operate on the other edge. This allows more CPU throughput than a multicycle computer at a given clock rate, but may increase latency due to the added overhead of the pipelining process itself."

[1] https://en.wikipedia.org/wiki/Instruction_pipelining


Addition was not the bottle neck for the 386. It had a FO4 delay of 80+ per clock. An adder is much faster.

Maybe you meant that it was (one, just one!, of many of) the bottle neck(s) in an optimized implementation?


> Addition was not the bottle neck for the 386.

It is a bottleneck for MIPS, SPARC, Alpha and not for 386. How so?


The 386 wastes so many FO4 gate delays on other things. I thought I made that extremely clear?


Can you elaborate on where the delays came from?


And the R2000 was implemented in 2µm and the (early) 386 was implemented in 1.5µm. Double-metal for both. Didn't bother to look up die size.


It's not apples-to-apples to compare raw clock rates between semiconductor processes; Intel's 386 was intially fabbed on 1.5μ then shrunk to 1.0μ process (Intel CHMOS III and IV), whereas MIPS R2000 was 2.0μ, fabless and relied on Sierra, Toshiba, then in 1987 LSI, IDT and other licensees [0][1].

Back in the 1980s/90s/2000s, Intel was consistently a process generation or two ahead of competitors. That was one of their main sources of advantage.

Just imagine if MIPS had been able to fab on Intel process.

[0]: https://www.righto.com/2023/10/intel-386-die-versions.html

[1]: https://en.wikipedia.org/wiki/R2000_microprocessor


And you are also confirm that in order to have higher clock frequency you need more than just pipelining.

Thank you.

I also think that 1.5x difference in clock speeds cannot be directly attributed to the difference between node size (lambda): difference in lambdas 1.3(3)=2.0/1.5 at the introduction of the 80386 and R2000 is noticeably less than 1.47=12.5/8.5.


Smaller transistors are faster, but the relationship between clock frequency and 1/feature size isn't necessarily linear like you're assuming.

https://cs.stackexchange.com/questions/27875/moores-law-and-...


My assumption is that speedup is less than lambda's ratio.


Is there something about RISC that is still makes it better than CISC when it comes to per-watt performance? Seems like nobody has any success making an x86 processor that's as power efficient as ARM or RISC.


> Is there something about RISC that is still makes it better than CISC when it comes to per-watt performance?

CLASSIC CISC was micro-coded (for example, IBM S/360 have feature, you could make your custom microcode for compatibility with your inherited equipment, like IBM-1401 machines or IBM-7XXX series, or for other purposes), and RISC was with pipeline from birth.

Second thing, as I understand, many CISC existed as multiple chips board or even as multiple boards, so have great losses on wires, but RISC appear in 1990s as one die immediately (only external cache added as additional IC), but I could mistake on this.

> nobody has any success making an x86 processor that's as power efficient as ARM or RISC

Rumors said, Intel Atom (essentially CMOS version of Pentium first generations) was very good in mobiles, but ARM far succeed it on software support of huge number of power saving features (modern ARM SOC allows to turn off near any part of chip any time and OS support this), and because of lack of software support, smartphones with Intel have poor time on battery.

More or less official info said, that Intel made bad power conversion circuit, so Atom consumes too much in mode between deep sleep and full speed, but I don't believe them, as this is too obvious mistake for hardware developer.


> CLASSIC CISC was micro-coded

Sometimes. Far from always. Some would have a complicated hardwired state machine. Some would have a complicated hardwired state machine and be pipelined. Some would have microcode and be pipelined (by flowing the microcode bits through the pipeline and of course dropping those that have already been used so less and less microcode bits survive at each stage).


Please give classic CISC examples, which was not microcoded and why you think they classic.

From my opinion, NONE of microprocessors could be considered classic CISC.


The PDP11-20 (the first PDP11) was not microcoded.

The PDP11 is the machine that unix was developed on.


Did you know for what purposes (targets) made mini-computers and why they was limited?


Well, as I see you don't have enough bravery to answer simple question about purpose of mini-computers, so I will.

When computers first appeared, they was big, just because technology limitations made small machines very expensive to use, so scale used to make computations cheaper.

In early 1970s, technology advanced to stage, where become possible to make simplified versions of big computers for some limited tasks, still too expensive for wide use.

Simple illustration, IBM-3033 mainframe with 16M RAM could serve 17500 3270 terminals, and PDP of same time could about few tens (may be 50, I don't know exactly), so mainframes even when was very expensive, but given good cost per workplace.

Known example, PDP used to control one of scientific nuclear reactor. PDP chosen, not because it have best mips/price ratio, but because it was cheapest adequate machine for this task, so is affordable for limited budget.

Very long time, mini machines stay in niche of limited machines, used to avoid much more expensive full-scale mainframes. They used to control industrial automation (CNC), chemical factories and other small things.

Once appeared microcomputers (CPU on one chip), they begin eat mini's space from bottom, when mainframes continue to become more cost effective (more terminals with appearance of cheap modems, etc) and eat mini's space from top.

And in 1990s, when appeared affordable 32-bit microprocessors and became affordable Megabytes of RAM, mini's disappear, because their place was captured by micro's.

To be honest, I just don't know anything we could not name microcomputer now, as even IBM Z mainframes are now have single-chip processor and largest supercomputers are practically clouds of SOCs (NUMA architecture).

And I must admit, I still see PDP's (or VAX's) on enterprises, where they still control old machines from 1990s (they are very reliable even when limited from modern view, but still work).

As I remember, last symmetrical multiprocessor supercomputer was Cray Y-MP, later machines become ccNUMA or just NUMA or even cloud.

https://en.wikipedia.org/wiki/LINPACK

Unix was simplified version of Multics, system considered to run on mainframes (BTW even exists officially certified Unix for mainframes).

You could try mainframes software yourself, it is very affordable now with emulator (sure, be careful about license):

https://en.wikipedia.org/wiki/Hercules_(emulator)

And you will see yourself, how many things borrowed by modern OS's from mainframes.

This is nature, people choose simpler, cheaper thing.


Have there been recent attempts? Maybe it's just, like, speciation, by this point in time.


A great discussion on this: Lex Fridman's interview of David Patterson.


RISC/CISC is near the top of the list of "things emphasized in education that bear little relevance in practice". RISC isn't so much a single coherent design idea as a collection of ideas, some of which have won out (more register files), and some of which haven't (avoid instructions that take multiple clock cycles). The architectures from the days the "debate" was more relevant that have had the most success are the ones which most thoroughly blurred the lines between classical RISC and CISC--namely, Arm and x86.

> I think there is another blurry line between superscalar and VLIW architecture, too.

No, the line is pretty damn sharp. The core idea behind VLIW is that having hardware doing dynamic scheduling (as superscalar does) is silly and the compiler should be responsible for statically scheduling all instructions. The only blur here is that both VLIW and superscalar envision having multiple execution units that can be simultaneously scheduled with work, but who is responsible for doing that scheduling is pretty distinct.


Okay, I will have to review the lecture about VLIW, again: https://www.youtube.com/watch?v=nHHsYp7ZkHQ


> classical taxonomy of RISC/CISC dichotomy is basically non-existent nowadays

After digest information about IBM 360, I decided, we lost CISCs. One of most important feature of 360 was customizable microcode, which you could load on system boot and got effectively different hardware (like with FPGA emulators of Amiga's). It was widely used to emulate old hardware, like IBM 1401 or IBM 7xxx series. But I have not seen this feature in 390 documentation, so looks like their 360 emulation become just software (and with achievements of semiconductors in 1990s it looks like adequate, to switch to software emulation).

I must admit, ARM marketed feature of customized microcode, to add new instructions (they have standardized place in instruction set, named "custom coprocessor instructions", so if you have enough money, you could make special ARM with your additional instructions), but it is nothing if compare to 360.


Did you know for what purposes (targets) made mini-computers and why they was limited?

When computers first appeared, they was big, just because technology limitations made small machines very expensive to use, so scale used to make computations cheaper.

In early 1970s, technology advanced to stage, where become possible to make simplified versions of big computers for some limited tasks, still too expensive for wide use.

Simple illustration, IBM-3033 mainframe with 16MBytes RAM could serve 17500 3270 terminals, and PDP of same time could about few tens (may be 50, I don't know exactly), so mainframes even when was very expensive, but given good cost per workplace.

Known example, PDP used to control one of scientific nuclear reactor. PDP chosen, not because it have best mips/price ratio, but because it was cheapest adequate machine for this task, so is affordable for limited budget.

Very long time, mini machines stay in niche of limited machines, used to avoid much more expensive full-scale mainframes. They used to control industrial automation (CNC), chemical factories and other small things.

Once appeared microcomputers (CPU on one chip), first known on wide market in 1977, they begin eat mini's space from bottom, when mainframes continue to become more cost effective (more terminals with appearance of cheap modems, etc) and eat mini's space from top.

And in 1990s, when appeared affordable 32-bit microprocessors and became affordable Megabytes of RAM, mini's disappear, because their place was captured by micro's.

To be honest, I just don't know anything we could not name microcomputer now, as even IBM Z mainframes are now have single-chip processor and largest supercomputers are practically clouds of SOCs (NUMA architecture).

And I must admit, I still see PDP's (or VAX's) on enterprises, where they still control old machines from 1990s (they are very reliable even when limited from modern view, but still work).

As I remember, last symmetrical multiprocessor supercomputer was Cray Y-MP, later machines become ccNUMA or just NUMA or even cloud.

https://en.wikipedia.org/wiki/LINPACK

Unix was simplified version of Multics, system considered to run on mainframes (BTW even exists officially certified Posix Unix for mainframes).

You could try mainframes software yourself, it is very affordable now with emulator (sure, be careful about license):

https://en.wikipedia.org/wiki/Hercules_(emulator)

And you will see yourself, how many things borrowed by modern OS's from mainframes.

This is nature, people choose simpler, cheaper thing (yes, I don't like x86, my love is 68k).


I don't know if a reduced instruction set can "take inspiration" from a big one, it just becomes a non reduced one.

Also these examples don't feel right for me: x64 has the same number of registers as CISCs traditionally did (eg m68k, z/architecture, vax). 32-bit x86 was just an exceptionally register-starved CISC. And SIMD postdates RISC vs CISC divide for a long time, both schools of architecture got SIMD around the same time.

But the divide has become less relevant because originally instruction set affected chip area a lot, and there were big gains to be had by the quantitative approach of benchmarking compiled apps with different proposed instruction sets and seeing what runs fastest when transistors are spent on hot instructions vs execution engine resources. Nowadays we have more transistors than we know what to do with, and just put in lots of cores that end up sitting idle because of diminishing returns trying to speed up cores with more transistors.


I agree that the line is pretty thin, but would draw it as: fixed-width versus variable-width. I think the M? line of Apple CPUs, with extremely-wide parallel decode, has been a game changer. The performance per watt is really off the charts. That's partly due to integrated RAM and all, but mostly due to microarchitectural changes, which I believe to be a massive step function in superscalar bandwidth (wider decode, huge ROB, huge numbers of ports). It seems like the power-hungry decode stage has been tamed, and I think this is because of fixed-width instructions in arm.


> RISC designs also taken some inspirations from CISC (such as having SIMD/vectorization units)

I think that one went the other way: for example the PlayStation 2 used a MIPS chip with 256-bit SIMD instructions (the TMPR 5900) as well as a dedicated GPU (the so-called “emotion engine”)


With all of the sanctions China is really starting to push RISC forward, challenge ARM, and they are starting to find success. That "No" has absolutely changed to a "Maybe".

https://www.prnewswire.com/news-releases/global-and-china-au...


A 20,000 gate minimal RISC-V RV32E controller CPU isn't going to use μops. In 2024, RISC-V has turned that 2015 No into an unqualified Yes even if the microarchitecture of more complex OOO RISC-V systems resemble the microarchitectures of similarly complex x86 and ARM CPUs.


To the extent that RISC-V is successful it's due to openness/freeness; RISC has nothing to do with it. An open "CISC-V" community would have been just as successful (and people wouldn't gripe about instruction fusion).


I have made a few of those RISC-V CPUs. The minute the "M" instruction set shows up (with division), a macro/micro-op split becomes worth it if you want to minimize gate count or maximize speed.


I'd say that "pure Functional programming" has become a no.

But "Functional programming approach" has been subsumed into existing programming languages, e.g. records in Java. You get most of the benefit of FP while keeping all of the other good stuf from an imperative language.


Definitely agree that mainstream languages are adopting functional features, but records aren't a functional feature.

Records are basic data modeling and something that has been around since the beginning of programming languages, whether procedural or functional. It's one of the bare minimums of having a type system, and Java didn't have this due to the misguided belief that "everything is an object". I think records being added is more of a symptom of that belief weakening.

There are functional features that have made it over to Java which are the things related to functions, i.e. lambdas and such which are a welcome addition.


Java records are object-oriented construct


Maybe. It depends what the definition of "object-oriented" is, which depends what the definition of "object" is. Neither of which has any semblance of agreement among programmers.

Many people would define an object as something that has externally visible behavior and internally hidden _data_. Objects could never be compared to each other for equality, because one could not access the internal data, only its public behavior. However, Java records can be compared for equality which objects would not.

Java records also cannot be extended from. Inheritance is the only uniquely OOP feature, which doesn't apply here either.

So I'm not sure that Java records are an object-oriented construct. First, the precise definition of OO should be established, and then we'll see


OOP is about bundling state and behaviour into units that hide their internal mechanisms by some kind of interface.

Records can have no state - compared to regular classes - so they are an anti-OOP feature.


I would say OOP revolves around the concept of modeling real-world entities or concepts as objects in code. Records encapsulate data fields within an object, providing a way to model real-world entities.


Records existed before and influenced OOP, and they exist outside of OOP today, in imperative and pure functional languages: https://en.wikipedia.org/wiki/Record_%28computer_science%29

Summary by Wikipedia is pretty good:

>Object-oriented programming (OOP) is a programming paradigm based on the concept of objects,[1] which can contain data and code: data in the form of fields (often known as attributes or properties), and code in the form of procedures (often known as methods). In OOP, computer programs are designed by making them out of objects that interact with one another.

But also, from same wikipedia page:

>Attempts to find a consensus definition or theory behind objects have not proven very successful (however, see Abadi & Cardelli, A Theory of Objects[68] for formal definitions of many OOP concepts and constructs), and often diverge widely. For example, some definitions focus on mental activities, and some on program structuring.

https://en.wikipedia.org/wiki/Object-oriented_programming

But I also recommend reading the chapter on objects from "Programming Languages: Application and Interpretation" by Shriram Krishnamurthi. https://www.plai.org/3/2/PLAI%20Version%203.2.2%20electronic...

One sentence summary there is: "Objects — the bundling of data with operations over them — are a generalization of closures."


Very few classes model a real world entity in my experience. Maybe that was the plan but it’s just not the reality of OOP in the industry.


Yeah this is why I always chuckle when people claim that OOP "models the real world".

Oh, because your "FooWidgetController", "FooWidgetService", "FooWidgetRepository" are all real world things?


> I would say OOP revolves around the concept of modeling real-world entities or concepts as objects in code.

This is just data modeling, has nothing to do with OOP.


I'd agree with this and add that pattern matching and functional interfaces are additional examples of tools from the FP toolbox being subsumed into existing programming languages.

Pure functional programming seems tempting. In small projects it can produce beautiful, readable code. In large projects I've only seen it result in messes, and I still haven't decided whether that's due to limitations of functional purity, due to the team (and myself) misusing features that we don't understand, or both.


What mainstream languages have a good suite of FP features though?

If you try to write mostly pure code in Java I’m afraid you’re in for a bad time, despite the (big!) improvements of records and lambdas.

Minimum viable FP starts at OCaml, F#, Scala and Closure, yet none of these are mainstream.


I code in C# and use a ton of LINQ when writing business logic. It's FP-ish enough to avoid logic mistakes. The mediator design pattern, which is kind of bringing another FP paradigm to the OO world, also features heavily.


I think this is the point really, not that mainstream, "general purpose" languages support FP well, but that FP ideas and aspects have been adapted into many of them.


C# LINQ, being a round-about implementation of do-notation, is a pretty advanced FP feature, and beyond most mainstream languages. C# is certainly a step up over Java etc.

However, most developers wouldn’t understand, say, a result monad implemented via LINQ, so you’re still fighting the ecosystem somewhat.


Hold on... Purity and functional programming are different things. Functional programs can be pure but not necessarily.

Functional programming means functions are first class citizens and can be constructed on the fly. Modern python, c++, rust, even java now do this.

Purity is a nice to have (and arguably rusts borrow system enforces a kind of purity).


> Functional programming means functions are first class citizens and can be constructed on the fly.

FP is much more than this one language feature.


Yes, the field of FP is much more, but the core of FP is that. A language doesn't become non-FP simply because it has some imperative abilities, or logic programming builtin, etc.


I’m arguing it’s not FP when you take an OOP language and bolt on lambdas. Lambdas are necessary but not sufficient.

You need expression orientation, immutability by default, persistent collections in the standard library, some way to handle monadic code, etc…


Immutability by default is not a requirement for functional programming (I mean... if it were, Haskell would be obviously not FP since the 'default' entrypoint is very mutable).

Neither are monads. There are entire FP languages without monads for effects (obviously, you can write a monadic interface in them, but it's not part of the idiomatic core). For example, clean uses linear types to control effects and purescript / Idris use a custom effect-system. So no, monads are not a requirement, and even if they are, modern c++ fully supports them, as does rust, javascript, etc. It's very common in javascript to use Array.map() and Array.flat().


> Immutability by default is not a requirement for functional programming (I mean... if it were, Haskell would be obviously not FP since the 'default' entrypoint is very mutable).

I mean the bindings and collections. For example, when you make an array in JS, the default syntax is a mutable list with a mutable binding:

    let xs = [ 1, 2, 3 ]

> Neither are monads. There are entire FP languages without monads for effects (obviously, you can write a monadic interface in them, but it's not part of the idiomatic core).

I should be more precise - there needs to be some way to mange effects. Monads with syntax extensions is simply the most common (Haskell, Scala, F#, Closure macros)

> and even if they are, modern c++ fully supports them, as does rust, javascript, etc. It's very common in javascript to use Array.map() and Array.flat().

JavaScript does not have good monad support. This is why async/await was added as a new language feature. Yeah, I know you can hack together something with generator functions, but it’s hardly idiomatic.

But we’re getting into the weeds here. My point is: I don’t consider a language to support FP when writing functional code in that language leads to lots of friction compared to what is idiomatic.

Have you ever tried FP in Java? It works for some toy thing but then you hit the lack of TCO, or the ridiculously long type names (not inferred) or the pyramid of doom…


Java streams.

java.time

Valhalla even


> e.g. records in Java

Aren't these just C structs?

> You get most of the benefit of FP

FP = Functions. Same output for the same input. No capability to interfere with (or to be interfered with) other functions.


> Aren't these just C structs?

Are C structs guaranteed to be immutable at compile-time?


Hybrid languages are sub-optimal in a lot of ways. One of the joys of functional programming are the guarantees that imperative languages can't offer (primarily immutability).


The moment you have any database or filesystem or remote-service, the hybridization starts anyway.

Sure, technically a single computer's local RAM is being managed with strict guidelines, but that correlates less and less to overall application state and behavior these days.


The promise of FRP was to solve this problem. It makes "state change" a first class object, and organizes your code around it.

The problem is that nobody made an usable FRP system yet. It's not obvious why it's so hard, and everything feels like it should be easy. But everybody just keep failing.


True, but you can isolate side effects.

Knowing that a small collection of functions is not referentially transparent is better than having to deal with any part of the program potentially changing your state.


“Functional style” doesn’t offer the same guarantees, sure, but I wouldn’t underestimate the structural and readability benefits it can offer for certain kinds of tasks.


> Hybrid languages are sub-optimal in a lot of ways.

The real world is messy and stateful.


> Lampson further remarks that to do parallel programming, what you need to do is put all your parallelism into a little box and then have a wizard go write the code in that box. Not much has changed since 2009.

I would like to see a reevaluation of this take with respect to Rust. When we're talking about Rust's safety features, we usually focus on memory safety, because that has the biggest impact on security. But there are lots of memory safe languages, and I think it's actually Rust's thread safety features that are the most unique. (Lots of shared type system machinery between both sets of features.)


Fascinating about how ARM has made tremendous strides in the “high end” market since 2015. I would argue that I would categorize RISC as a “yes” with its absolute dominance on mobile and now moving into data center not to mention all the embedded use cases.


I think the battle between RISC and CISC is overshadowed by the battle between non-x86 and x86. On average are new designs more RISC than CISC? I don't know but that's different from numbers of chips of a certain type sold.

RISC showed what you could do with a clean sheet and the battle has really been about whether we can afford the cost of changing to a new instruction set just because it's better by a bit.


>> by the battle between non-x86 and x86.

68000 -> PowerPC -> x86 -> arm

Apple has been through 4 architectures in 30 years. Given enough money and tyranny (as in "were doing this" kind of leadership, vs committee) its apparently not that terrible.


Add the transition to "32-bit clean" on 68K (and some trouble with caches) + 32-to-64-bit transitions on PPC and x86.


And rumors said, they even considered IBM RS-6000, but pushed to make simplified PowerPC, and IBM had not very good times, so agreed.


I still have to agree with Dan. "If there's any threat to x86, it's ARM, and it's their business model that's a threat, not their ISA."


I would have believed this before the M1, but now I think fixed-width instructions are great for parallel decode, so there's a real threat now which is attributable to RISC.


Fixed-width decode only one of the ideas of "RISC," but not the main one. I would argue that modern ARM is almost as much of a CISC-y abomination as was x86 in 1999. ARM has a lot of instructions that do multiple things and are very non-RISC.

POWER is probably the most RISC-y architecture in use at the high end right now, but it still looks like CISC to the people who originally came up with that idea.


At the moment, x86 is mainly hanging on in legacy spaces because of backward compatibility. Everything new is RISC including Apple's newer Macs. Windows computers still run on x86 because people buy Windows to run legacy code. Playstation and Xbox run on x86 because that makes porting games from Windows more convenient.

My view, even when I was studying RISC V in grad school around 6 years ago, was that RISC is clearly superior technically and this would only become more obvious with Moore's Law dying. I think subsequent events are only confirming this view. The strongest evidence for it is that nobody would even think about making a new CISC architecture that isn't x86.


> At the moment, x86 is mainly hanging on in legacy spaces because of backward compatibility.

x86 platforms also tend to let you run your own code, and are associated with 'proper computers/proper operating systems' where you have full access to your own device.

The vast majority of non-x86 devices are of the 'locked down and dumbed-down' variety. Content consumption devices built around monopolistic App Stores and touch-centric UIs. They tend to be entirely non-upgradable and, increasingly, actively repair-resistant, too.

The market for a 'real computer' may be shrinking, but it's premature to call them 'legacy devices'.

(It'd be nice if serious ARM-based PCs became more of an option though, not just little devices like the Pi, or glued-in-battery Apple products, but fully-upgradeable replacements for a high-end x86 workstation or gaming PC)


> not just little devices like the Pi

What you are dismissing is by-the-book disruptive competition.


> Playstation and Xbox run on x86 because that makes porting games from Windows more convenient.

I expect it helps a lot that AMD can easily provide competitive x86 and GPU cores in one SoC, as they’re already building similar APUs - just with smaller graphics segments?


> Fancy type systems

We are taking steps to this direction. By adding optional typing to dynamic languages Python and JavaScript/TypeScript. And then type checker tools and local programming style guides are making using these maybe less optional, and more mandatory.


Sum types have definitely been making a big splash. I'd also look at how C++ has added concepts and Go has added generics. Local type inference is also commonplace too, even Java has it.


Even C23 has it.


IMO the day python types become mandatory there will be a fork.

It would be such a total betrayal of it's reason for existing that we would have to invent another untyped or duck-typed language again.


For me the primary purpose of TypeScript is to give my editor information about interfaces so I don’t have to do the menial back and forth of accidentally making a typo in a function name, object param, etc.

I find myself using less type hints in Python because the story for REPL driven development is so much better than JavaScript, and that takes most of the pain away.


Giving the editors hints in this case is very expensive.


It is, but it’s worth it in some situations.

It’s so much easier to sit down to an unfamiliar codebase, or to participate in a team of more than three or four serious contributors, when typescript is there to guide you.

I never would have guessed that that would be the benefit that won me over, but it absolutely has, all it took was a two year / six people project to completely sell me on typescript.


I find that even when type hints are made "mandatory" using Mypy's strict mode, having a dynamically typed language underneath that allows you to cheat using Any or cast() where necessary makes writing Python feel much less cumbersome than writing in actual statically typed languages.

Presumably, a Python with "mandatory" type hints would still allow you to cheat in those same ways.


I mean, your company or your project may require you to write type hints and use a type checker tool. Not that Python the language makes typing mandatory.


nagware like Typescript have turned type bolt-ons into a religion almost. It has its place but really gets in the way in others. Hence, the reason untyped languages exist in the first place.


Those would be considered basic type systems. For "fancy", you gotta dive deeper into the lambda cube (tho generics I guess in 1999 would be fancy and one step in).


The borrow-checker is pretty fancy.


The author thinks that Formal Methods are a Maybe because chipmakers while Fancy type systems are a No. I think the bar is pretty high for Type systems (in the mind of the author).


Good 'jcranmer on the RISC-CISC thing:

https://news.ycombinator.com/item?id=39481940


I just want people to start doing interesting things with stack machines again. Like, hardware ones, not VMs (plenty of interesting stuff happening there). But that's the concatenative language lover in me wanting to see more interesting things happen, not some zealot claiming we all should switch to it.


I guess from some sense, all web apps and all GUI apps using the GPU are using parallelism. That's almost everything. Those are both leveraging shared-nothing type architectures so you can think in a single thread and apply it to concurrent work loads for parallelism.

Does that not count? What would satisfy this category?


I think the dream of parallelism in 1999 was that CPUs aren't going to get much faster in terms of clock cycles, so how will algorithms run on more data. This is a bit dumbed-down, but things like sorting in parallel.

It turns out that local data didn't quite scale like that, we got more ram and SSDs, and that coordination usually makes small-scale parallel algorithms prohibitively expensive. Where parallelism does work today is some flavor of SIMD like vector instructions, parallel matrix multiplication on a GPU, or map-reduce.


    Yes                      Maybe
    Firefox Reader Mode      CSS


Also, Reading Mode in the sidebar of Chrome.

The days of square monitors and wall-to-wall text have been over for a while.


Interesting how much has changed since 2015. Apple's M chips have made RISC is a clear yes now. Rust has a pretty fancy type system. Not Haskell-fancy but still. Functional programming is pretty much an expected feature now.


> Apple's M chips have made RISC is a clear yes now.

ARM is not a pure RISC architecture (even though its instruction set is somewhat inspired by those ideas behind RISC that stood the test of time).


What counts as "pure RISC"?


Ask the Scottish.

Elsewhere in the comment section is describe the question isn’t RISC/CISC, it’s x86/Nonx86. And far more interesting since those lines are still fairly well established.


Good question. Now things are complicated. When all beginning, CISC CPUs was not one chip but board or even cabinet (like IBM S/360), and they featured customizable microcode, so you could even load different microcode on different CPUs in system.

As I know, very powerful feature of S/360 series was to supply custom microcode to make machine compatible with older IBM hardware, like 1401 series or 7xxx series (or to make your own architecture if you wish and if you have enough money).

I have not hear about customizable microcode in RISC (to be honest, I hear, it exists in ARM, but it is rare used option, if compare with IBM 360).


What can you do in Haskell that you can’t do in Rust with macros and elbow grease?


The phone networks and basic infrastructure for the internet in many countries wouldn’t work without Erlang. Which is functional… but maybe that doesn’t count?


On the other hand, the banking infrastructure in many countries wouldn't work without COBOL, scientific research wouldn't work without MATLAB, and healthcare wouldn't work without MUMPS. Many languages and paradigms, good and bad, end up entrenched within an industry.


> COBOL

> MATLAB

> MUMPS

One of each uglier than the one before. But:

Is there something we can learn from these examples? Are there good reasons for these languages being adopted? And are the Racket designers with their approach of "a language to define interoperable DSLs" up to something?


I think programming languages are more like spoken languages than we give them credit for. Their design is more intentional, but the processes by which they spread, compete, and evolve is similarly difficult to pin down.


You forget FORTRAN (was very popular for scientific computing, and nearest neighbor with COBOL in S/360 environment) :)))


> That Intel ceded the low end of the market might seem ironic considering Intel's origins, but they've always been aggressive about moving upmarket

Will see. Intel after 2023 is not like before 2023, when it lost its dominance to AMD and partially to Nvidia and ARM (Apple-M2).

Now lowest end CPUs become RISC-V and ARM pushing to become one of leaders.

x86 is strong, but who knows, how long it could dominate under pressure.

And if we count not desktops but all personal devices, ARM is already won (on just smartphones, now more ARM CPUs than people on Earth, and Data Centers share of ARM CPUs growing).

Only one final thing I could copypaste from "X-files" - "truth is out of there".


After digest information about IBM 360, I decided, we lost CISCs. One of most important feature of 360 was customizable microcode, which you could load on system boot and got effectively different hardware (like with FPGA emulators of Amiga's). It was widely used to emulate old hardware, like IBM 1401 or IBM 7xxx series. But I have not seen this feature in 390 documentation, so looks like their 360 emulation become just software (and with achievements of semiconductors in 1990s it looks like adequate, to switch to software emulation).

This was not only feature of 360th, for example Xerox Alto, also have documented feature to alter microcode when need (as I hear, they have special framework to work with it, just like we now work with Assembler when need), and I hear rumors that something similar was shipped with DEC mini-computers, but for micro-computers, this feature practically disappeared.

Even when we have "microcode update" feature in many modern CPUs, but it is usually undocumented feature, to which nobody have access outside CPU manufacturers (only could upload encrypted binary, supplied by manufacturer to fix bugs). As I said, in 360th, this was documented standard feature, you could use if need.

I must admit, ARM marketed feature of customized microcode, to add new instructions (they have standardized place in instruction set, named "custom coprocessor instructions", so if you have enough money, you could make special ARM with your additional instructions, you could even order some additions on die), but it is nothing if compare to 360.

And I could tell from FPGA cooking, not all things implemented in FPGAs as hardware logic pipelines. When speed accepting, many people using in FPGA practically microcode engines (very common thing is 1-bit CPU, which is very similar to CISC microcode engine, and programmed in Assembler, very similar to early 8-bits; some people prefer full-featured CPU, like 8048 or even more).


Fancy type systems have come a long way since then. (TypeScript, for example.)


TS really stands out as amazing. It’s realized a lot of the promise of strong typing.


I agree that TypeScript is quite amazing. And that it's indeed improved the programs created that run in the browser or on `node`.

However, I wanted to point out something that I think often gets overlooked when folks talk about TypeScript. I'd argue that TS has realized it for the web programming masses, who usually don't have any computer science education and thus are unaware of computing fundamentals such as types. TS hasn't realized the promise of strong typing only because it has been quite late to the game, so to speak.

I do think I understand where you're coming from. Web programmers are the largest group of programming-related professionals. Bringing CS wins to this large group absolutely does bring the largest gains and impact to industry.

There have been many programming languages created decades before TypeScript that have realized the promise of strong typing. Unfortunately, I think this road took too long. Collectively, people have known about these ideas since John Backus's 1977 Turing Award Lecture [1] -- "Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs"

Anyways, I digress. Hopefully this was insightful! Have a great day :)

[1] https://dl.acm.org/doi/pdf/10.1145/359576.359579



How so? It looks a lot like a less-rich Java, whose type system has existed for literally decades. In fact, the generics syntax and type erasure was directly influenced by Java.


Typescript has far more powerful type constructs than Java.


Such as?



Quite nifty, but I still wouldn't call it far more powerful. Take a look at https://checkerframework.org/ for example.


I haven’t used Java in many years, but TypeScript’s structural types give it a different flavor than I remember from Java. Unlike in Java, most of the types I define aren’t classes or interfaces. It’s just data that has an expected shape.

Check out the design of Zod, for example. I have a bunch of Zod types for the validation of incoming JSON messages. This automatically generates the corresponding TypeScript types through the magic of type inference.

It’s quite easy to create discriminated unions, which are just structs where one field has a fixed value.


In functional programming, a type is just a function that returns a list of possible values. It’s not a class.


> In functional programming, a type is just a function that returns a list of possible values

Its literally not; there may be a language which does this or something close (actually, I’ve seen narrow, purpose-focussed relational languages where this is the case, and all types are enumerable), but it's definitely not generally the case in functional languages.


Conceptually, you can think of a type as a set of values, but no, it’s not how static type-checking is implemented. Some sets are very large (consider the set of all JSON values) and enumerating them isn’t useful.


Tho Typescript does have structural types, mapped types, union types, optional types, type aliases..... Bunch of useful type features.


More like indirectly influenced by Java by way of C# (Anders Hejlsberg designed both C# and TS)


I disagree. The language was probably more inspired by C#, which is itself inspired by Java. Type erasure is just part of transpiling to JS.


TS has a powerful type system that behaves in strange and counter intuitive ways, particular for people coming from JS. It doesn’t even have a spec, really. I would prefer something less powerful but more predictable, personally.


The link to "Microsoft's driver verification tool", which "has probably had more impact than all formal chip design tools combined", is broken. Does anyone know which tool this meant?




Related:

What's worked in Computer Science (2015) - https://news.ycombinator.com/item?id=15796515 - Nov 2017 (62 comments)

What's Worked in Computer Science - https://news.ycombinator.com/item?id=10623600 - Nov 2015 (63 comments)


Do GPUs and TPUs for AI count towards parallelism?


I don't think so, they still tend to fall into the "Lampson further remarks that to do parallel programming, what you need to do is put all your parallelism into a little box and then have a wizard go write the code in that box." statment, for the most part.


What could be a different case is Clojure. But I am not sure, and the performance characteristics of Clojure make it well-suited for server-style concurrency, but not so much for high-performance parallelism.


What is "capabilities" supposed to mean?



Funny how in the 90s security was an enterprise feature and now better security and cryptography than we had in the 90s is on every $15 android phone.


Thank you :)


It means that the permission (capability) to do something is encapsulated into an unforgeable bearer instrument that can be stored, passed around and so on. An open file handle (descriptor on UNIX) is a capability, because if you have it you can use it to read and maybe write to the file, and because you can send it to another process, at which point that process also has the capability to read and write that file.

Capabilities are one of those concepts that's a bit like FP or RISC. It sounds elegant but in the real world experience is mixed, so it's rare for a system to rely on it purely. Most real security systems today are built on semi-static permissions granted to domains defined by some third party identity system. Capabilities do get used, but mostly in the sandbox context and mostly as a detail.

So I think Dan is not quite correct that mobile platforms use capabilities. Users assign permissions to specific apps semi-statically there. The lowest levels of the OS may use a small set of capabilities as part of the implementation, but granted permissions are not generally easy to send around to other apps.


> What is "capabilities" supposed to mean?

"Is this app allowed to read your contacts?"


"Fancy type systems" What about TypeScript? I've literally implemented snake game using types alone, it's quite powerful.


Fancy Type Systems is indeed vague, but I’d disagree with No in 2024. They are slowly winning. Definitely a Maybe to a Yes. E.g. Rust is hugely popular/successful and has brought a much more sophisticated type system to system programming.


Neural networks:

1999 - No

2015 - Not really

2024 - Yes?


I'd say 2005 to 2010 is probably more probably more appropriate for not really. By 2015, neural networks were already a really hot research topic. Just off the top of my head, the seq2seq paper was published in 2014 and U-Net and ResNet were published in 2015.


This is eliding most of the history of neural networks as a hot reasearch topics. Since the late 50's early 1960s they've had several resurgences in interest, e.g. 80s RNNs, 90s stuff around several centers. Hell people were doing interesting things with them commercially in the 90's. The late 90s and early 00's had a lot of other interest (kernel methods, SVMs) but NN folks kept plugging, and the hardware to hit the next level was just around the corner.

The resurgence you're noting are papers with a 10 year tail before them (hell, most of the deep concepts were initiated decades before but lacked both the data sources and efficient hardware to really work them out).

This stuff has a long and deeply connected history.


I wish this was updated for 2024

His RISC being “No” most would agree is somewhat incorrect though it seemed correct back in 2015.

But it kinda goes to show how these yes/maybe/no things can evolve unexpectedly over time and not be to taken as gospel that will stand the test of time.


Formal Methods was for people who didn't want to write any code.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: