aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2022-07-22 21:53:43 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2022-07-22 21:53:43 -0400
commit5cdf1d8f32fedf0e9b57268254a6e483e6c75fe2 (patch)
treeb483755511fcd3303eca4c40d087b5de1c5a0cb0
parent9b005a4c978c582b362f7fb8e6b086e1b62b8e4f (diff)
Mention that it's harder for compilers to support new architectures
-rw-r--r--docs/implementation/kclaims.html4
-rw-r--r--implementation/kclaims.md4
2 files changed, 4 insertions, 4 deletions
diff --git a/docs/implementation/kclaims.html b/docs/implementation/kclaims.html
index 05e1dbe3..b00d9ca1 100644
--- a/docs/implementation/kclaims.html
+++ b/docs/implementation/kclaims.html
@@ -21,8 +21,8 @@
<p><em>That's CPython of course. Language names here refer to the commonly-used implementations, such as V8 or SpiderMonkey for Javascript.</em></p>
<p>Popular APL and J implementations interpret source code directly, without even building an AST. This is very slow, and Dyalog has several other pathologies that get in the way as well. Like storing the execution stack in the workspace to prevent stack overflows, and the requirement that a user can save a workspace with paused code and resume it <em>in a later version</em>. But the overhead is per token executed, and a programmer can avoid the cost by working on large arrays where one token does a whole lot of work. If you want to show a language is faster than APL generally, this is the kind of code to look at.</p>
<p>K's design is well-suited to interpreting scalar code because of its simplicity. It has only one kind of user-defined function and doesn't allow lexical closures. Implementations always compile to bytecode, which for example Q's <a href="https://code.kx.com/q/ref/value/">value</a> function shows. Having to keep track of integers versus floats is a drag, but ngn/k is able to use <a href="https://en.wikipedia.org/wiki/Tagged_pointer">tagged pointers</a> to store smaller integers without an allocation, and I doubt Whitney would miss a trick like that. So K interpreters can be fast.</p>
-<p>But K still isn't good at scalar code! It's an interpreter (if a good one) for a dynamically-typed language, and will be slower than compiled languages like C and Go, or JIT-compiled ones like Javascript and Java. A compiler generates code to do what you want, while an interpreter (including a bytecode VM) is code that reads data (the program) to do what you want. Once the code is compiled, the interpreter has an extra step and <em>has</em> to be slower.</p>
-<p>This is why BQN uses compiler-based strategies to speed up execution, first compiling to <a href="vm.html#bytecode">object code</a> and then usually further processing it (compilation is fast enough that it's perfectly fine to compile code every time it's run). In particular, CBQN can compile to x86 to get rid of dispatching overhead. And ktye's somewhat obscure K implementation now has <a href="https://github.com/ktye/i/tree/master/kom">an ahead-of-time compiler</a> targeting C, which is great news. Commercial K and Q are always described by developers as interpreters, not compilers, and if they do anything like this then they have kept very quiet about it.</p>
+<p>But K still isn't good at scalar code! It's an interpreter (if a good one) for a dynamically-typed language, and will be slower than compiled languages like C and Go, or JIT-compiled ones like Javascript and Java. A compiler generates code to do what you want, while an interpreter (including a bytecode VM) is code that reads data—the program—to do what you want. Once the code is compiled, the interpreter has an extra step and <em>has</em> to be slower. Compiling has its difficulties, particularly for JIT compilers. An interpreter can use one set of source code and re-compile for different architectures, but a native compiler (such as the one used to build that interpreter…) either needs new code for each architecture or has to target an intermediate language that can then be handled with an existing compiler. But, well, it runs faster.</p>
+<p>This is why BQN uses compiler-based strategies to speed up execution, first compiling to <a href="vm.html#bytecode">object code</a> (fast enough that it's no problem to compile code every time it's run) and then usually further processing it. Right now, CBQN can compile to x86 to get rid of dispatching overhead, although that's well short of true <a href="compile/intro.html">array language compilation</a>. On the K side, ktye's somewhat obscure implementation now has <a href="https://github.com/ktye/i/tree/master/kom">an ahead-of-time compiler</a> targeting C, which is great news. Commercial K and Q are always described by developers as interpreters, not compilers, and if they do anything like this then they have kept very quiet about it.</p>
<h2 id="parallel-execution"><a class="header" href="#parallel-execution">Parallel execution</a></h2>
<p>As of 2020, Q supports <a href="https://code.kx.com/q/kb/mt-primitives/">multithreaded primitives</a> that can run on multiple CPU cores. I think Shakti supports multi-threading as well. Oddly enough, J user Monument AI has also been working on their own parallel <a href="https://www.monument.ai/m/parallel">J engine</a>. So array languages are finally moving to multiple cores (the reason this hasn't happened sooner is probably that array language users often have workloads where they can run one instance on each core, which is easier and tends to be faster than splitting one run across multiple cores). It's interesting, and a potential reason to use K or Q, although it's too recent to be part of the &quot;K is fastest&quot; mythos. Not every K claim is a wild one!</p>
<h2 id="instruction-cache"><a class="header" href="#instruction-cache">Instruction cache</a></h2>
diff --git a/implementation/kclaims.md b/implementation/kclaims.md
index add2b42a..19cfee02 100644
--- a/implementation/kclaims.md
+++ b/implementation/kclaims.md
@@ -34,9 +34,9 @@ Popular APL and J implementations interpret source code directly, without even b
K's design is well-suited to interpreting scalar code because of its simplicity. It has only one kind of user-defined function and doesn't allow lexical closures. Implementations always compile to bytecode, which for example Q's [value](https://code.kx.com/q/ref/value/) function shows. Having to keep track of integers versus floats is a drag, but ngn/k is able to use [tagged pointers](https://en.wikipedia.org/wiki/Tagged_pointer) to store smaller integers without an allocation, and I doubt Whitney would miss a trick like that. So K interpreters can be fast.
-But K still isn't good at scalar code! It's an interpreter (if a good one) for a dynamically-typed language, and will be slower than compiled languages like C and Go, or JIT-compiled ones like Javascript and Java. A compiler generates code to do what you want, while an interpreter (including a bytecode VM) is code that reads data (the program) to do what you want. Once the code is compiled, the interpreter has an extra step and *has* to be slower.
+But K still isn't good at scalar code! It's an interpreter (if a good one) for a dynamically-typed language, and will be slower than compiled languages like C and Go, or JIT-compiled ones like Javascript and Java. A compiler generates code to do what you want, while an interpreter (including a bytecode VM) is code that reads data—the program—to do what you want. Once the code is compiled, the interpreter has an extra step and *has* to be slower. Compiling has its difficulties, particularly for JIT compilers. An interpreter can use one set of source code and re-compile for different architectures, but a native compiler (such as the one used to build that interpreter…) either needs new code for each architecture or has to target an intermediate language that can then be handled with an existing compiler. But, well, it runs faster.
-This is why BQN uses compiler-based strategies to speed up execution, first compiling to [object code](vm.md#bytecode) and then usually further processing it (compilation is fast enough that it's perfectly fine to compile code every time it's run). In particular, CBQN can compile to x86 to get rid of dispatching overhead. And ktye's somewhat obscure K implementation now has [an ahead-of-time compiler](https://github.com/ktye/i/tree/master/kom) targeting C, which is great news. Commercial K and Q are always described by developers as interpreters, not compilers, and if they do anything like this then they have kept very quiet about it.
+This is why BQN uses compiler-based strategies to speed up execution, first compiling to [object code](vm.md#bytecode) (fast enough that it's no problem to compile code every time it's run) and then usually further processing it. Right now, CBQN can compile to x86 to get rid of dispatching overhead, although that's well short of true [array language compilation](compile/intro.md). On the K side, ktye's somewhat obscure implementation now has [an ahead-of-time compiler](https://github.com/ktye/i/tree/master/kom) targeting C, which is great news. Commercial K and Q are always described by developers as interpreters, not compilers, and if they do anything like this then they have kept very quiet about it.
## Parallel execution