HNHacker News
TopNewBestAskShowJobs

abainbridge

1,994 karma · joined October 5, 2012

submissionscomments
abainbridge··on You can't fool the optimizer
The examples are fun, but rather than yet another article saying how amazing optimizing compilers are (they are, I already know), I'd probably benefit more from an article explaining when obvious optimizations are missed and what to do about it.

Some boring examples I've just thought of...

eg 1:

    int bar(int num) { return num / 2; }
Doesn't get optimized to a single shift right, because the that won't work if num is negative. In this case we can change the ints to unsigneds to tell the compiler we know the number isn't negative. But it isn't always easy to express to the compiler everything you know about your data and use case. There is an art in knowing what kinds of things you need to tell the compiler in order to unlock optimizations.

eg 2:

    int foo(void) { return strlen("hello"); }
We all know that strlen will return 5, but some compilers don't: https://godbolt.org/z/M7x5qraE6

eg 3:

    int foo(char const *s) {
      if (strlen(s) < 3) return 0;
      if (strcmp(s, "hello") == 0)
        return 1;
      return 0;
    }
This function returns 1 if s is "hello". 0 otherwise. I've added a pointless strlen(). It seems like no compiler is clever enough to remove it. https://godbolt.org/z/Koj65eo5K. I can think of many reasons the compiler isn't able to spot this.
abainbridge··on Macro Splats 2025
FTA, "A Gaussian splat is essentially a bunch of blurry ellipsoids. Each one has a view-dependent color". Does that explain it?
abainbridge··on Los Alamos is capturing images of explosions at 7 millionths of a second
While we're nit-picking the title, what does the "real-time" part mean? How would it be different if it wasn't real-time?

Dictionary.com defines "real-time" like as, "the actual time during which a process or event occurs", eg "along with much of the country, he watched events unfolding in real time on TV". Or in the domain of Computing, "relating to a system in which input data is processed within milliseconds so that it is available virtually immediately as feedback to the process from which it is coming, e.g. a missile guidance system might have "real-time signal processing".

Neither definition work here. It seems like they took a sequence of pictures very quickly, and then, some time later, played them back at an enormously slowed-down rate.

abainbridge··on Link Time Optimizations: New Way to Do Compiler Optimizations
Or academics in 1986: https://dl.acm.org/doi/abs/10.1145/13310.13338

The idea of optimizations running at different stages in the build, with different visibility of the whole program, was discussed in 1979, but the world was so different back then that the discussion seems foreign. https://dl.acm.org/doi/pdf/10.1145/872732.806974

abainbridge··on Dead trees keep surprisingly large amounts of carbon out of atmosphere
> I would have guessed that any kind of forests have quite limited cap how much carbon it could retain in dead wood

The article says, "We found that a forest that's developing toward old-growth condition is accruing more wood in the stream than is being lost through decomposition" and "The effect will continue in coming decades, Keeton said, because many mature New England forests are only about halfway through their long recovery from 19th- and 20th-century clearing for timber and agriculture".

abainbridge··on Biological Miracle – Wood Frog
I skimmed https://en.wikipedia.org/wiki/Sinoatrial_node#Function. Here's my guess at what is going on:

In humans (and I guess many animals), the thing that controls the heart beat is a structure in the heart called the Sinoatrial node. Each cell in the SA node has an ability to generate its own rhythmic electrical impulse. I imagine that when one of these cells thaws out in a Wood frog, it immediately starts producing its rhythmic pulse. It has to get in sync with the rest of the cells in the Sinoatrial node before the heart will beat correctly, so the cells have a mechanism to communicate their rhythm with their neighbours. I guess each cycle, each cell adjusts its phase a little towards the average phase of its neighbours and thus a consensus will be reached.

abainbridge··on I wag, therefore I am: the philosophy of dogs
Yep. When I walk into a room containing my dog and the poo it did on the carpet two hours earlier, it is sorry about what it did.
abainbridge··on Zen 5's 2-ahead branch predictor: how a 30 year old idea allows for new tricks
Another example is Low Density Parity Check Codes [1]. Discovered in 1962 by Robert Gallager but abandoned and forgotten about for decades due to being computationally impractical. It looks like there was a 38 year gap in the literature until rediscovered by David MacKay [2].

The first mainstream use was in 2003. It is now used in WiFi, Ethernet and 5G.

[1] https://en.wikipedia.org/wiki/Low-density_parity-check_code

[2] https://scholar.google.com/scholar?q=%22low+density+parity+c...

abainbridge··on AI speech generator 'reaches human parity' – but it's too dangerous to release
An article about that from 2000. https://www.theregister.com/2000/04/17/playstation_2_exports...

