[vector] ClassCastException in C2 with Mask rebracketing

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Fri Feb 16 23:14:19 UTC 2018


> Yep, the problem went away with "-XX:-UseVectorApiIntrinsics". My vector 
> shapes are unchanging though, everything is fixed at S256Bit as that's 
> what I've got on my desktop. I thought the rebracket for things like 
> masks were supposed to be optimised out, as a Float 256 Mask is the same 
> bit string as an Integer 256 Mask.

Yes, rebracketing turns into an no-op when boxes go away. Otherwise, the 
operand has to be boxed/reboxed.

> Any idea when the generalized intrinsics will land?

The first batch is already there, but no exact dates when the rest follow.

Best regards,
Vladimir Ivanov

> On 15/02/18 12:50, Vladimir Ivanov wrote:
>> 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