Repository navigation
Infinite Arithmetic #708
Replies: 2 comments 1 reply
|
I agree with the underlying objective. Unlocking native SIMD capabilities for Solana programs is an obvious win, and one of several long-term goals we have for JIT intrinsics. That said, I think this API approaches the problem at the wrong level of abstraction. What Our preliminary research in this area also identified another significant bottleneck beyond access to the host's native ISA (which we've now addressed): the inability to directly leverage host vector registers across operations, resulting in repeated stack setup, copying, and spilling. This becomes catastrophically worse for perf when you wish to perform multiple contiguous SIMD operations over the same memory, as you force a stack setup and spill at every single step. We can do considerably better than this. Our current prevailing idea is to introduce a dedicated vector memory region to represent wider operands without having to modify BPF's existing scalar register architecture. The compiler and JIT could simply treat this region as a set of "virtual wide registers", mapping them directly onto native host vector registers. Combined with AVX2/AVX-512 or equivalent JIT intrinsics and vertical integration via libcalls, this allows us to lower SIMD operations directly at the compiler level, eliminating much of the intermediate memory traffic and syscall overhead altogether. This would make all of those cryptography libraries that have spent the past decade or so tuning their algorithms for AVX instructions to “just work™️”, making Solana's VM the fastest place in the world to do general purpose cryptography on a blockchain without requiring additional syscalls. This is obviously still exploratory work, and we haven't done nearly enough testing or benchmarking to justify proposing a concrete API yet, but if the need has arisen and this is now a priority, this is the direction we would propose. I'd much rather we explore how to extend our existing compiler and JIT infrastructure to support these capabilities before committing to maintaining an entirely separate arithmetic instruction architecture inside the runtime. |
|
i love the idea of the separate memory region. i really do. i think it's elegant. But, practically, i don't see how this could be faster than a syscall. if the ISA does not support loading into this mem region directly, it leaves us with having to go through the real registers or 1 or and then AGAIN for the copies back from this is in contrast to the syscall which just reads and writes into the buffers directly. i don't see why the perf has to be that bad. doesn't seem to me that let ops: Vec<SimdInsn> = unpack_polish(op_sequence)?;
for chunk in chunks {
let mut regs = load_inputs(chunk);
for op in &ops {
execute(op, &mut regs);
}
store_output(chunk, regs);
}would spill necessarily if i think we should literally just impl the two things and see which one is faster according to clock on linux's wall |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
thank you to @ptaffet-jump for the initial syscall structure, @cavemanloverboy for helping with the design & discussion post
infinite arithmetic
math today is expensive. we do not yet have native support for 128-bit math, and we have no support for any sort of data-level parallelism. the incredible advancements made by hardware designers, available on modern validator hardware, still elude the solana program developer. this forces many protocols to decide between efficiency & sophistication, stifling innovation from happening on chain.
despite the great work done by blueshift on simd-0645 and
sol_multi3, high-performance 128-bit multiplication is but a small subset of the operations we must improve to bring increasingly sophisticated protocols to solana. we must empower developers to write complex mathematical operations on chain with unprecedented efficiency by unlocking SIMD at a vm level, enabling a wholly new set of products to be built on solana.sol_math
we propose introducing
sol_math, a generalizable math syscall.metering
the cost of a call is statically determined before any work is done. it depends only on the op sequence and
cnt, so the proof-of-concept implementation calculates & consumes the cost immediately after decoding the op sequence. this prevents the validator from wasting immense amounts of time working through trillion-element slices. acntlarger than the buffers actually passed also fails before any arithmetic.the charge itself is a fixed base cost per call plus a cost per 8-lane chunk, proportional to the number of vector instructions the op sequence executes. further work on the cost model could expand to pricing avx instructions more in accordance with their cost. the current cost model charges each instruction 4 cu.
further detail regarding the proposed design is available in the benchmark repo.
initial results
the results from this design are quite promising. at 4096 lanes per call, across the set of proposed operations we see a wallclock speedup of 11.7x-47.6x for 64-bit integers and 10.3x-45.1x for 128-bit integers. the proposed cost model results in a 6.1x-20.0x reduction in cu consumption for 64-bit operations and an 11.1x-60.5x reduction for 128-bit operations. for several operations, cu-per-ns performance of
sol_mathexceeds that of the sbpf jit, indicating that even further cu reductions are justifiable. all benchmarks were run on an epyc 9275f.additional operations
under the proposed design, enabling new operations is trivially simple. as opposed to introducing a new jit intrinsic or syscall to support a desired operation, this framework only requires an additional opcode to be accepted by the syscall's parser, a price, and an execution path added to the interpreter dispatch.
outside of the operations laid out in the poc, there are several other operations which would likely be valuable.
vpmullq/ avx-512-dq)MIN/MAXvplzcntq/ avx-512-cd,vpopcntq/ avx-512-vpopcntdq)All reactions