Brilliantly it says:

Register readers with very long memories indeed will recall similar concerns being raised over Sir Clive Sinclair's ZX-81. The fear then was that the sneaky Sovs would try to buy heaps of ZX-81s for their Zilog Z80-A CPUs and might 1KB RAM to upgrade their nuclear missile guidance systems.

abainbridge··on Integrated assembler improvements in LLVM 19
You missed out the input to the LLM, which would presumably be a requirements spec with all behaviour specified in exact detail, including all the tricky corner cases were someone has to think hard about which solution is most useful and least confusing to the customer. Natural language isn't great for expressing such things. A formal notation would be easier. Perhaps something that makes it easy to express if-this-then-that kinds of things. I wonder if a programming language would be good for that.
abainbridge··on GCC's new fortification level: The gains and costs (2022)
Hmmm, yes. I didn't understand what the code did.

Instead of creating those buff0 and buff1 variables before the loop, I should have done:

    for (int i = 0; i < 10; ++i) {
        unsigned a = i;
        unsigned b = i+1;
        msg->a = a;
        msg->b = b;
        SendWord(a);
        SendWord(b);   
    }
That gets rid of the load from the loop. https://godbolt.org/z/xsqWfxKzd
abainbridge··on GCC's new fortification level: The gains and costs (2022)
> strict aliasing allows for optimizations that are actually worthwhile

I don't think there are many sensible, real world examples.

A nice explanation of the optimizations the strict-aliasing rule allows: https://stackoverflow.com/a/99010/66088

The example given is:

    typedef struct Msg {
        unsigned int a;
        unsigned int b;
    } Msg;

    void SendWord(uint32_t);

    int main(void) {
        // Get a 32-bit buffer from the system
        uint32_t* buff = malloc(sizeof(Msg));

        // Alias that buffer through message
        Msg* msg = (Msg*)(buff);

        // Send a bunch of messages
        for (int i = 0; i < 10; ++i) {
            msg->a = i;
            msg->b = i+1;
            SendWord(buff[0]);
            SendWord(buff[1]);
        }
    }
The explanation is: with strict aliasing the compiler doesn't have to think about inserting instructions to reload the contents of buff every iteration of the loop.

The problem I have is that when we re-write the example to use a union, the generated code is the same regardless of whether we pass -fno-strict-aliasing or not. So this isn't a working example of an optimization enabled by strict aliasing. It makes no difference whether I build it with clang or gcc, for x86-64 or arm7. I don't think I did it wrong. We still have a memory load instruction in the loop. See https://godbolt.org/z/9xzq87d1r

Knowing whether a C compiler will make an optimization or not is all but impossible. The simplest and most reliable solution in this case is to do the loop hoisting optimization manually:

        uint32_t buff0 = buff[0];
        unit32_t buff1 = buff[1];
        for (int i = 0; i < 10; ++i) {
            msg->a = i;
            msg->b = i+1;
            SendWord(buff0);
            SendWord(buff1);
        }
Doing so removes the load instruction from the loop. See https://godbolt.org/z/ecGrvb3se

Note 1: The first thing that goes wrong for Stackoverflow example is that the compiler spots that malloc returns uninitialized data, so it can omit the reloading of buff in the loop anyway. In fact it removes the malloc too. Here's clang 18 doing that https://godbolt.org/z/97a8K73ss. I had to replace malloc with an undefined GetBuff() function, so the compiler couldn't assume the returned data was unintialized.

Note 2: Once we're calling GetBuff() instead of malloc(), the compiler has to assume that SendWord(buff[0]) could change buff, and therefore it has to reload it in the loop even with strict-aliasing enabled.

abainbridge··on The tiny chip that powers Montreal subway tickets
https://en.wikipedia.org/wiki/Wafer_backgrinding
abainbridge··on A market mystery: Why do capers come in such tiny jars?
They come in normal aspect ratio jars in the UK. eg https://www.ocado.com/products/m-s-nonpareilles-capers-60903...
abainbridge··on A market mystery: Why do capers come in such tiny jars?
I doubt the surface area matters. The volume of air and therefore oxygen you introduce every time you open the jar is the important factor. I would have thought that oxygen will dissolve in the liquid over a day or so even with a small surface area between the air and the liquid.
abainbridge··on Are animals conscious? New research
Not only that, but my dog has enough theory of mind to ignore a toy/food resource until another dog turns up, at which point she will grab it and parade in front of the other dog to show they can't have it. She knows she can demonstrate dominance by holding the resource that she thinks the other dog wants, even though she doesn't want it herself.
abainbridge··on Optimizing the Particle Life: From 400 to 4M particles
Ah right, yep.
abainbridge··on Optimizing the Particle Life: From 400 to 4M particles
OK, right, that's the clarity of thought I was missing.

