Neso is an ahead-of-time compiler backend for Triton. It lowers Triton TTIR/TTGIR into MSL or HLSL shader code, to allow modern LLM compute kernels such as Flash Attention II to run on GPUs in consumer devices such as Macs and Windows laptops. A companion project, NSpeech https://github.com/dropbox/nspeech, built in Rust with Candle, demonstrates how Neso can be used to power local ASR and TTS models.
Nobody cares if kernels are written in Rust. Kernels were meant to be written in C, but if you want to go more high-level try Triton or a similar DSL that nicely abstract tile sizes etc.
kernels aren't meant to be written by any defined language. C is just a traditionally good default language that took over from assembly. No particular reason we have to stick with C.
What reasons would you have to prefer Rust over C for compute kernels?
I am a great fan of Rust, but I don't see any benefit for kernels, due to their relatively simple nature.
SYCL is the natively polyglot counterpart, with practical implementations of it compiling down to the same sort of SPIR-V kernels as OpenCL. (OTOH, much of the current adoption on the open standards side seems to target the more widely supported SPIR-V compute shaders, via Vulkan compute.)
Not really, first of all it is for C++, not the range of languages supported by CUDA.
Before SPIR was a thing in OpenCL, Khronos could not understand why anyone would care about anything else other than C99, or why supporting Fortran on GPUs was at all relevant.
Secondly, from the competition only Intel cares about SYCL with their own sugar on top, OpenAPI.
AMD hasn't cared one second about it.
You may mention Codeplay, which is anyway an Intel owned company since 2022.
As for Vulkan, it doesn't have neither the features, nor the tooling that CUDA enjoys, it is the usual putting up with using LEGOs from different brands, with various pin sizes, that is so common with Khronos.
I strongly dislike CUDA. Once you have allowed that proprietary cr*p into your C++ codebase, it is very hard to get rid, and you end up with code that is either tied to a single vendor or an #ifdef hell, probably both.
The best way to program GPUs is face up to the reality that they are not the same machine as the CPU, write your kernels in separate files, and launch them manually, like in Metal, OpenCL, and D3D12, etc.
These days we even have DSLs like Triton that make kernel writing much more ergonomic than anything you would hope to achieve in Rust.
> Once you have allowed that proprietary cr*p into your C++ codebase
People have been doing that all the time for every kind of codebase. It's just part of the business. I don't see how it's worth having any emotions or opinions about it. Seems like you are wasting your energy.
Are win32 APIs proprietary? So you decide to use them, use a wrapper/UI framework, or don't develop for Windows. Easy choice.
Developing for embedded devices? So you read the manufacturers manual and implement based on the spec, use some sort of HAL if they are available, or you don't have a job. Even simpler.
Oh, does that mean I get to say you're ironic because, literally, they didn't tell anyone to do anything. They said they didn't understand the worth of the opinion. You're interpretation is selectively literal in order to be rhetorical.
Does that mean someone else gets say I'm being ironic because I'm selectively literal in order to be rhetorical? Well, okay, I guess it's harder now.
You're interpretation is selectively literal in order to be rhetorical.
Where do you think you are ?
Most of us are in tech/IT/research the population in the spectrum here is orders of magnitude bigger than the avg on real life. SO yeah people will be literal in order to be rhetorical. Not even selectively, this is the one site where you NEED to use /s unironically.
That opinion is work-ethic related, not CUDA-related. The stance is reasonable too; why complain about characteristics of CUDA that can't be changed?
Your job as a CUDA engineer isn't to decide whether or not a proprietary API/compiler is the right call. Your boss made that choice for you when they hired you, and you accept the tradeoff if you want to keep working there. It's like someone protesting Dotnet because they wish they spent the rest of their life working with Perl instead. You can do that, but it's a completely different job with different pay grades and demands.
> It's just part of business. I don't see how it's worth having any emotions or opinions about it.
Because we're engineers? Hackers? You know, hacker news?
We're supposed to care about the craft, its quality, and our long-term interests, not the shareholders, not the executives, and definitely not Microsoft and NVIDIA. If you really think this isn't a discussion worth having then you don't belong in this domain at all and you shouldn't be an engineer.
If that business makes it money selling a cross-platform AI inference engine, as was the case for my previous startup, it is bad business to tie yourself to single platform. I managed to build a single code base that would support CPUs, OpenCL, Metal, CUDA, D3D12, and WebGPU from a single set of kernel sources. As a single developer, there was no way I would have been able to, at the time, maintain separate code paths and GPU kernels for each of those platform, in addition to training the models etc.
> People have been doing that all the time for every kind of codebase. It's just part of the business.
What is your ecosystem where this is true? Embedded or industrial, maybe?
I'm guessing you assume other people also use the same windows or embedded systems you're referring to. That's an insane thought: nobody would use this if they had any chance, and you intentionally chose this misery.
Obviously, you don't need to live this way. You can be free. Breathe.
The CPU on most machines is quite proprietary. I don’t understand this faux purity dogma.
Practical computing is not and never has been an abstract pure concept. It’s about making machines built by corporations to do usefull things at scale.
There is no ”non proprietary” computing unless you make your own stack.
Yes but there are business costs to using high-level proprietary tools and libraries. If you write your app using win32, you won’t be able to port is very easily. You’re also stuck with whatever bad or bizarre decisions Microsoft made.
It’s even worse for CUDA. GPUs are expensive, and now you’re vendor locked. You’re between a rock and a hard place. Either spend millions in engineering time, or millions on price-gauged hardware.
” If you write your app using win32, you won’t be able to port is very easily.”
This is wrong way around.
If you don’t support the platform your app runs on using the native api:s to the hilt your port is just bad.
If you actually want to support multiple platforms _you actually need to support_ them from the ground up.
This is speaking industrially and businesswise. A professional software business always has per-platform implementation resources. Or they have just one platform. Or they pretend they are multiplatform and then _everybody_ _daily_ fights with the problems this causes.
Obviously those elements that can be portable should be. It’s like Einsteins simplicity maxim - your codebase should be as portable as can be but not more.
” It’s even worse for CUDA…”
No these are just the business and market constraints. If this does not make sense for your offering then don’t use it. This feels like false FOMO - CUDA is not a silver bullet but it might be a specific solution to a specific problem.
It really depends on the application. The reason web is so successful as a platform is because it’s rich enough for most applications, and inherently cross-platform at an OS level.
And Re: CUDA: yes if it doesn’t make sense then dont use it. That’s sort of my whole argument. It might make some level of sense from a technical perspective, but that needs to be balanced with business risk. I’m saying a lot of people aren’t doing the balancing right, which is why these new tools have value.
Correct, most of Linux user land targets API stability, not ABI stability. Windows targets ABI stability because applications are typically distributed as binary blobs. Most applications on Linux are open-source and built per each distro, so it’s a non-issue, just recompile.
This doesn’t work for proprietary software that’s distributed as blobs and rarely updated, like say, video games. But that’s a minority of stuff on Linux. But not on windows.
Realistically, on Linux applications target specific API versions of frameworks. Like Qt 6, or GTK 3, or whatever. Then everything is compiled or dynamically linked at a per-distro level. The ABI compat can bite specifically when distros enforce strict dynamic linking. But then containerization technologies come in.
And there is a difference between API and ABI stability. For example, adding SSO to std::string in C++ broke ABI, not API. If you recompile it’s fine, everything works. If you don’t then it doesn’t.
Dead wrong. Win32 (externally) only seems stable, but internally it changes between Windows releases. Win7 syscalls are completely different from Win11 syscalls, meaning if I want to release a binary _without relying_ on Win32 I need to provide full syscall mappings _for each and every Windows version_. This doesn't happen on Linux.
That's literally the definition of it being stable. Programs written against an interface keep working despite the implementation changing. The Linux kernel also constantly changes internally but programs written against syscalls keep working, so it is stable; that fact doesn't stop being a fact just because I dislike perf_event_open(2) or whatever. This is all very basic and easy to understand.
I wonder which APIs you would use to port easily, because POSIX and Khronos aren't it either, as they are industry standards driven by companies where one has to pay for a seat at Open Group and Khronos offices.
Porting has never been hard. Just follow the platform guidelines. Make sane architecture. Done.
I mean _it's just work_. You don't need to invent anything. Just do the work.
What _is_ hard is when people run after silver bullets to avoid all this work.
Because people who don't understand software decide it would be cheaper to implement something only once. Or someone who does not really understand what they are doing insists that same C++ code runs automatically on all platforms.
AI has given the software engineers permit from the beancounters to do the sane thing.
Good software development orgs _have always_ done proper per platform ports.
Also - there is nothing wrong in supporting only one platform as such!
> Good software development orgs _have always_ done proper per platform ports.
I really wonder why this was never fundamentally fixed. How performant a certain instruction on a specific platform is, how well it is supported and potential equivalents or sets of other instructions to emulate an equivalent are usually all very well understood.
So there should be some graph of operations which can transform any software from and to the specifics of each platform. Especially because firmware + compliers + platform abstracting libraries are basically already just that graph, although (usually?) to lossy to be applied in reverse. Add the recent developments in very large scale statistics to it and it'd probably be quite possible to transform from and to generic intent in the implementation to the uniqueness of each platform. E.g. the theming differences between a MacOS UI and a terminal application served over serial or the processing capabilities of a VLIW CPU compared to a FPGA or a GPU server.
Considering the enormous amount of work that went into compilers, better debugging and intermediate representations it seems like a huge missed opportunity nobody seriously asked the question whether information could be emitted that would allow for decompiling all the way back to the generic intent.
The hard part of porting to a different platform is usually not the instruction set. It’s the OS and system abstractions.
For example, if you have a program that just does raw math and pointer arithmetic and data structure manipulation —- that is, pure computation — then porting it to a different CPU might well be trivial. Just recompile. As long as your language toolchain supports it, this will Just Work.
But if your program works with the filesystem and sockets and threads, then it’s less likely to work. This is the promise of POSIX: if your program uses only what’s offered by the POSIX standard and uses those functions correctly, then it’s supposed to work on any POSIX-compliant system. Just recompile.
But if your program has a GUI, or does 3D graphics, or uses special methods for high-performance networking, or accesses gyroscopes or accelerometers or touch sensors, well then you have to do work to port. And notice that this work isn’t about which CPU instruction to use. It’s about figuring out —- deciding —- what the right thing to do is, for your app, given a slightly different set of available system capabilities.
I can program all my non-CUDA GPUs use completely open non-proprietary toolchains. And if that ceases to be the case on one platform I can switch platforms without having to rewrite all my code.
If you're going to make apps in windows, you need to call their proprietary API somehow. Maybe you do it via a wrapper library, or via electron or something. But that's the same thing, just with more indirection.
> If you're going to make apps in windows, you need to call their proprietary API somehow. Maybe you do it via a wrapper library, or via electron or something. But that's the same thing, just with more indirection.
Not even close to being true. You can invoke syscalls directly, just needs a bit of reverse engineering. I wrote a bare metal libc library, with (not a whole lot of) effort I'm fully able to interface with the kernel/open windows etc. Fully statically linked, no libc, no win32, compiled on Linux executed on Windows.
The problem is this isn't really well documented _at all_, and I even ended up attempting to get in touch with the Windows kernel dev team to give me the actual internal syscalls/endpoints, but they refuse to cooperate. Which is why writing anything for Windows is entirely pointless.
The problem is much deeper than that. Most OSes' syscall ABIs are not stable and could change without warning. What is stable is the dynamically-loaded libraries, shipped as part of the system. Linux is the notable exception here; the Linux kernel project doesn't ship a libc, and Linus is very famously opposed to "breaking userspace."
There's nothing that can stop you from using syscalls in theory, but if you want your app to be portable across different OS versions, past and future, you'd better not.
Incidentally, syscalls would also break Wine. The way Wine works is basically by shipping their own versions of Windows DLLs, which express their operations in terms of Linux APIs. Because Windows programs don't rely on syscalls, and call all system functions via the system-provided libraries, the Wine loader can just link Wine's version and let the program work normally.
If I recall correctly, the Golang team got bitten by this on MacOS.
They initially implemented the Golang runtime directly on top of MacOS syscalls (not the C runtime library), just like they did on Linux - and then those syscalls changed, breaking Golang.
They had to switch to the official stable API which on MacOS is the C runtime library, not syscalls.
That’s insane. Windows does not have a stable syscall ABI. The way you’re supposed to interact with the kernel is through the userspace library. Of course the kernel team refuses to cooperate.
Do you want to keep reverse engineering the syscall ABI for every Windows edition and update ever? Do you want to ask your users to disable Windows Update?
Regardless, I don’t even understand how that’s relevant, since you’re still introducing a dependency on a proprietary ABI.
> This isn’t even close to being true. Here’s a thing I did that made things way more complicated than is worth it for 99% of developers when there is a proprietary solution made so I do not need to worry about these things. Because it is so hard to work around it, it is entirely pointless to develop for one of the most used operating systems in the world.
Just being totally honest this is how I read this comment when I insert context that seems important to me. I respect having principles but at some point there needs to be more value in practicality over your codebase not being locked into a proprietary framework at all.
> Not even close to being true. You can invoke syscalls directly,
The windows syscall API is yet another proprietary windows API. Sure - you can call it without loading any DLLs. But you're still calling into a proprietary windows API.
If you really hate calling proprietary windows APIs that much, maybe stop developing for windows? Develop software for linux. Or make your own kernel, or whatever. But if you keep developing software for windows, stop fighting it. Unless you have a very good reason, your software should try to fit in on its host platform. It should behave well, and work like other windows software.
It's like travel. If you fly to France, try to fit in. Maybe learn a bit of French before you go. If you hate France, don't go.
> The CUDA runtime is a special case of one of the libraries provided by the CUDA Toolkit. The CUDA runtime provides both an API and some language extensions to handle common tasks such as allocating memory, copying data between GPUs and other GPUs or CPUs, and launching kernels. The API components of the CUDA runtime are referred to as the CUDA runtime API.
That's a nice way of saying that it's a dependency clusterfuck.
I've never understood why we can't just expose the GPU ISA directly the way the CPU does. It's all getting compiled down at the end of the day so someone has to write a compiler for it either way. We'd be substantially better off IMO if it was all built directly into LLVM and then let middleware sort out the details.
That would require vendors to either stick with a single backwards compatible ISA like intel did for x86 or document how their graphics cards work.
CPUs manage this by changing the internal micro-architecture, but historically GPUs only needed to support a graphics API and used that abstraction layer to freely change the hardware.
> I don't see how it's worth having any emotions or opinions about it. Seems like you are wasting your energy.
Some people only care about the easiest path to their pay check. Some people actually care about software engineering. I tend to prefer the latter but hamstrung by the former.
Have you considered that maybe, just maybe, you can have both an easy path to your paycheck and care about software engineering? You also might have an incorrect definition of "software engineering" in mind
Launching kernels manually is an error prone PITA which I believe is the principle reason for CUDA's popularity. Having the compiler give an error when you mess up is a huge benefit. But having the compiler allow you to express "I want to launch this kernel over a grid with these dimensions, with these arguments" as a single expression is where the vast majority of the value comes from.
The having it all in a single file is mostly an artefact of the fact that it is C++, because C++ is single file at a time compilation. In D (which is multiple files in a single compiler invocation) with DCompute (which targets CUDA and OpenCL with upcoming support for Vulkan and Metal), you are required to write the kernels in a separate module, but you get all the benefits of the compiler complaining when you mess up _and_ the expressivity of "launch me this kernel".
Write python code, ask any llm to translate it to C, then compile the C code - if it produces errors or fails to run, ask LLM to fix it. Then take it a step further and ask it produce machine code, and repeat the procedure.
Then RL the llm on the above, and you basically have a Python -> Machine code compiler. If you cover every single possible python syntax, every single possible C syntax, every possible standard library call, and all the compiler optimization examples (all of which is a final set), you should get something that is extremely accurate.
Having also played with Metal and WebGPU (at least years ago), I would say that CUDA is, amazingly, the best GPGPU API we have. Do I wish we had an open source parallel programming language as good or better than it? Yes. But asymmetrically hating on CUDA like this is how we continue to lag behind it in UX.
> The best way to program GPUs is face up to the reality that they are not the same machine as the CPU, write your kernels in separate files, and launch them manually
Not to mention that this is a completely sane way to use CUDA as well.
I know it's not the same thing because proprietary vs open software it's way less important but, generally if you are not ideologically against something you can easily follow the stream and do lot of nefarious actions, especially if the action has enough degrees of separations from the actual nefast outcome.
As it happens, I just got my employer's permission to release as open source a Triton back-end for Metal and D3D12 GPUs here: https://github.com/dropbox/neso .
Finally, I am also going to be switching the inferencing part of Witchcraft from current Candle on MacOS and OpenVINO on Windows to just Candle with Neso; https://github.com/dropbox/witchcraft
It is currently faster than the stock Candle / MPS shaders it replaces on MacOS/ARM64, and IIRC a bit slower than OpenVINO/CPU on my old Windows laptop, where I never got OpenVINO/GPU to compute correctly. Candle didn't have support for GPUs on MacOS/Intel, and OpenVINO ceased to be supported there.
Compared to OpenVINO (I tried ONNX runtime too, but never got it produce correct outputs with my quantized models) it is very nice to be able to build the exact kernels I need, at the quantization settings and precision that works for the models I have and with the custom operators required (speech models do a lot of non-standard stuff), run from a single set of sources, and not have to ship a hefty third-party DLL, and having to deal with their memory leaks and other stability issues.
> The best way to program GPUs is face up to the reality that they are not the same machine as the CPU, write your kernels in separate files, and launch them manually,
Yes, I also prefer doing it that way, but in Cuda with the driver API. Allows you to handle kernels like shaders, including editing and hot-reloading at runtime.
The reason I'm sticking with CUDA is because it's by far the most convenient API to use, without nonsense like 50-liners to alloc memory or the need to manage descriptors, bindings, queue families, etc.
> The reason I'm sticking with CUDA is because it's by far the most convenient API to use, without nonsense like 50-liners to alloc memory or the need to manage descriptors, bindings, queue families, etc.
I was there when the OpenCL committee was deciding on that sort of stuff.
As I recall, and it's been two decades and a lot of sleepless nights since then, there was real pushback at the time against OpenGL-style default bindings. So folks didn't want to establish an implicit command queue or any other default objects attached to other objects. Part of it is because OpenGL was perceived as clumsy and passé, some of it was because it is not friendly to multi-threaded applications.
Those first meetings were a shitshow full of tension, implicit threats from Apple, and backroom deals. Kudos to Neil Trevett for chairing the group; I I bet it wasn't fun for him either.
That's unfortunate. Cuda has shown that, when done right, defaults and a convenience layer can make for a well received API without sacrificing performance.
> The best way to program GPUs is face up to the reality that they are not the same machine as the CPU, write your kernels in separate files, and launch them manually
No. CUDA allows you to write all the code in a single file, and uses a preprocessor to split it back out and pass it through separate compilers, one for host and one for device.
This true, but you can write the two separately if you want.
The disadvantages of writing them together are listed in the various parent posts. But some code authors really like the convenience of having the two in the same file.
from what i can tell, you're going to be stuck with that no matter what you do
i'm currently using vulkan, and HLSL via dxc.
which should be portable but it's not.
apple refuses to support vulkan, and relies on moltenvk
and there's a bunch of OS/hardware/driver differences no matter what you do, that you'll probably have to feature test for, and compile a few different versions of your code no matter what you do
i think if you're doing something that you don't have to distribute to customers, just picking one stack and getting locked in has some appeal.
it leaves you vulnerable to lockin. but, especially in the age of ai, "claude, port this to vulkan" seems like a good enough defense against that
I don't mind CUDA, I do mind that all of the SDKs don't dynamically load the various CUDA shared libraries at runtime.. intertwining itself into your application linking process makes for extreme binary portability inconvenience.
There a flavor of CUDA runtime libraries that binds at runtime, so you can have a single binary that runs with CUDA and without it. I did this at work.
Obviously you need to check if CUDA is available before trying to execute kernels, or it will error out.
I fell in love with MATLAB (or GNU Octave for free since you really pay for toolboxes/packages) back around 2004, despite it warts. So I second Julia, which is similar, but is a more modern functional language instead of imperative.
I asked Google's Gemini if Julia can run on GPU unmodified without annotations, pragmas, intrinsics or similar manually-managed friction, and it said yes, but that data types must be swapped out for GPU-backed types:
If your code is written using vector/matrix operations, broadcasting, or standard linear algebra functions, it can run on the GPU entirely unmodified. You only need to change the input data type to a GPU-backed array (e.g., swapping a CPU Array for a CuArray from CUDA.jl).
# A standard Julia function — completely agnostic to hardware
function custom_math!(C, A, B)
@. C = sin(A) + 2 * B # Normal broadcasted operation
end
# Running on the CPU:
A_cpu = rand(1000)
B_cpu = rand(1000)
C_cpu = similar(A_cpu)
custom_math!(C_cpu, A_cpu, B_cpu)
# Running on the GPU (Unmodified function!):
using CUDA
A_gpu = CuArray(A_cpu)
B_gpu = CuArray(B_cpu)
C_gpu = similar(A_gpu)
custom_math!(C_gpu, A_gpu, B_gpu) # Automatically compiles to native PTX!
This is the direction we should be going. So while Nvidia's Rust port is an important first step, it's an evolutionary rather than revolutionary achievement. But that's all Nvidia can really do now, since it's locked into its own paradigm like Intel/Microsoft and has gotten too big to think outside the box.
Edit: PTX in its example stands for Parallel Thread Execution, the Virtual Machine (VM) Instruction Set Architecture (ISA) created by NVIDIA for its GPUs, which works similarly to Java byte code.
Edit 2: Broadcasting is a feature in Julia that allows you to apply a function or mathematical operation element-by-element across arrays of different shapes and sizes, without writing manual loops. In Julia, broadcasting is syntactically indicated by a dot (.) placed before an operator or function name (e.g., sin.(x) or .+). <- I was today years old when I learned the term for this
I highly recommend Julia for (scientific) GPU programming but it would be nice if there was a larger community and/or funding behind the GPU side of things. It has very few core devs for what it is.
Julia has had a great CUDA story for a few years now, and this about 9 days old. Rust rejects buffer aliasing at compile time using Rust's borrow checker, but shared memory in cuda-oxide currently requires unsafe, but then there's HuggingFace's Grout and mistral.rs, so yeah, Rust is picking up ground here on Julia. How is OpenCL's performance these days?
You don't need to use the CUDA (SIMT) programming model if you don't like it. The project includes cutile, which lets you program the GPU using tensors. It feels a lot like programming the GPU using numpy and triton.
i'm surprised modular's doesn't get much traction. The promise seems super interesting, and chris latner has the record to back up his claims. If someone has an explanation..
Ive essentially followed that paradigm with Python and C. I start out writing Python code. If I need something to run fast, I build a standalone C application that either reads from a file or listens on a socket, and just invoke it from Python. No need to write the entire thing in Rust and deal with all its semantics when it will be at best like 2% faster.
You need Objective-C, Swift, and Metal is a C++14 dialect with extensions.
You may refer to the C++ bindings, which still not obviate the need for the C++14 dialect in the shaders, and it only works, because there is a shim to call the Objective-C runtime from C++.
Likewise there are DirectX COM interfaces that are really only usable from Visual C++ COM extensions, and the HLSL semantics depend very much on which compiler is being used, hence why there is finally a language reboot going on.
> I strongly dislike CUDA. Once you have allowed that proprietary cr*p
Genuine question...why not just type "crap"? It's not even that much of a curse, but I've never really understood the point of self-censorship. If you don't want to curse then you could just use a non-curse word.
It doesn't read as emphasis to me. It reads like the person is trying hard not to curse, and they think "crap" is a curse word. It's a little bit adorable, like I'm reading a comment from an obedient child.
I guess you are not from the generation of texters. This how languages work we used to use * as a way to avoid getting censored it over time became a way to curse or give emphasis.
But typing "b*tch" with T9 is just as difficult (if not more) as typing "bitch". Anyway, I guess I never had a need to swear much over SMS. On IRC, on the other hand...
People are getting used to censor themselves in order not to be reported, banned, or «hurt » other sensibilities. The words « rape » couldn’t be written in instagram for example, what a great way to deal with such a serious issue. Mainly an American thing spreading away from young people if you ask me. Sorry America, just being honest here.
As much as I personally dislike TikTok, I don't think it is fair to it: cultural willingness for more sensor sheep on Internet started years before TikTok's popularity in the west.
It's not the sole cause, but I believe it's the main driver behind a bunch of specific substitutions that are mainstream now or nearly so. For example, dih, ahh, and unalive. They may not have been invented on tiktok, but that's where they incubated.
There's no such censorship on TikTok, it's entirely groupthink based on people saying "when I use that word my video is seen less so therefore it's being censored".
Youtube is a lot more guilty of it though, as well as demonetizing.
It sounds like there is a documented policy or proven that TikTok does it. Just people thinking it does leading them to self-censor. Then people see others doing it and copy it. So, I guess it is censorship but not by TikTok.
After reading through the threat here it seems more like a cultural thing.
The US has quite a lot of filters for profanity.
I remember from my youth that in 2009 Eminem was a guest in a Germany TV show and very happy to swear as much as possible without being censored.
https://www.youtube.com/shorts/2OC-yKZ5Yag
No, but I think ICQ and some IRC clients had profanity filters turned on by default. I remember visiting a friend once and realising he hadn't turned the profanity filter off. I teased him about it for weeks.
I think a string of non-alphanumeric characters would work much better here, like "Once you have allowed that proprietary @#$&% into your C++ codebase”
In any context I've seen, asterisks are for wrapping formatting and said formatting it to add emphasis. So being in the habit of typing `emphasised phrase`, for italics - regardless of whether the platform parses markdown/similar formatting, e.g. SMS.
To have an unclosed asterisk replacing characters in a word? I've only ever seen that as a way to bypass censorship. This spans communications from people currently in their 40s down to 20.
But this isn't perceived as emphasis at all. If I wanted to emphasize something, I'd be more likely to use something like *bitch* or something along those lines. Replacing a letter with an asterisk comes across as self-censorship, which is pretty silly - just use a different word if you're that uncomfortable with swearing.
Maybe more like p**p, as in "that cunt p**ped in my yard"?
I'll admit, it never once occurred to me that people might be using censored characters to provide more emphasis that a word is a swear, but I guess it does indeed do that, at least to the writer. Whether that comes across to the reader, and whether the writer cares that their intention was understood... I'm not so sure.
I was so disappointed when I tried reading tintin in other languages and found the dear captain was straight up using slurs in those. I wonder whether the english language ones have been edited over the years to remove that sort of thing
I certainly dislike how everyone on YouTube is saying “SA” and “unalive” and “corn”.
It’s one thing if it’s some funny commentary channel avoiding those words, but what bothers me is the true crime YouTubers. In the subject of true crime, rape and murder are just things that are probably going to come up, and when they refuse to use the appropriate language, it comes off as infantilizing, which is weird considering that my actual YouTube account is over 18, let alone the viewer using it.
I don't think those filters are even real, I think it's just mass-hysteria. I call these kinds of behaviours "traditions", but I'm not sure if there's a better term for it.
Basically someone comes up with something which is nonsensical, but plausible. Like believing that their videos are unpopular because they said the word "rape" and the algorithm magically got them, rather than because their videos suck. Then someone else sees that and starts thinking it is true. It silently spreads across the population.
I've seen this in organisations, where new recruits haven't been properly trained. Someone has come up with a method which is wildly incorrect and illegal, but plausible. The other new people around them have copied them. They've become slightly more experienced people, they've taught the next round of new people.
Before you know it, half of the organisation is doing something hilariously wrong, and they all sincerely believe it is the right way of doing it, because everyone does it. It's just self-reinforcing at that point.
> I call these kinds of behaviours "traditions", but I'm not sure if there's a better term for it.
In psychology that kind of thing is referred to as "superstition".
More specifically, "superstition" in this sense refers to the phenomenon of copying someone else's successful approach to a problem you have. (In your example, getting views on youtube.) Since you don't know what parts of their approach matter, you copy the effective parts and the ineffective parts equally.
No it isn't mass hysteria. YouTube has a set advertiser friendly guideline. It will scan uploads and streams automatically.
YouTube used to demonetise profanity unless it was mild. YouTube would demonetise profanity in the first X number of seconds of the video. These rules change and have been relaxed of April last year, but generally these rules still exist.
There isn't a hard filter if you say "suicide" you automatically get it. However it increases the likely hood of demonetisation. So people avoid it to be safe. So you end up with people using stupid euphemisms all the time.
The Suicide stuff is about protecting them from people who were promoting self harm. The unalive stuff is because of threats of violence. You can reference murder if it is say part of a news story or referencing something historical.
Creators are being careful don't want their video demonetised because once it gets the yellow flag, even if it is removed later they've lost the majority of monetisation.
The problem with providing direct proof of this is that YouTube moves the goalposts quite often and their auto moderation system is very inconsistent.
I am sure they are bullshit. Like when they mute cursing and "risky" speech, but when you enable autogenerated subtitles they show up there. Youtube knows what thay said regardless if it's censored or not. It's so fucking stupid
A (baseless) hypothesis: perhaps there are plenty of YouTube creators who use the proper, mature terminology but you never see their videos because the algorithm really is penalizing them for it...
It's become so bad that even quality history youtube channels are frequently using euphemisms like "moustache-man" instead of just saying "Hitler", to avoid their videos being buried by The Algorithm, and therefore cut severely into their viewership.
> even quality history youtube channels are frequently using euphemisms like "moustache-man" instead of just saying "Hitler"
That can be quite confusing. You had German mustache-man, Russian mustache-man, French mustache-man (Petain), French small-mustache-man (de Gaulle), Spanish small-moustache-man (Franco)
It may be to bypass censorship, rather than self-censorship. Some platforms block or shadowban comments with curse words. Not sure about this platform.
I have written many words far worse than "crap" on this site. I haven't gotten in trouble over it yet.
I do find it a little amusing, because commenters stopped criticizing my cursing the moment I started getting a good chunk of karma here. I remember in 2016 someone criticized me for using the term "shitposting"...I don't think I've gotten that kind of criticism since 2016 though.
Because I know it is not technically crap, a lot of competent people worked on it, most with good intentions. I suppose it is better described as a cleverly designed Trojan horse than can infect your software and make that software become crap, in the sense that it becomes harder to maintain, increases code duplication, messes with your build system, ties your build system to platforms that have their toolchain binaries available, etc., etc., without bringing any long-term benefits over learning things the hard way.
The long term benefit is that there are more developers with CUDA experience available to hire than there are with any of the "hard ways" you mention.
Not saying you're wrong, but my career got a lot less frustrating when I started focusing more on the product and less on the ergonomics of the implementation. If you need to build a house and the customer isn't willing to pay for brick, you use vinyl siding.
For learning that may be a fine approach, but CUDA (in C++) really tries to hide what is going on behind the scenes, which is roughly:
1) code gets split between a host part that goes through your normal compiler, and a device part that goes through the GPU compiler. You may as well write the kernels separate and compile them via a separate compilation step, and keep your trusted host compiler for the host-side code.
2) data needs to move between the host and devices via explicit buffer transfers and synchronization steps, CUDA tries to hide this with annotated pointers, but it is really easier to think about those as just buffers that you allocate and transfer IMO, instead of trying to transparently share pointers between host and device like CUDA does.
3) kernel launches can we wrapped in a function similar to:
Instead of the funky <<< >>> syntax that CUDA for C/C++ imposes. The problem is that once you start putting that in your code, it stops being C++ and stops being portable to non-CUDA GPUs. The launching and grid settings can be a bit hard to grasp at first, but sugarcoating that in bastardized C++ syntax does not absolve from having to understand it eventually.
So a good place to start might be an OpenCL or Metal primer, depending on the hardware you have available. D3D12 (and probably Vulcan too) makes this much harder than it should be, with too much boilerplate but is overall a mature and well-designed API should you wish to develop for Windows. Starting with WebGPU might also be good these days. It has a very different shader language than the others, but the rest of the concepts are similar, and it has a strong emphasis on making things async, which is what you want for performance anyways.
Claude/Codex should be able to get you moving very quickly.
Thank you very much for the effort you put into your advice!! I think I will start with WebGPU (wgpu), even though I have an Apple Silicon Macbook. I would really prefer to work with Rust instead of C++ because I am not good with C++. (I believe) I am good with C, so my C++ code looks like C code, and I am kinda learning the differences as I learn CUDA, which is a terrible way to learn C++, I guess.
> I've never really understood the point of self-censorship.
Some platforms disallow certain words. In order to bypass that, some people use the asterisks. That's just as one possible answer to your question; there can be many different reasons for self-censorship, but to me the most logical one is when one tries to work around crappy restrictions, such as on terrible reddit (they killed old.reddit recently; I retired before that due to moderators being insane, but I also said that if old.reddit is gone, I am gone anyway - the requirement to now log in, totally defeats old.reddit com's usecase. Then again reddit went downhill many years before that already, so not a real loss.)
Your comment only makes sense in context if you believe in a deity who is too dumb to understand the difference between cr*p and crap. I for one do not worship a Bayesian spam filter.
"Daddy, what does cr*p mean?" Kids aren't stupid and this self-censorship isn't protecting anyone from anything.
(if a platform is serious about Bad Words for whatever reason (moral?) they would also forbid character replacements; ultimately it's the intent, not the word itself, that they try to steer with rules like that)
I guess I never understood censorship when it’s plainly obvious what you’re censoring. Anyone who can read will clearly know that it said “crap”, so I don’t see how it’s fundamentally different than just saying the word. You still put the word into my brain.
IMO cr*p and crap are both valid but separate swear words. People have a wide option to choose from when they want to swear, and people like variety (much much more than LLMs do). People also tend to influence each other with their usages: cr*p is popular because it is popular.
Otherwise cr*p is just as good as crap, shit, horseshit, poopoo or such.
edit: * replaced with \* as HN interprets asterisks as formatting for emphasis. Thx latexr for informing me
I invented VM live migration to solve the problems with traditional process migration, and my work was inspired by both Sprite and MOSIX. I believe that VM migration is in wide use today, especially at hyperscalers.
Mike Nelson, who worked on Sprite, invented VM live migration in parallel with me, but secretly within VMware.
I've been on Mastodon for a few years, and though it has less drama than Twitter/X, it does seem to have reached critical mass of users and does cover most of my needs for random gossip. I am surprised that that nobody has mentioned it here.
Threatening assault on a paying customer for not knowing tipping norms is just one of the many reasons why American society is in the state it is. I've seen similar things like 'be glad I didn't spit in your food', 'next time they are getting trouser food'. This is despicable.
You can always hide in your own country, as long as you or the people who protect you are able to stay in power, but at least you cannot use the rest of the world as playground or shopping center. Sucks to be a rich kleptocrat and not be able to have a yacht in Nice or be able to take your wife shopping in London.
Hi Jacob, thanks for sharing! Witchcraft looks super interesting—starring the repo now.
The late interaction (ColBERT / MaxSim token-level) approach is fascinating for local search. Retaining per-token interaction matrices gives incredible semantic retrieval precision without losing fine-grained token context.
From an architectural standpoint, the main trade-off I explored with Hillock was moving away from dense token-embedding matrices entirely toward an explicit neuro-symbolic split:
1. Symbolic Grounding: Hard Subject-Predicate-Object (SPO) triples in relational SQLite tables to eliminate vector drift for exact factual memory.
2. Subsymbolic VSA Gating: A 10,000-dimensional Vector Symbolic Architecture (HDC) hypervector space on CPU using subword n-grams and GloVe SimHash projections for <1ms gating and pronoun resolution.
3. Edge VRAM Footprint: Keeping the whole engine under 1.2 GB VRAM on a GTX 1070 by using a CUDA bi-encoder pipeline (Fastcoref + MiniLM + GLiREL) for non-generative document parsing.
I'm curious—how do you manage the index footprint and per-token memory overhead in Witchcraft when scaling to larger local document collections?
There is no memory overhead, in that everything resides on disk/in the sqlite database, and is read from there on demand. That said, sqlite for blob storage is a bit inefficient, so the next version will use tightly packed structs on disk. I also managed to finetune an embedding down to 96d, so in the coming version the storage for the index is getting close to parity with the size of the text being indexed.
reply