/** * Compute the offset given an array of offsets. * The offset is computed(for both fortran an d c ordering) as: * sum from i to n - 1 o[i] * s[i] * where i is the index o is the offset and s is the stride * Notice the -1 at the end. * @param arr the array to compute the offset for * @param offsets the offsets for each dimension * @return the offset that should be used for indexing */ public static long offset(INDArray arr, long... offsets) { return offset(arr.stride(), offsets); }
/** * Return the proper stride * through a vector * relative to the ordering of the array * This is for incX/incY parameters in BLAS. * * @param arr the array to get the stride for * @return the stride wrt the ordering * for the given array */ public static int getStrideForOrdering(INDArray arr) { if (arr.ordering() == NDArrayFactory.FORTRAN) { return getBlasStride(arr); } else { if (arr instanceof IComplexNDArray) return arr.stride(1) / 2; return arr.stride(1); } }
/** * This method is used in DL4J LSTM implementation * @param input * @return */ public static INDArray toMmulCompatible(INDArray input) { if (input.rank() != 2) throw new IllegalArgumentException("Input must be rank 2 (matrix)"); //Same conditions as GemmParams.copyIfNecessary() boolean doCopy = false; if (input.ordering() == 'c' && (input.stride(0) != input.size(1) || input.stride(1) != 1)) doCopy = true; else if (input.ordering() == 'f' && (input.stride(0) != 1 || input.stride(1) != input.size(0))) doCopy = true; if (doCopy) return Shape.toOffsetZeroCopyAnyOrder(input); else return input; }
private INDArray copyIfNecessary(INDArray arr) { //See also: Shape.toMmulCompatible - want same conditions here and there //Check if matrix values are contiguous in memory. If not: dup //Contiguous for c if: stride[0] == shape[1] and stride[1] = 1 //Contiguous for f if: stride[0] == 1 and stride[1] == shape[0] if (arr.ordering() == 'c' && (arr.stride(0) != arr.size(1) || arr.stride(1) != 1)) return arr.dup(); else if (arr.ordering() == 'f' && (arr.stride(0) != 1 || arr.stride(1) != arr.size(0))) return arr.dup(); else if (arr.elementWiseStride() < 1) return arr.dup(); return arr; }
private String shapeInfo(INDArray arr) { return Arrays.toString(arr.shape()) + " and stride " + Arrays.toString(arr.stride()) + " and offset " + arr.offset() + " and blas stride of " + BlasBufferUtil.getBlasStride(arr); }
public LogEntry(INDArray toLog, String status) { //this.id = toLog.id(); this.shape = toLog.shape(); this.stride = toLog.stride(); this.ndArrayType = toLog.getClass().getName(); this.length = toLog.length(); this.references = toLog.data().references(); this.dataType = toLog.data().dataType() == DataBuffer.Type.DOUBLE ? "double" : "float"; this.timestamp = System.currentTimeMillis(); this.stackTraceElements = Thread.currentThread().getStackTrace(); this.status = status; }
private INDArray copyIfNeccessary(INDArray arr) { //See also: Shape.toMmulCompatible - want same conditions here and there //Check if matrix values are contiguous in memory. If not: dup //Contiguous for c if: stride[0] == shape[1] and stride[1] = 1 //Contiguous for f if: stride[0] == 1 and stride[1] == shape[0] if (!Nd4j.allowsSpecifyOrdering() && arr.ordering() == 'c' && (arr.stride(0) != arr.size(1) || arr.stride(1) != 1)) return arr.dup(); else if (arr.ordering() == 'f' && (arr.stride(0) != 1 || arr.stride(1) != arr.size(0))) return arr.dup(); else if (arr.elementWiseStride() < 0) return arr.dup(); return arr; } }
/** Check if strides are in order suitable for non-strided mmul etc. * Returns true if c order and strides are descending [100,10,1] etc * Returns true if f order and strides are ascending [1,10,100] etc * False otherwise. * @return true if c+descending, f+ascending, false otherwise */ public static boolean strideDescendingCAscendingF(INDArray array) { long[] strides = array.stride(); if (array.isVector() && strides[0] == 1 && strides[1] == 1) return true; char order = array.ordering(); if (order == 'c') { //Expect descending. [100,10,1] etc for (int i = 1; i < strides.length; i++) if (strides[i - 1] <= strides[i]) return false; return true; } else if (order == 'f') {//Expect ascending. [1,10,100] etc for (int i = 1; i < strides.length; i++) if (strides[i - 1] >= strides[i]) return false; return true; } else if (order == 'a') { return true; } else { throw new RuntimeException("Invalid order: not c or f (is: " + order + ")"); } }
/** * Infer the order for the ndarray based on the * array's strides * @param arr the array to get the * ordering for * @return the ordering for the given array */ public static char getOrder(INDArray arr) { return getOrder(arr.shape(), arr.stride(), arr.elementStride()); }
/** * Compute the offset given an array of offsets. * The offset is computed(for both fortran an d c ordering) as: * sum from i to n - 1 o[i] * s[i] * where i is the index o is the offset and s is the stride * Notice the -1 at the end. * @param arr the array to compute the offset for * @param indices the offsets for each dimension * @return the offset that should be used for indexing */ public static long offset(INDArray arr, INDArrayIndex... indices) { return offset(arr.stride(), Indices.offsets(arr.shape(), indices)); }
public LogEntry(INDArray toLog, StackTraceElement[] stackTraceElements, String status) { //this.id = toLog.id(); this.shape = toLog.shape(); this.stride = toLog.stride(); this.ndArrayType = toLog.getClass().getName(); this.length = toLog.length(); this.references = toLog.data().references(); this.dataType = toLog.data().dataType() == DataBuffer.Type.DOUBLE ? "double" : "float"; this.timestamp = System.currentTimeMillis(); this.stackTraceElements = stackTraceElements; this.status = status; }
public static void printNDArrayHeader(INDArray array) { System.out.println(array.data().dataType() + " - order=" + array.ordering() + ", offset=" + array.offset() + ", shape=" + Arrays.toString(array.shape()) + ", stride=" + Arrays.toString(array.stride()) + ", length=" + array.length() + ", data().length()=" + array.data().length()); }
public static boolean hasDefaultStridesForShape(INDArray input){ if(!strideDescendingCAscendingF(input)){ return false; } char order = input.ordering(); long[] defaultStrides; if(order == 'f'){ defaultStrides = ArrayUtil.calcStridesFortran(input.shape()); } else { defaultStrides = ArrayUtil.calcStrides(input.shape()); } return Arrays.equals(input.stride(), defaultStrides); } }
@Override public void checkDimensions(INDArray other) { assert Shape.contentEquals(other.shape(), Shape.shapeOf(shapeInformation)) : " Other array should have been shape: " + Shape.toString(Shape.shapeOf(shapeInformation)) + " but was " + Arrays.toString(other.shape()); assert Shape.contentEquals(other.stride(), Shape.stride(shapeInformation)) : " Other array should have been stride: " + Shape.toString(Shape.stride(shapeInformation)) + " but was " + Arrays.toString(other.stride()); assert Shape.offset(javaShapeInformation) == other.offset() : "Offset of this array is " + Shape.offset(javaShapeInformation) + " but other was " + other.offset(); }
/**Choose tensor dimension for operations with 3 arguments: z=Op(x,y) or similar<br> * @see #chooseElementWiseTensorDimension(INDArray) */ public static int chooseElementWiseTensorDimension(INDArray x, INDArray y, INDArray z) { if (x.isVector()) return ArrayUtil.argMax(x.shape()); // FIXME: int cast int opAlongDimensionMinStride = (int) ArrayUtil.argMinOfMax(x.stride(), y.stride(), z.stride()); int opAlongDimensionMaxLength = ArrayUtil.argMax(x.shape()); //Edge case: shapes with 1s in them can have stride of 1 on the dimensions of length 1 if (opAlongDimensionMinStride == opAlongDimensionMaxLength || x.size((int) opAlongDimensionMinStride) == 1) return opAlongDimensionMaxLength; int nOpsAlongMinStride = ArrayUtil.prod(ArrayUtil.removeIndex(x.shape(), (int) opAlongDimensionMinStride)); int nOpsAlongMaxLength = ArrayUtil.prod(ArrayUtil.removeIndex(x.shape(), opAlongDimensionMaxLength)); if (nOpsAlongMinStride <= 10 * nOpsAlongMaxLength) return opAlongDimensionMinStride; else return opAlongDimensionMaxLength; }
/** Are the elements in the buffer contiguous for this NDArray? */ public static boolean isContiguousInBuffer(INDArray in) { long length = in.length(); long dLength = in.data().length(); if (length == dLength) return true; //full buffer, always contiguous char order = in.ordering(); long[] shape = in.shape(); long[] stridesIfContiguous; if (order == 'f') { stridesIfContiguous = ArrayUtil.calcStridesFortran(shape); } else if (order == 'c') { stridesIfContiguous = ArrayUtil.calcStrides(shape); } else if (order == 'a') { stridesIfContiguous = new long[] {1, 1}; } else { throw new RuntimeException("Invalid order: not c or f (is: " + order + ")"); } return Arrays.equals(in.stride(), stridesIfContiguous); }
/** Can we do the op (X = Op(X)) directly on the arrays without breaking X up into 1d tensors first? * In general, this is possible if the elements of X are contiguous in the buffer, OR if every element * of X is at position offset+i*elementWiseStride in the buffer * */ public static boolean canDoOpDirectly(INDArray x) { if (x.elementWiseStride() < 1) return false; if (x.isVector()) return true; //For a single NDArray all we require is that the elements are contiguous in the buffer or every nth element //Full buffer -> implies all elements are contiguous (and match) long l1 = x.lengthLong(); long dl1 = x.data().length(); if (l1 == dl1) return true; //Strides are same as a zero offset NDArray -> all elements are contiguous (even if not offset 0) long[] shape1 = x.shape(); long[] stridesAsInit = (x.ordering() == 'c' ? ArrayUtil.calcStrides(shape1) : ArrayUtil.calcStridesFortran(shape1)); boolean stridesSameAsInit = Arrays.equals(x.stride(), stridesAsInit); return stridesSameAsInit; }
return otherDim; } else { int majorStride = arr.stride(-2); long vectorsAlongDimension = arr.vectorsAlongDimension(-1); double rowCalc = (double) (index * majorStride) / (double) arr.length();
/** * Choose tensor dimension for operations with 2 arguments: x=Op(x,y) or similar<br> * @see #chooseElementWiseTensorDimension(INDArray) */ public static long chooseElementWiseTensorDimension(INDArray x, INDArray y) { if (x.isVector()) return ArrayUtil.argMax(x.shape()); //Execute along the vector //doing argMin(max(x.stride(i),y.stride(i))) minimizes the maximum //separation between elements (helps CPU cache) BUT might result in a huge number //of tiny ops - i.e., addi on NDArrays with shape [5,10^6] long opAlongDimensionMinStride = ArrayUtil.argMinOfMax(x.stride(), y.stride()); //doing argMax on shape gives us smallest number of largest tensors //but may not be optimal in terms of element separation (for CPU cache etc) int opAlongDimensionMaxLength = ArrayUtil.argMax(x.shape()); // FIXME: int cast //Edge case: shapes with 1s in them can have stride of 1 on the dimensions of length 1 if (opAlongDimensionMinStride == opAlongDimensionMaxLength || x.size((int)opAlongDimensionMinStride) == 1) return opAlongDimensionMaxLength; //Using a heuristic approach here: basically if we get >= 10x as many tensors using the minimum stride //dimension vs. the maximum size dimension, use the maximum size dimension instead //The idea is to avoid choosing wrong dimension in cases like shape=[10,10^6] //Might be able to do better than this with some additional thought int nOpsAlongMinStride = ArrayUtil.prod(ArrayUtil.removeIndex(x.shape(), (int) opAlongDimensionMinStride)); int nOpsAlongMaxLength = ArrayUtil.prod(ArrayUtil.removeIndex(x.shape(), (int) opAlongDimensionMaxLength)); if (nOpsAlongMinStride <= 10 * nOpsAlongMaxLength) return opAlongDimensionMinStride; else return opAlongDimensionMaxLength; }
/** * Get a copy of a row. * * @param r the row to get */ @Override public INDArray getRow(long r) { if (isRowVector() && r == 0) return this; else if (isRowVector() && r > 0) throw new IllegalArgumentException("Illegal index for row"); INDArray result = get(NDArrayIndex.point(r), NDArrayIndex.all()); // FIXME: this is bad if (!this.isView() && this.ordering() == 'c' && result.elementWiseStride() == 1 && result.ordering() != 'c') { ((BaseNDArray) result).setShapeInformation(Nd4j.getShapeInfoProvider().createShapeInformation(result.shape(), result.stride(), 0, 1, 'c')); } return result; }