HN user

PeCaN

3,584 karma
Posts9
Comments992
View on HN

To be honest I don't really see people who don't want to learn APL being that interested in putting in the effort to completely upend how they think about programming and algorithms in order to use other array languages, regardless of syntax. (After all this is by far the hardest part of learning APL, the symbols are easy enough and easy to look up anyway.)

map is general in kind of the wrong way. You could after all add a #map method to Object for scalars and make a Matrix class that also implements it and then just call map everywhere. However you still run into the problem, mentioned in the video, that it doesn't easily generalize to x + y where both x and y are arrays; you have to use zip or map2 or something (and now you still have to figure out how to do vector + matrix) and yes you can kind of do explicit "array programming" in Ruby if for some reason you're really compelled to do that but it will look awful. And that's just what array languages do for you implicitly. As a paradigm there's a bit more too it than "just call map everywhere"—there's still all the functions for expressing algorithms as computations on arrays.

If you watch the video it looks like their proposed syntax is not APL-like but closer to mainstream languages.

I'm honestly not sure if this is a good thing or not. You said "easier" syntax than APL but APL is honestly a very easy syntax for working with arrays. That's a significant part of the advantage of APL, it makes it very easy to come up with, talk about, and maintain array algorithms.

Matlab and Julia and other languages aimed at scientific computing have some array language-like traits but lack a lot of the functions that make APL more generally applicable. And .map is all wrong; it's extra noise and it doesn't generalize down to scalars or up to matrices—the defining feature of array languages is that operations are implicitly polymorphic over the rank of the input.

I've been working on something like this on and off for the past 4 years or so, although with something more like generators than streams.

I think it's a very, very promising idea (I admit to heavily being biased towards anything APL-influenced) although surprisingly difficult to get right. Gilad Bracha is obviously way smarter than me so I'm definitely curious where he goes with this.

One additional idea that I keep trying to make work is integrating variations of (constraint) logic programming and treating solutions to a predicate as a generator or stream that operations can be lifted to rank-polymorphically. As a simple example a range function could be defined and used like (imaginary illustrative syntax)

    range(n,m,x) :- n <= x, x <= m
    
    primesUpto(n) = range(2,n,r),               # create a generator containing all solutions wrt r
      mask(not(contains(outerProduct(*, r, r), r)), r)  # as in the video
    
I've never really gotten this to work nicely and it always feels like there's a sort of separation between the logic world and the array world. However this feels incredibly powerful, especially as part of some sort of database, so I keep returning to it even though I'm not really sure it goes anywhere super useful in the end.
Servo’s new home 6 years ago

it's not so much that gcc does anything specific so much as LLVM is just really really inefficient—they don't track compilation time at all so it's easy for releases to regress, half the stuff in there is academics implementing their PhD thesis aiming for algorithmic accuracy with little regard for efficiency, and LLVM's design itself is somewhat inefficient (multiple IRs, lots and lots of pointers in IR representation, etc)

that said this makes it an excellent testbed but compilation time will keep getting slower every release until they start caring about it

Servo’s new home 6 years ago

that's just because gcc has certain optimization passes that can't be disabled

(that said gcc -O0 is still absolutely nothing like what a human would write)

