[vector] ClassCastException in C2 with Mask rebracketing
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Thu Feb 15 17:50:46 UTC 2018
Adam,
Thanks for the report.
I hit a similar problem with vectors and tracked it down to a changes in
Parse::do_call (disabled C->optimize_virtual_call() on vectors). The bug
is devirtualized non-inlined call can float before the type check it
depends on. It leads to a wrong method being called when type check
fails and manifests as a CCE in interpreter after deoptimization (due to
failed type check). It usually happens when vector shapes change at
runtime: C2 produces a method specialized for some particular vector
shape and then the first time the method observes a different vector shape.
The problem is specific to original intrinsics which rely on some
inlining tweaks (like in Parse::do_call) to make intrinsification more
reliable.
I suggest you to try -XX:-UseVectorApiIntrinsics and check whether the
problem goes away.
Generalized intrinsics will be used (where available) and they shouldn't
be prone to that problem (relevant code path in Parse::do_call is used
only for original intrinsics).
Unfortunately, not all operations are covered by generalized intrinsics
yet. So, generated code quality may suffer as well.
I didn't bother fixing the bug because the plan is to replace original
intrinsics with generalized ones and remove inlining tweaks.
Best regards,
Vladimir Ivanov
On 2/15/18 8:11 PM, Adam Pocock wrote:
> Hi,
>
> I've been working on more involved machine learning demos on top of the
> vector API. As part of that I built a binary search demo that searches n
> vectors at the same time using an n-wide SIMD. This keeps rebracketing
> the Mask from Integer to Float and back again as it searches through the
> arrays.
>
> Paul Sandoz has been helping me debug it, and when this code is run
> using C1 or lower it executes fine, but when it's recompiled with C2
> (triggered by executing binarySearchCDF in a loop with the same
> arguments and a print statement, takes about 300-500 iterations) it
> throws a ClassCastException (stack trace below). Turning off C2 with
> "-XX:TieredStopAtLevel=3" allows the loop to complete.
>
> Code:
>
> public static <S extends Vector.Shape> IntVector<S>
> binarySearchCDF(IntSpecies<S> spec, float[][] input, int fromIndex, int
> toIndex, FloatVector<S> key) {
> IntVector<S> low = spec.broadcast(fromIndex);
> IntVector<S> high = spec.broadcast(toIndex - 1);
> IntVector<S> one = spec.broadcast(1);
>
> Mask<Float,S> mask = key.species().trueMask();
>
> int[] indicesBuffer = new int[key.length()];
> float[] valuesBuffer = new float[key.length()];
>
> while (mask.anyTrue()) {
> IntVector<S> mid =
> low.add(high,mask.rebracket(Integer.class)).shiftR(1);
> mid.intoArray(indicesBuffer,0);
> for (int i = 0; i < valuesBuffer.length; i++) {
> valuesBuffer[i] = input[i][indicesBuffer[i]];
> }
> FloatVector<S> values =
> key.species().fromArray(valuesBuffer,0);
>
> Mask<Integer,S> lessThanKey =
> values.lessThan(key).and(mask).rebracket(Integer.class);
> low = low.blend(mid.add(one),lessThanKey);
> Mask<Integer,S> greaterThanKey =
> values.greaterThan(key).and(mask).rebracket(Integer.class);
> high = high.blend(mid.sub(one),greaterThanKey);
> Mask<Integer,S> equalsKey =
> values.equal(key).and(mask).rebracket(Integer.class);
> low = low.blend(mid,equalsKey);
> mask = mask.and(equalsKey.rebracket(Float.class).not());
> mask = mask.and(low.lessThan(high).rebracket(Float.class));
> }
>
> return low;
> }
>
> Stack trace:
>
> Caused by: java.lang.ClassCastException:
> jdk.incubator.vector/jdk.incubator.vector.Int256Vector$Int256Mask cannot
> be cast to
> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask
> at
> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask.and(Float256Vector.java:488)
>
> at
> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask.and(Float256Vector.java:430)
>
> at
> mlrg.topicmodel/com.oracle.labs.mlrg.topicmodel.util.vector.BinarySearch.binarySearchCDF(BinarySearch.java:37)
>
>
> Line 37 is:
> mask = mask.and(equalsKey.rebracket(Float.class).not());
>
> Thanks,
>
> Adam
>
More information about the panama-dev
mailing list