-
Notifications
You must be signed in to change notification settings - Fork 17
Strange error when doing a StdArrays.copyFrom with a matrix using JDK 17 #11
Description
Expected Behavior
Note: title changed - Strange error interfacing with Scala when doing a StdArrays.copyFrom with a matrix using JDK 17
While exploring and documenting the Index API, I get errors when using Scala. I get a java.nio.BufferOverflowException exception. However, what seems like an equivalent Java test, has no problem. I expect the Scala code to work just as it does in Java. I am trying to replicate the error in Java.
I understand that Scala is not a supported platform, but will appreciate any help. I have been at this for a week.
Actual Behavior
I have created a test that succeeds here . The relevant code is:
String[][] indexData = new String[5][4];
for (int i=0 ; i < 5; i++)
for (int j=0 ; j < 4; j++)
indexData[i][j] = "("+j+", "+i+")";
NdArray<String> matrix2d = StdArrays.ndCopyOf(indexData);
assertEquals(2, matrix2d.rank());
/*
|(0, 0), (1, 0), (2, 0), (3, 0)|
|(0, 1), (1, 1), (2, 1), (3, 1)|
|(0, 2), (1, 2), (2, 2), (3, 2)|
|(0, 3), (1, 3), (2, 3), (3, 3)|
|(0, 4), (1, 4), (2, 4), (3, 4)|
*/
// all rows, columns 1 to 2
NdArray<String> same7 = matrix2d.slice(Indices.all(), Indices.slice(1,3));
assertEquals(2, same7.rank());
assertEquals(Shape.of(5,2), same7.shape());
assertEquals(10, same7.size());
String[][] expectedr7 = new String[][]
{
{"(1, 0)", "(2, 0)"},
{"(1, 1)", "(2, 1)"},
{"(1, 2)", "(2, 2)"},
{"(1, 3)", "(2, 3)"},
{"(1, 4)", "(2, 4)"}
};
String[][] lArray = new String[5][2];
StdArrays.copyFrom(same7, lArray);The equivalent Scala code is:
val indexes =
for
i <- (0 until 5)
yield
val row = for { j <- (0 until 4) } yield s"($j, $i)"
row.toArray
val indexData = indexes.toArray
val matrix2d = StdArrays.ndCopyOf(indexData)
// all rows, columns 1 to 2
val same7 = matrix2d.slice(Indices.all(), Indices.slice(1,3))
assert(same7.rank() == 2)
assert(same7.shape() == Shape.of(5,2))
assert(same7.size() == 10)
val expected_r7 = Array
(
Array("(1, 0)", "(2, 0)"),
Array("(1, 1)", "(2, 1)"),
Array("(1, 2)", "(2, 2)"),
Array("(1, 3)", "(2, 3)"),
Array("(1, 4)", "(2, 4)")
);
val lArray = Array.ofDim[String](5,2)
assert(lArray.size == 5)
assert(lArray(0).size == 2)
StdArrays.copyFrom(same7, lArray)Steps to Reproduce the Problem
- I forked the NdArray repository, created and ran the test above with success
- I am using the latest version of the NdArray library for the Scala code
- I created an equivalent "test" as shown above
- When I execute the Scala code I get the following error:
Exception in thread "main" java.nio.BufferOverflowException
at org.tensorflow.ndarray.impl.buffer.Validator.copyToArgs(Validator.java:61)
at org.tensorflow.ndarray.impl.buffer.misc.ArrayDataBuffer.copyTo(ArrayDataBuffer.java:52)
at org.tensorflow.ndarray.impl.dense.DataTransfer.execute(DataTransfer.java:114)
at org.tensorflow.ndarray.impl.dense.AbstractDenseNdArray.read(AbstractDenseNdArray.java:94)
at org.tensorflow.ndarray.StdArrays.copyFrom(StdArrays.java:2735)
at org.tensorflow.ndarray.StdArrays.lambda$copyFrom$75(StdArrays.java:2752)
at org.tensorflow.ndarray.impl.sequence.SlicingElementSequence.lambda$forEachIndexed$0(SlicingElementSequence.java:65)
at org.tensorflow.ndarray.impl.sequence.NdPositionIterator.forEachIndexed(NdPositionIterator.java:43)
at org.tensorflow.ndarray.impl.sequence.SlicingElementSequence.forEachIndexed(SlicingElementSequence.java:64)
at org.tensorflow.ndarray.StdArrays.copyFrom(StdArrays.java:2751)
at core.TensorExamples$.ndArraySlicing(TensorExamples.scala:751)
at core.TensorExamples$.main(TensorExamples.scala:1176)
at core.TensorExamples.main(TensorExamples.scala)
It is difficult for me get a failing example in Scala that anyone here could easily run and check. So my goal is to try and replicate this in Java. In particular I have found that the Java version does not follow the same path as the Scala code. When debugging the Java version I manually get this trace:
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java [2747]
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java [2751]
/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java [50]
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/impl/sequence/SlicingElementSequence.java []
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java [2752]
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/StdArrays.java [2735]
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/AbstractDenseNdArray.java [94]
dst: ArrayDataBuffer length = 2, offset = 0, readOnly = false
/workspaces/java-ndarray/ndarray/src/main/java/org/tensorflow/ndarray/impl/dense/DataTransfer.java [104] <-----> [114]
Note that with the Java version the DataTransfer class executes the copyByElement [104] method. The Scala code does a srcBuffer.copyTo [114]. The test srcDimensions.isSegmented() seems to be different. The relevant code is shown below:
static <T, B extends DataBuffer<T>> void execute(B srcBuffer, DimensionalSpace srcDimensions, B dstBuffer, OfValue<B> valueTransfer) {
if (srcDimensions.isSegmented()) {
long elementSize = srcDimensions.get(srcDimensions.segmentationIdx()).elementSize();
copyByElement(
srcBuffer,
PositionIterator.create(srcDimensions, srcDimensions.segmentationIdx()),
dstBuffer,
PositionIterator.sequence(elementSize, dstBuffer.size()),
elementSize,
valueTransfer
);
} else {
srcBuffer.copyTo(dstBuffer, srcDimensions.physicalSize());
}
}So my question is, how can one change the Java test code so that a srcDimensions.isSegmented() is false and I srcBuffer.copyTo method is used.
On another note, would it be interesting to provide additional tests as a PR, including the one above?
Specifications
- Version: 0.3.3
- Platform: Java JDK 17 on Linux