I sort of wonder if this approach to JITing is worth it over just writing a faster interpreter. This is basically like what V8's baseline JIT used to be and they switched to an interpreter without that much of a performance hit (and there's still a lot of potential optimizations for their interpreter). LuaJIT 1's compiler was similar, although somewhat more elaborate, and yet still routinely beaten by LuaJIT 2's interpreter (to be fair LuaJIT 2's interpreter is an insane feat of engineering).

That's fair. It's definitely not a killer, (or even in my opinion the worst thing about RISC-V,) just another one of these random little annoyances that I'm not really sure why RISC-V doesn't include.

It's not like someone is proposing some crazy new instruction to do vector math on binary coded decimals while also calculating CRC32 values as a byproduct. It's conditional move. Every ISA I can think of has that.

[She] complains Risc-V need 4 instructions to do what x86_64 and arm does in two, but... it says Risc-V.

So… what, it should take 5 instructions?

Executing more instructions for a (really) common operation doesn't mean an ISA is somehow better designed or "more RISC", it means it executes more instructions.

And x86_64 CISC instructions devolve to a pile of microcode anyway.

Some people seem to have this impression that like every x86 instruction is implemented in microcode (very, very few of them are) and even charitably interpreting that as "decodes to multiple uops" (which is completely different) is still not right. The mov in the example is 1 uop.

I'm not sure about this "RISC way" stuff. From a uarch standpoint the RISC vs CISC distinction is moot and from an ISA standpoint the only real quantifiable difference seems to be being a load-store architecture.

ISAs without conditional moves tend to have predicated instructions which are functionally the same thing. I'm not actually aware of any traditionally RISC architectures that have neither conditional moves or predicated instructions. While ARMv7 removed predicated instructions as a general feature ARMv8 gained a few "conditional data processing" instructions (e.g. CSEL is basically cmov), so clearly at least ARM thinks there's a benefit even with modern branch predictors.

Conditional instructions are really, really handy when you need them. It's an escape hatch for when you have an unbiased branch and need to turn control flow into data flow.

Ironically enough I feel like IBM is actually an example of a giant company that, against all odds, is somehow still innovating, at least with its POWER CPUs. They're doing really interesting and open-ended things like CAPI and the upcoming Open Memory Interface.

I considered multiple selections a bit of a gimmick in sublime text and various emacs/vim extensions but the way it works in kakoune feels completely different.

Think about vim (and kakoune) as basically a highly interactive language for editing text. At least at a conceptual level something like diw is basically a function (d) applied to data (iw). Vim is completely scalar. The type of all the functions is more or less something like string → string. Kakoune is the APL of text editors. Multiple selections are an array of strings to operate on. It automatically maps the function (editor commands) over every selection. I find this extremely attractive and powerful.

At least for me kakoune blows all other editors out of the water. It really is quite good.

Probably not, since it's optimized for scientific workloads (being designed specifically for the K computer replacement) (so it doesn't have texture units, ROPs, etc; you'd have to do too much in software to make it actually render things). However I think the overall design is really good and has enormous potential, if not for graphics at the very least for ML.

The vector architectures with extremely high memory bandwidth coming out of Japan recently (NEC SX-Aurora Tsubasa, Fujitsu A64FX) are pretty fascinating.

I thought I'd seen a rather dramatic benchmark of this but I can't find it now. (I think it was in the context of io_uring, whose documentation mentions that polled IO is much lower latency and I'd trust Jens Axeboe on that one.)

This intuitively makes sense especially with SSDs and especially with NVMe SSDs: you're not going to have to wait that long, especially compared to the overhead of an interrupt. Also, if you're reading sequentially, once you get one I/O completion you're going to get a lot more in a short timeframe—it makes sense to just poll for those instead of handling every one as an interrupt. Interrupts are pretty expensive (I honestly don't have a good grasp of how Linux interrupt handling works but it can easily be on the order of microseconds.)

It also has some side benefits like preventing the CPU from going into a lower power state for only a short period of time.

I was extremely (I think justifiably) skeptical of async I/O on Linux for the longest time but now I legitimately think with io_uring Linux is actually somehow the gold standard for (1). They really got their act together. io_uring is really good.

While this is intuitively obvious, it doesn't really always play out that way in practice since interrupts can be expensive to handle. For example polled IO can be significantly lower latency than waiting for interrupts.

You can find QNX 6.5 and suitable license keys by digging around on the web a bit. 6.5 is probably the last version suitable for use as a desktop OS—I believe 6.6 is where they started to remove the ability to self-host, and the GUI was completely removed by QNX 7. (It's a shame, because IMO the Photon GUI is really clever.)

Unfortunately QNX 6.5 is pretty old and not too well-supported (QNX is fully POSIX-compliant so you can sometimes get things working on it without too much trouble however) but it's damn fantastic to play around with in a VM. It's actually so fun.

It's actually the exact opposite of fuzzing; with symbolic execution you aim to prove, symbolically, that all possible code paths have some desired behavior (e.g. not crashing,). With fuzzing you just try code paths (guided) randomly and see if any of them crash.

What the fuck

It's kind of funny to me though that there's an actual language out there where you can do use-after-free and all sorts of other C-level stuff but can't use tabs.

I don't think "coronavirus escapes from a lab, in the exact area where the outbreak started, that was studying coronaviruses" is exactly an 'extraordinary claim'. If anything it's the elephant in the room. Are we just supposed to casually ignore that or what….

I think the problem is that when people think of "lab" they think of some sort of devious genetic engineering bioweapons program, and not something considerably more likely but much more mundane like some scientists studying what sort of potentially bad viruses the local bats have.