What language would? Even if you directly write assembly the microcode or pipelining layers are not visible to you, its abstracted in hardware itself. In that sense I think accusing C of not being hardware friendly because these aspects are not exposed to it is nonsense. These are not exposed to even assembly language forget any other higher level language. Regarding parallel programming and GPUs I think a better case could be made for alternative abstractions.
My point wasn't that C wasn't hardware friendly. My point was that it doesn't teach you "how a computer really works". It teaches you a lower-level abstraction than Python does, but it's still an abstraction, and there's a ton of mechanisms at work that you can't see.
Of course. Even below assembly language there are many layers on today's computers. As you noted pipelining, microcode, branch prediction, etc there is a lot more below it. And further below one gets electronics and then quantum theory and so on. So its a matter of what abstraction one can safely ignore I think. And today I think we at least need to go to the level of that sub-assembly stuff if one wants to write anything that does not perform badly. I personally also feel whatever layer one usually works in, one should learn the layer immediately below at the very least. So yes I think we agree.
> And today I think we at least need to go to the level of that sub-assembly stuff if one wants to write anything that does not perform badly
You can write fast software today in assembly, C, C++, Rust, and languages like that. You don't need to go to the microcode level. The reason we have trouble with slow, bloated software today is because people don't do that, and instead use slower languages, like Python or JavaScript, using inefficient algorithms, with lots of potentially unnecessary dependencies that optimize for the general case, and not whatever specific problem the programmer wants to solve (which is often less efficient as well).
By sub-assembly level I meant we must have some knowledge at least of pipelining, branch prediction, caching etc at least regardless of your language choice which is to say its not a completely clean abstraction you can totally ignore and forget about. Layers underneath that are probably not so important.