2,026 karma · joined October 5, 2012
I think this paper's abstract claims that wooden debris from the landslide has been dated to 5000 years older than the Sumerian tablet: https://www.researchgate.net/publication/329153343_The_produ...
I know. I mainly just wanted to link that video because it is awesome.
The article does explain how the Inca did it - only the front edges are tight fitting. The gaps between the inside surfaces are filled with mortar. They sat the stone where it was to be placed, but with the front edge raised up by resting on some spacers, then just incrementally improved the fit of the edge and re-tried the fit. I'd have still thought that was impossible without seeing something like the video I linked - my intuition of what can be achieved with hammer and chisel was wrong.
Similarly astonishing to me is that Michelanglo's David was carved from a single piece of marble with a hammer and chisel. I mean, just look at it: https://en.wikipedia.org/wiki/David_(Michelangelo)
> (also note you got the endianness wrong in your hand-optimized version) Doh :-)
int foo(char const *s) {
if (s[0] == 'h' && s[1] == 'e' && s[2] == 'l' && s[3] == 'l')
return 1;
return 0;
}
The outputs 4 cmp instructions here, even though I'd have thought 1 was sufficient. https://godbolt.org/z/hqMnbrnKeIs the best way to think of optimizing compilers, "I wonder if someone hand wrote a rule for the optimizer that fits this case"?
BTW, the case of it not optimizing was MSVC targetting Windows (which doesn't support LD_PRELOAD, but maybe has something similar?).
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/M7x5qraE6eg 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.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.
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
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".
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.
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...
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.
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/xsqWfxKzdI 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/ecGrvb3seNote 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.