[0] https://godbolt.org/z/85nx44zcE
edited: I tested gcc/clang and they just straight up fail to compile without -msse3. The generated code without optimizations is also pretty bonkers!
113 karma · joined October 14, 2019
Software engineer at tangram.dev, formerly at JITX, Ambidio. Currently a generalist, formerly audio/DSP specialist.
[0] https://godbolt.org/z/85nx44zcE
edited: I tested gcc/clang and they just straight up fail to compile without -msse3. The generated code without optimizations is also pretty bonkers!
What natural language processing does is just make a much smarter (and dumber, in many ways) parser that can make an attempt to infer the intent, as well as be instructed how to recover from mistakes.
Personally I'm a skeptic since I've seen some hilariously bad hallucinations in generated code (and unlike a human engineer who will say "idk but I think this might work" instead of "yessir this is the solution!"). If you have to double check every output manually it's not that much better than learning yourself. However, at least with programming tasks, LLMs are fantastic at giving wrong answers with the right vocabulary - which makes it possible to check and find a solution through authoritative sources and references instead of blindly analyzing a problem or paying a human a lot of money to tell you the answer to your query.
For example, I don't use LLMs to give me answers. I use them to help explore a design space, particularly by giving me the vocabulary to ask better questions. And that's the real value of a conversational model today.
I couldn't find any lock off the shelf that solved this, or a clean way to hack it with a fair mutex. So I wrote my own, and I'm pretty sure it's correct (1).
It's like a ticket lock, except the total number of tickets is known up front so every task can get one ticket. To acquire a lock is one CAS, where the lock is acquired iff the "current" value of the lock matches the ticket value of the task, if so we swap in a magic LOCK value. When the writer releases the lock it writes (ticket + 1) % num_tickets back to current so the lock can be acquired by the next task.
There's a deadlock condition though - if one task is cancelled while any other task is outstanding, no other task may acquire the lock, even if the cancelled task didn't acquire it!
To deal with that, the lock is poisoned with a magic POISON value. Then when any other task attempts to acquire the lock, but its value is POISON, then an error is returned and those tasks may be cancelled accordingly.
It's be possible to support adding/removing tasks concurrently by replacing the tickets with a circularly linked list of atomic pointers, so when one task is cancelled the "next" of the "prev" item can be atomically swapped, but I don't have a use case for that and it's annoying enough to write in Rust that I didn't want to bother with it.
(1) The code for this is here: https://github.com/m-hilgendorf/sequex/. I call it "sequex" for sequence-mutex. It could also be called a round-robin lock or something like that.
---
You could do this with just a ticket lock, where you take a ticket up front N times and then give one ticket to each task. When a task's ticket comes up it acquires the lock, but before releasing the lock, it takes another ticket. That's where I started, but I found this implementation cleaner.
Keep up the excellent work, seeing the autorouter come to fruition and demoed on the homepage is a massive accomplishment and mind blowing.
FUSE is much, much easier to work with. The protocol (even v4) should also be less chatty, and if performance is your goal there are projects like ExtFuse that can move some caching into the kernel via eBPF which I don't think would be possible with NFS.
If you poke around other user space file systems (sshfs, cephfs, objectivefs, etc) they're all FUSE.
Personally I don't like too many images in a README. It's not a SHOWME. That's for your product page.
Disclaimer: I'm an engineer at JITX. The core technology is a programming language for designs. It's a low level language for describing schematics and circuit boards, the kicker is that it's fully parametric and embedded into a high level language, which is stanza. The pitch I would give is that we're trying to do for hardware what GCC or NodeJS did for software engineering - everyone is hand coding assembly and manually checking it, we're building a compiler and set of libraries for getting things right and doing it fast.
I wouldn't just call it AI to automate circuit board design. We're definitely working on it and hiring folks for the tough optimization problems, but a lot of what we do is allow engineers to encode their expertise as reusable software components. I would say we're language and algorithm designers first, married to hardware designers.
For example, one of the cooler projects we did early in the pandemic was a mechanical keyboard designer that takes the JSON output of Keyboard Layout Editor and compiled it into a working circuit board and generated enclosure. I have it sitting in my office right now.
I may be overly biased but it's an awesome place to work. There are tons of interesting problems and great people. We have hardware experts designing boards, coming up with checks (think unit tests for hardware to automate design review), software folks doing our front end (a language server, custom VS Code extension to view circuit boards in a text editor), component selection, automatic placement, topological routing, web front end and backend, interesting and challenging DevOps, even real world compiler engineering - you name it. Every week is like the best course you've taken in CS - there so much to learn.
We're well funded and hiring. Since I joined in 2019 we've more than tripled in size and hiring! And frankly there's not many people working on this crucial problem. My email is in my profile if this sounds interesting to anyone.
The function call is a little deceivingly simple, it queries a parts database for one that fits the constraints like value/rating/stock and the part/footprint are parameterized by global design variables/rules under the hood.
(1) https://github.com/JITx-Inc/open-components-database/blob/1f...
It doesn't compile to JS, but this is one of the canonical use cases for Stanza 's (1) "optional" type system
It's remarkable how many problems are easier when you just accept it's some kind of compiler problem that needs parsing into a tree you can walk with a pass to spit out the required data. For example in audio networks, you can write a buffer allocation and latency compensation solver as a compiler pass over an AST that represents the network topology, collected by walking the network graph objects. It's way easier to write and test than using the same objects as the network itself.
I will say one of the downsides (if not tackled early) is incremental and streaming data through the architecture. It's a lot easier to write a batch parser than interactive one - which can hurt if you need partial compilation in the future.
Since MIDI is already going the opposite direction of say AES67 and reinventing wheels is ok, a custom binary encoding would have made more sense to me. Something that can be encoded in a C89 struct without a ton of trouble or doesn't need much thought put into an allocator on bare metal devices to get the handshake working.
I believe it's not strictly JSON though, I don't have the docs in front of me but iirc strings have a max length. So that's good.
The big underlying change is that MIDI 2 is duplex, which allows for device discovery, property exchange, and profile configuration. What that buys you is an arbitrary protocol for exchanging information about what things are connected to each other on the same network of devices. It should allow for a lot of cool features, like supplanting Mackie Control and Eucon with an open (or at least trivially open) protocol. One thing I think we'll see with these is more support for microtonal or arbitrary pitch systems that MIDI currently can't realize.
Jitter compensation is built into the protocol too so it should resolve some of the timing issues with USB.
Having read through the spec and written the data structures out for it already I'm not sold that it's overly complex. The additional annoyance is that it mandates JSON parsing but that isn't a tall order these days.
https://pure.mpg.de/rest/items/item_2383164/component/file_2...
./very-long-task.sh && say 'success' || say 'fail'
I use it when I need to context switch and leave something running. `espeak` is an alternative for `say` on Linuxes.One of the problems in designing generic tools for language development is they have to be far more abstract than the author might realize at first. The notion of evaluation is a big one, as in what it means to evaluate a chunk of code, what its results are, its intermediate products, and when the evaluation takes place (is it compile time, run time, parse time, etc). I think the next generation of tools are going to inspect these subtleties a lot more than traditional tools, since it has a big impact on usage when languages have heavy macro or other compile/parse time evaluation.
It's a great time to create language tools. The language server/debug adapter protocols make it possible to develop a rich backend for your language of choice and a thin client to integrate into many editors, rather than extending a single editor/IDE platform. You don't really need to build an entire IDE to create a rich IDE experience, or tie that experience to a particular platform.
I'd also add that you can get really far without linters/static analysis tools. A DSL doesn't necessarily need them to be useful. That said, there are language agnostic linters you can use to add support for your own language.
I will say though that there needs to be richer/better language agnostic tools. There are a few for linting, debugging, static analysis, etc, but there's a need for things like auto formatting, CI/CD/general automation, build systems, and package managers. There are a many but it's tough to know which horse to pick.
That serves as a less magical introduction to the operator. You can then point out that the polynomials whose coefficients one convolves can be considered power series, which has a nice interlude into the Z transform and its usefulness as an analytical tool when working with convolutions (and then on to the Fourier transform, etc).
I wouldn't discount the amount of people using voice assist and rely on noise reduction/echo cancellation in their meetings, or the near future where we have SMPTE 2098 renderers running on HTPCs.
I really think we're only a few years away from seeing a lot more realtime DSP in consumer applications. Conferencing, gaming, and content consumption all benefit immensely, and it would good for us all to start thinking about the latency penalty on audio-centric HCI like we do for video.
The computer can be an entry point for one's journey just the same as an acoustic guitar or piano. You can use that as your platform to learn theory as well as (if not better than) a piano or guitar.
But to get elitist for a moment, there's no better way to learn music aside from private lessons. That's true of any instrument, including the DAW.
I'm in disagreement with the parent, dynamic dispatch through vtables is only a zero-cost abstraction across FFI boundaries. Personally I'd ballpark about 33% of the value-add of traits are shared interfaces on different types.
The real money is in associated types and trait bounds. The latter is still a serious type-checking requirement at compile time, and the former requires RTTI to support dynamically in some form - both of which have costs at compile and runtime.
All that said, there may be an argument that the features GP is talking about are covered currently by enum variants (many of the use cases one would have for base classes with associated member variables are done that way, for example), and if you could show how performance and ergonomics improved by increasing the semantic complexity of dyn trait objects - you'd have a strong argument to add it to the language. Just my two cents.
[0] https://github.com/microsoft/com-rs/
[1] https://github.com/RustAudio/vst3-sys
[2] https://github.com/RustAudio/vst3-sys/blob/master/examples/p...
As a little dose of irony, clippy doesn't like the com-rs crate too much.
For example, an exponential moving average:
s_n+1 = a x_n + (1 - a) s_n
y_n = s_n
where a, x, s, y in Reals
The next state depends on all past state, including initial conditions.Conceptually, stateful systems are the notion "where I am going depends on where I am." Markov processes are stateful systems where "where I am going depends on where I am, but not upon where I came from."