But in this case the compiler still misses the optimization with '(double)0.02f'. https://godbolt.org/z/az7819nKM

I think this is because the optimization isn't safe. I wrote a program to find a counter example to your claim that "the optimization should in theory still apply". It found one. Here's the code:

    #include <stdio.h>
    #include <stdlib.h>

    float mul_as_float(float t) {
      t += 0.02f * (float)17;
      return t;
    }

    float mul_as_double(float t) {
      t += (double)0.02f * (float)17;
      return t;
    }

    int main() {
        while (1) {
            unsigned r = rand();
            float t = *((float*)&r);

            float result1 = mul_as_float(t);
            float result2 = mul_as_double(t);
            if (result1 != result2) {
                printf("Counter example when t is %f (0x%x)\n", t, *((unsigned*)&t));
                printf("result1 is %f (0x%x)\n", result1, *((unsigned*)&result1));
                printf("result2 is %f (0x%x)\n", result2, *((unsigned*)&result2));
                return 0;
            }
        }
    }
It outputs:

    Counter example when t is 0.000000 (0x3477d43f)
    result1 is 0.340000 (0x3eae1483)
    result2 is 0.340000 (0x3eae1482)
What do you think?
abainbridge··on Optimizing the Particle Life: From 400 to 4M particles
One optimization for the C code is to put "f" suffixes on the floating point constants. For example convert this line:

    t[i] += 0.02 * (float)j;
to:

    t[i] += 0.02f * (float)j;
I believe this helps because 0.02 is a double and doing double * float and then converting the result to float can produce a different answer to just doing float * float. The compiler has to do the slow version because that's what you asked for.

Adding the -ffast-math switch appears to make no difference. I'm never sure what -ffast-math does exactly.

Minimal case on Godbolt:

https://godbolt.org/z/W18YsnMY5 - without the f

https://godbolt.org/z/oc1s8WKeG - with the f

abainbridge··on What's worked in Computer Science: 1999 vs. 2015 (2015)
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

abainbridge··on What's worked in Computer Science: 1999 vs. 2015 (2015)
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.

abainbridge··on What's worked in Computer Science: 1999 vs. 2015 (2015)
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.

abainbridge··on The KDE desktop gets an overhaul with Plasma 6
Yep. I want to have the same config as everyone else to maximise the chance that I'm using the well tested path of the software.
abainbridge··on New UK record for wind power set today – 21.81 GW between 0900-0930 GMT
Not a direct answer to your questions, but there's some nice data here: https://en.wikipedia.org/wiki/List_of_offshore_wind_farms_in...

Currently we have 14.7 GW of operational off-shore wind gen. Another 13 GW is in the planning stage and 46 GW more in the "early planning" stage.

There's currently 14 GW of on-shore wind gen.

abainbridge··on Show HN: WebGPU Particles Simulation
I'm just seeing a white frame - no noise. Clicking on the white frame doesn't help. (Chrome 119, Windows 10, Intel NUC6i3).
abainbridge··on Astronomers detect almost 100 new extremely metal-poor galaxies
No. I believe a metal poor solar system wouldn't have rocky planets.
abainbridge··on Kolibri OS: fits on a floppy disk, programmed using interrupts
Not if you had a hard drive. I can't find a decent video on YouTube showing how long booting from a hard drive took. Does anyone know of one? Otherwise I might have to get a pile of junk out of my loft and record a video myself. From memory, I'd say my A1200 with IDE disk took about 10 seconds to boot - from power on to sitting idle in the Workbench GUI.

An early Archimedes booted directly into the GUI from ROM and was even faster.

abainbridge··on My Left Kidney
> I don't know where Scott got 30

The text where he says that is a clickable link! https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4635397/

abainbridge··on My Left Kidney
The thing I don't understand is that if the CT scan is more dangerous than having a kidney removed, then surely they'd take the kidney out to see if it was compatible with the recipient rather than give you such a dangerous scan.
abainbridge··on My Left Kidney
The paper he links to [1] broadly agrees with his statement, eg "An estimated 1 in 270 women who underwent a coronary angiography CT at age 40 will develop cancer from that CT (1 in 600 men), compared with an estimated 1 in 8,100 women who had routine head CT at the same age (1 in 11, 080 men)".

1. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4635397/

← PreviousPage 2 of 18Next →