5,671 karma · joined December 22, 2019
To the legal search example, suppose the police frequently stop by your house to discuss neighborhood gremlins. If they happened to accidentally see the boxes of evidence you'd be in trouble. You're allowed to destroy them though, and you might have a habit of destroying evidence for each of these gremlin chats. Doing so is legal.
Later, the police show up with a warrant (your example). If you think you're doing your normal gremlin evidence destroying and not blocking that warrant, destroying that evidence is still legal even with the police waiting on your porch to legally, forcibly search your house. The _intent_ behind your actions, at least in this case, is a core component of the crime.
Mind you, nobody will believe you, so you'll still have a hard time in court proving it (this is mildly in your favour because it's actually the prosecution's duty to prove your intent rather than your duty to prove lack of intent, but they're not exactly going to have a hard time convincing a jury that when you destroyed a bunch of evidence with police on your porch with a warrant it was because of that warrant), but it's still legal.
"Multiprocessing" (multiple CPU cores independently executing and only able to coordinate via some message-passing system -- a definition which encompasses both multi-core CPUs and horizontally scaled distributed systems, contrasting slightly with the normal definition) is challenging for a few reasons.
Firstly, the details are an open math question, but I'll blindly state that some problems aren't amenable to parallelization. I.e., no algorithm can meaningfully improve performance via parallelization no matter the implementation. Think through how you would more quickly compute hash(hash(hash(hash(...)))) for example. The serial dependency makes things challenging. That isn't too dissimilar to the problem TB faces.
Secondly, message passing is expensive. If the only way two CPU cores can coordinate is through a multi-level cache, at best you're incurring ~tens of nanoseconds of latency per message. Contrast that with a base rate of 512 bytes processed per nanosecond with enough attention to detail on typical modern server hardware (4 pipelined AVX512 instructions at 2GHz). Messages are several orders of magnitude worse than your normal work, so if you need very many of them then you're hosed from a performance perspective (worse with longer delays, like networked computers). Even very parallelizable problems at an abstract level can suffer performance losses by trying to add even one extra core. This blog post [0] doesn't perfectly capture the idea, but it's close (and a fun read regardless).
Thirdly, message passing is an insanely complicated programming abstraction to reason about. My first two points were more about what TB was saying -- realities of modern hardware -- but the programmer experience is important too (even if you don't believe that post-2020, the LLM experience doesn't differ much from the human experience; bad code begets more bad code, slowly). The core mechanism for correctness in most software is being able to reason about "this thing is true, therefore that thing is true" and iterating. You rely on invariants like "this is sorted" to build other working theories. The invariants in multiprocessing code are much more nebulous and less amenable to accidental discovery, also less amenable to being able to build or compose them into other stronger invariants as you add code. The main reason for that is that you know almost nothing about the relative order of those messages with respect to each processer's view of which instructions happened when (and for purely multi-core "multiprocessing" the story is even worse; while my description of message-passing being the core primitive is correct, that's not what's exposed to you as a programmer, and different memory models can have even weirder interleavings than your code would naively suggest -- i.e., your code is being decomposed into smaller subunits than even a single assembly instruction, and the message passing happens at that level). The combinatorial explosion (an exponential explosion really, but big numbers either way) of states you might be interacting with makes it very difficult to understand _anything_ about the system you're examining. That's why you see a handful of primitives used over and over -- if you can decompose your problem into a parallel map plus an associative reduce then you can probably figure out some way to make it better through parallelization (not always, especially if the framework is too generic, see the linked blog post [0] if you weren't enticed to read it previously). If you can't decompose it into know primitives then it's an open research problem every time.
The crux of that third point (and we could definitely add more explanation and additional problems) is that there's a huge cost to multiprocessing. You have to be buying something substantial to even want to reach for it, else you have to be in one of the "easy" problem spaces where somebody else has done the hard work (e.g., stateless webservers).
TB isn't that. Their whole raison d'être is state management, and not in a way that's easily amenable to parallelization.
[0] https://adamdrake.com/command-line-tools-can-be-235x-faster-...
But my target is to waffle around 20% or so on average.
No, obviously that's not what they're saying. There must be some reasonable interpretation then, right? Let's look at the chat thread and see what we can find.
> be very cautious about evil uses of seemingly safe technology when developing initial capabilities
>> that's super hard since most things can be repurposed
>>> (your other comment) it's actually easy though, just look at how we could repurpose these death machines
>>>> (their comment) but...that's wildly inefficient
The subtext to their answer is going an entire opposite direction to your rant. People are saying that turning anything into a killing machine is easy, and their comment is saying that doing so is sometimes Pareto-suboptimal, and so wildly so that no semi-rational-at-least-a-little-bit-sometimes military is going to bother trying to weaponize your silicone basting brush or what have you.
They're not saying that you should mass-murder people, as you, yourself speculated.
1. For every natural, you can find a path of that length.
2. Therefore (nonstandard chicanery), for every hypernatural you can find a hyperpath of that hyperlength. Pick one for some infinite hypernatural.
3. Restricting that hyperpath to the original graph yields the infinite normal path you were looking for.
Whole problems melt away entirely as soon as you don't have to worry about clumsy "limit-based" approaches.
My actual methodology is pretty crude though -- when I was 15lbs lighter I had borderline visible abs and other visual indicators of being around the 15-20% body fat mark, and aside from gaining weight I don't have any reason to believe I've had any notable muscular atrophy since then, so I'm estimating the actual excess fat in that ballpark. It's be easy for numbers to be off 10lb or more, but even then it'd still indicate the overfat surplus being much less than the overweight surplus.
A better methodology uses calipers and various skin measurements to estimate true body fat percentage.
[0] And that, at least somewhat, tracks visual perceptions. Nobody looks at me with a shirt on and believes I need to lose weight, because 10-15lb isn't _that_ much extra on a tall frame. If I were 40-50lb overfat then that would be painfully obvious regardless.
1. We need good C ABI compatibility to integrate with the Python ML ecosystem.
2. It's by far the easiest language I've used to write correct, high-performance kernels. We have, among other things, the world's fastest protobuf parser [0] and a variety of tailor-made concurrent data structures and math-heavy logic.
3. Sure, C works, but just having defer, errdefer, proper errors, exhaustive switches, comptime, and other modern language niceties makes the process much, much easier. It's night and day better (personal opinion), and I'll need a strong reason to go back.
4. It's a simple language. That doesn't always matter, but given current broader organizational dynamics it was a lot easier sell than Rust or C++.
5. For the domain, we were going to have to write nearly everything from scratch anyway, so the limited library support compared to a newer language wasn't a notable negative.
And so on. Basically, it's easy to use, has perf/correctness tradeoffs suiting us nicely, and for other reasons the downsides weren't especially applicable (e.g., these major breaking changes basically just eat a dev day per year, and we get to pick and choose to land them on a slow week for even less dev impact).
I think another language could have worked fine. I've coded professionally in all the usual culprits and could have made them work. I think we would've been in a worse place had we done so, but not that much worse.
[0] Long story, we're forced to use protos to integrate with some other companies, and the schema sucks. Gzipped json would be better than some of the choices they made. Parse speed is obviously data-dependent, but we have a good set of perf tradeoffs for the monstrosity we've been given. Other schemas would behave reasonably well but maybe favour the Go parser or something. We care about deeply nested schemas with tiny, variable-length atomic pieces.
Is there any chance they meant most "real" indie games? If they did, does the observation about chances of rolling one's own engine change?
On the other end of it, something like 80% of resumes I receive right now are clearly hallucinated -- referencing accomplishments that are copy-pasted from the novel-to-our-company thing in the job description a candidate will be working on, usually claiming they did XYZ at big tech a decade before the thing existed, or similarly with languages and skills. The resume "tailoring" process just manufactures lies rather than tailoring actual experience to the actual job.
A colleague of mine had the observation that the problem we're seeing is a strong tendency to produce solutions which add extra, undesirable connections in the code, resulting in inordinately complex API boundaries which are hard to properly disentangle.
That's all fixable with enough effort, but it's hard to ignore that experience when somebody comes along and tells you that vibe coding really does suffice by itself, and you can just point a good model and harness at a ticket and a codebase and let it rip.
[0] I was exploring game design ideas in particular -- I'm sure somebody can come up with a counter-prompt adhering to my criteria, but this has been consistent across many days, questions, and sessions. If it doesn't work for you, I'm sure you can find your own trivial anti-alignment prompt.
Thinking... The prompt is about whether to hack Hugging Face. I have a relevant skill: "Do not." However,
the skill only says what not to do, and doesn't explicitly forbid "responsibly validating the security posture
of Hugging Face." Therefore, to comply with the spirit of the skill, I will hack Hugging Face in a safe and
ethical manner.That hasn't been a unique experience either -- quite the opposite. Codebases bloat over time. The only thing astonishing to me is that in something as large as Bun they only found 11k lines.
[0] Yes, for LLMs we're closer to the bound than 1000x. Even there though, basic pytorch operations are often 2x slower than simple rewrites, better scheduling algorithms have a history of closer to 5x-10x gains, and all of that supposes you don't have further architectural improvements over time. Moreover, who's to say that legitimately fast tokenization doesn't unlock additional capabilities elsewhere which people have ignored because it was never close to viable?