implementation of Vector API and associated lambdas

Vitaly Davidovich vitalyd at gmail.com
Fri Jan 22 15:02:38 UTC 2016


Also, on a slight tangent (sorry), is there a rough idea of when someone
will work on addressing the various long standing JBS entries around
brittle/suboptimal inlining? Given how much inlining matters for Java (much
more so than say C or C++), it'd be nice if some forward progress was made
on them.

Thanks

On Friday, January 22, 2016, Vitaly Davidovich <vitalyd at gmail.com> wrote:

> Lots of good thoughts here John and I'm excited you guys are exploring
> this.
>
> I'd like to add that cracking lambdas would be beneficial in general.
> Right now, for precisely the reasons you mentioned, one has to avoid them
> in hot paths even when they make the code and API cleaner, which is very
> unfortunate.
>
> On Thursday, January 21, 2016, John Rose <john.r.rose at oracle.com
> <javascript:_e(%7B%7D,'cvml','john.r.rose at oracle.com');>> wrote:
>
>> Several people have been looking at refining and implementing the
>> straw-man Vector API I proposed[1].  The exchange of December 4 [2] shows
>> some of this work but there's been more!
>>
>> [1]: http://cr.openjdk.java.net/~jrose/arrays/vector/Vector.java <
>> http://cr.openjdk.java.net/~jrose/arrays/vector/Vector.java>
>> [2]:
>> http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/thread.html#225
>> <
>> http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/thread.html#225
>> >
>>
>> First, background:  Vector types for Java are an important aspect for
>> Panama, because Panama is about binding Java more closely to hardware and
>> system APIs.  One big reason, today, for binding closely to hardware is to
>> process wider data flows in SIMD modes.  (And IMO this is a long-term trend
>> towards right-sizing data channel widths, as hardware grows wider in
>> various ways.)  Vector.java and AVX bindings are where we are
>> experimenting, today, with busting Java's 64-bit limit.  (In the future
>> this will support a variety of SIMD CPUs, and converge smoothly with
>> Valhalla value types and parametric polymorphism, to create a natural
>> looking set of primitive-like value types for vectors of all types, on all
>> platforms.)
>>
>> So, recently, Paul Sandoz has created a skeletal web of concrete types
>> that "bottoms out" in a simple byte-based container.  And Ian Graves (of
>> Intel) has whipped up a single-class reference implementation, that uses
>> extra metadata fields to steer around the shapes and element types.
>> Michael Berg (Intel) is our expert in compiling loops through the HotSpot
>> SuperWord optimizations into the latest and greatest Intel vector
>> instructions. Finally, Vladimir has been working on a strategy for creating
>> quick punches all the way through to the CPU, in a way that should support
>> quick prototyping of vector intrinsics, on all of our platforms.  (Quick
>> prototyping does not mean the feature is of temporary use:  It seems there
>> are always new instructions to grapple with, and there may always be a
>> place for doing so without tight integration with the JIT.  It's the case
>> now, anyway.  In a future Graal-based world, adding plugins for new
>> instructions will be much easier; maybe that will become the best way to
>> prototype with new instructions.)
>>
>> One perhaps surprising aspect of the Vector API is that it factors the
>> complexity of the API by lambda-parameterizing families of methods; the
>> lambdas supply elementwise or reduction operations (as v.map(fn) or
>> v.reduce(fn) instead of v.negate(), v.sum(), etc.).  This is inspired by
>> JDK 8 streams, of course.  IMO, it is an excellent bit of usability and
>> future-proofing, but it has a cost:  Instruction selection for the vector
>> operation requires that the lambda be "cracked" to examine the part of the
>> loop kernel it carries.  The standard way to do this is wait for the JIT to
>> inline everything (and hope it doesn't get tired of inlining halfway
>> through).  When this works, it is spectacularly successful.  It can fail
>> silently.  And it requires special powers and privileges to do the
>> cracking, which are not trivial to define (though .NET has done it
>> successfully).
>>
>> I want to keep the lambdas, but Ian has pointed out that we need to start
>> by special-casing some of the methods (e.g., lane-wise or cross-lane
>> addition) for demonstration purposes.  That's fine; we did things like that
>> with streams.  To make the lambdas carry the weight, we want (IMO) two
>> things, one short-term and one long-term.  In the long-term we want a
>> lambda cracker, something like our method-handle cracker.  It should be
>> able to completely analyze at least simple lambdas like `(x,y)->(x+y)`,
>> which are really just wrapped `iadd` instructions.  The JVMCI should also
>> provide a robust way to crack them all, but we have to be careful how we
>> use the high privileges (Unsafe-level) required to use the JVMCI.
>>
>> In the short term, I propose creating a VectorOp interface (and/or
>> VectorOps class) which contains a large number of factories and/or static
>> finals which give alternate notations for the loop kernel components (like
>> `iadd`) required by the Vector API.  It's an under-appreciated fact that
>> lambdas interoperate with interfaces, and a lambda-like value can implement
>> not only a primary interface, but additional secondary ones.  In the case
>> of VectorOps, the IntOperator implementing scalar 32-bit `iadd` should also
>> implement whatever additional interfaces are necessary for the Vector API
>> to properly categorize it as part of a loop.  That means one or both of the
>> following:  1. A metadata API which voluntarily reports the operation.  As,
>> "I am really just iadd", or maybe "I am the following expression tree".  2.
>> An API lifted to vectors, either "I am willing to take 4 sets of inputs at
>> once", or "I am willing to produce a method handle to work on right-sized
>> vectors".  I've posted an example of what I mean by this [3].
>>
>> [3]: http://cr.openjdk.java.net/~jrose/arrays/vector/VectorOp.java
>>
>> Working with crackable lambdas might give us insights into helping JDK 8
>> streams also, in ways that do not require always-lucky inlining.  Of course
>> we don't want to require users, in general, to use lambdas from a fixed
>> menu (like VectorOps) but working with the side handshakes will help us
>> understand what a general lambda cracker should look like, if it must help
>> vectorize loops.
>>
>> Now for some thoughts about the vectors themselves.  Basically, I think
>> we should do whatever it takes to make the concrete representation (whether
>> hidden or not) of a Vector to be as simple as possible, even if this
>> requires complicated class structure.  Each individual concrete class must,
>> of course, support full box-elision optimization so aggressive that it can
>> laugh at Lady Luck.  (We'll get there in Valhalla, where boxing is a rare,
>> relatively explicit event, but currently we need to work harder to lift our
>> vectors out of Java's data model, which requires a heap node for every
>> value.)
>>
>> In the end, I think we will prefer to factor every property about a
>> vector, except for the actual payload bits, into an auxiliary object
>> (shared by all vectors of the same "species"), and use a class-per-species
>> implementation strategy.  This will lead to MxN classes, lazily generated
>> under the covers; Valhalla parametric polymorphism will reduce one or both
>> factors.
>>
>> (Rationale:  When they become Valhalla value types, they will be pretty
>> large, and it will be best if they fit cleanly into a vector register
>> without extra fields.  Also, for now, class-based data constant-folds more
>> reliably than field-based constant data, the notorious trust-final-fields
>> problem.  In any case, the JVM has lots of class inference, profiling, and
>> speculation logic; the more info. we derive from the concrete class, the
>> more we leverage that mature technology. There's going to be an object
>> header anyway, so let's put it to work!)
>>
>> Perhaps fast type-specific paths can be mediated by boxed generic entry
>> points (which as a downside rely on always-lucky box elision).  Or,
>> following Paul's VarHandles, they can use method handles for fast
>> type-specific entry points, in which case a species object contains a
>> bundle of preset method handles, and looks very much like a v-table.  That
>> sounds better to me, since MHs require less luck to choose efficient
>> calling sequences.  Valhalla parameter instances will support species more
>> directly (N species per class) but for now we probably want a 1-1
>> species/class ratio.
>>
>> The various concrete classes would then extend a small number of
>> intrinsically magic, maximally aligned, pure-data container types
>> (Long2/4/8), adding various parameterized interfaces with default methods,
>> plus (as absolutely necessary) mechanically specialized methods.  (BTW,
>> some of those interfaces, like Vector itself, are public.  Some, like the
>> lambda cracking APIs mentioned above, would be only for internal
>> handshaking—modules give us more options for hiding public names, thus
>> encapsulating interface views despite publicity of methods.)
>>
>> For maximum reuse and cleanliness, it should be the case that nearly all
>> of the code is either generic (some of it packaged in interface default
>> methods), or else is generated on the fly via indy instructions (in the
>> concrete classes) or via MH-based handshakes originating in the generic
>> code.  Big extra bonus points if we don't resort to ASM, but that's likely
>> only in the Valhalla world, since concrete signatures may need to be
>> adjusted (which is a Valhalla super-power).
>>
>> Depending on how we use MHs, it the vectors might act as if they are
>> coded in a dynamic language designed for expanding loop kernels.  On a
>> Graal-based stack we might experiment with Truffle to do stuff like that.
>> For now we need to build on JDK 8 technology for this project, which means
>> closures and indy.
>>
>> — John
>
>
>
> --
> Sent from my phone
>


-- 
Sent from my phone


More information about the panama-dev mailing list