659 karma · joined August 27, 2010
I'm the same user name @gmail.com if you ever have any questions. It's been a while but I'd be happy to try to page things back in for a good cause.
When you code simd it's best to assume the integer divide instruction does not exist. Just an impossibility, if you need to divide ints, rethink your whole program.
Never found a use for this sort of thing once novelty wore off. :/
I see it as something like a personal gradient descent. You're working on a problem, there are solutions down there somewhere, and you can kind of feel the gradient of the tools-and-techniques ground around you. Any way you walk means you're investing time improving some skill or another. So you should go the way that personally feels to you will best get you moving in the direction that you want to go.
For some people it's obvious LLMs are competent coders, getting better, sticking around... and those people should lean into that gradient. For some people what's obvious is nearly the exact opposites of all that, and I'd encourage those people to also follow their gradient/heart/nose down the path of sharpening their personal traditional coding skills. Some people are in a relatively flat area where nothing is obvious, and need to explore and maybe just keep doing their best to hedge with a bit of both.
Sometimes I pop back into a terminal, mkdir, git init, crack my knuckles to do some all-natural hacking and the sadness sets in before the hour is up... "why am I insisting on doing this the long way? I know this project would be better with me in a different role now."
Coding for me has always been a balance of process and ends. Getting done what I wanted done mattered most, but I can't pretend that I didn't also enjoy being the moving parts of that process. And I am most grateful for what I learned by throwing myself over and over against problems I didn't quite know how to solve. There's a satisfaction to doing a thing well that I always love being a part of, still do, anything, even doing the dishes or laundry.
And just recently with Opus I found myself having some really joyously manic days and weeks, making calls, picking tech, designing APIs, insisting on quality, keeping agents spinning. But Fable just kind of came in with "oh, I can do that all for you too. You can relax," and that was both exactly what I wanted and what started making me realize this had all finally caught up to me.
I never wanted to be management, but I can't unsee that I am more effective now playing Fable's boss than I was the last few months as TLM of a squad of Opuses, and that was more effective than just coding myself the way I love.
With Opus I still feel like I'm pair coding and want to get in there and make some changes myself, but working with Fable (even Fable managing Opus agents) had me in a completely different mindset, one where I realized I would just be getting in the way.
Using __attribute__ to tweak calling conventions can often really clean this up, but that's just as obscure and non-portable as the problem it fixes. So you either end up writing weird non-portable code one way or weird non-portable code another... Code working with these types doesn't get to benefit from zero-cost abstraction to the degree we're used to with normal scalar code.
assert(x == 7); // fine
assert(y == NaN); // never true
assert(y != y); // this is what you meant
so this equiv() helper fixes that, assert(equiv(x, 7)); // fine
assert(equiv(y, NaN)); // also fine
now, as far as treating NaNs equivalently, the IEEE 754 float format has a huge number of possible representations of NaN, and if you did something like a bitwise comparison, you might think that 0x7fc00000, 0x7f800001, 0xffc00000, 0x7fc0f00d were all different and not equivalent, but they're all NaNs, and I find that when I'm looking for a NaN, I very rarely care about exactly which one I'm looking at. So checking (x!=x && y!=y) admits any two NaNs as equivalent. _Bool equiv(float x, float y) {
return (x <= y && y <= x)
|| (x != x && y != y);
}
which both handles NaNs sensibly (all NaNs are equivalent) and won't warn about using == on floats. I find it also easy to remember how to write when starting a new project.So I'd bet the issue is either newness of the codebase, as the article suggests, or perhaps that it is harder to schedule the work in 256 bit chunks than 128. It's got to be easier when you've got more than enough NEON q registers to handle the xmms, harder when you've got only exactly enough to pair up for handling ymms?
struct foo {
_Alignas(64) float x,y;
_Alignas(64) int z;
};
_Static_assert(sizeof(struct foo) == 192, "");