public ONNXTensor Permute(int[] permutations) { // transpose both data & shape var transposedData = Permute(m_Data, permutations); var transposedShape = ONNXLayout.Permute(m_Shape, permutations); return(new ONNXTensor(transposedData, transposedShape)); }
public ONNXTensor Reshape(long[] onnxShape) { var symbolicShape = ONNXLayout.ConvertSymbolicShapeToBarracuda(onnxShape, "?"); var reshapedData = m_Data.Reshape(symbolicShape); for (var i = 0; i < onnxShape.Length; ++i) { if (onnxShape[i] < 0) { onnxShape[i] = reshapedData.shape[i]; } Debug.Assert(onnxShape[i] == reshapedData.shape[i]); } return(new ONNXTensor(reshapedData, onnxShape)); }
public Tensor ToBarracuda(string onnxLayout) { Profiler.BeginSample("ONNXTensor.ToBarracuda"); if (onnxLayout == "?") { throw new OnnxLayerImportException("Unknown ONNX layout in not supported when converting constant tensor to Barracuda"); } Debug.Assert(m_Shape.All(v => v > 0)); var permutations = ONNXLayout.AxisPermutationsForMappingONNXLayoutToBarracuda(rank, onnxLayout); Debug.Assert(rank <= permutations.Length); var outTensor = Permute(m_Data, permutations); Profiler.EndSample(); return(outTensor); }
internal static Tensor Permute(Tensor inTensor, int[] permutations) // TODO: unify Permute() arguments { var padPermutationsToBarracudaRank = 4 - permutations.Length; if (padPermutationsToBarracudaRank > 0) { permutations = permutations.Concat(Enumerable.Range(permutations.Length, padPermutationsToBarracudaRank)).ToArray(); } Debug.Assert(permutations.Length == 4); // See: https://stackoverflow.com/a/32034565 Profiler.BeginSample("ONNXTensor.Permute"); var outTensor = new Tensor(ONNXLayout.Permute(inTensor.shape.ToArray(), permutations)); Debug.Assert(outTensor.length == inTensor.length); // {0, 2, 3, 1} => {0, 3, 1, 2} // {2, 3, 1, 0} => {3, 2, 0, 1} // => {find_index(0), find_index(1), find_index(2), find_index(3)} var reversePermute = new int[permutations.Length]; for (var i = 0; i < permutations.Length; ++i) { reversePermute[i] = Array.IndexOf(permutations, i); } // outTensor strides var outStrideC = outTensor.channels; var outStrideWC = outStrideC * outTensor.width; var outStrideHWC = outStrideWC * outTensor.height; var outStride = new int[reversePermute.Length]; for (var i = 0; i < reversePermute.Length; ++i) { outStride[i] = new[] { 0, outStrideHWC, outStrideWC, outStrideC, 1 } }
public ONNXTensor(TensorProto onnxTensor) { // read shape var onnxShape = onnxTensor.Dims.ToArray(); if (onnxShape.Any(s => s == 0)) { // empty tensor, not data m_Shape = onnxShape; m_Data = null; } else { // read data var shape = ONNXLayout.ConvertShapeToBarracuda(onnxShape, onnxLayout: "?"); float[] data; if ((onnxTensor.RawData != null) && (!onnxTensor.RawData.IsEmpty)) { var byteArray = new byte[onnxTensor.RawData.Length]; onnxTensor.RawData.CopyTo(byteArray, 0); // Double if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Double) { var typedData = new double[shape.length]; Debug.Assert((sizeof(double) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Float32 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float) { data = new float[shape.length]; Debug.Assert((sizeof(float) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, data, 0, byteArray.Length); } // Float16 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float16) { var typedData = new UInt16[shape.length]; Debug.Assert((sizeof(UInt16) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => HalfHelper.HalfToSingle(x)).ToArray(); } // Int8 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int8) { var typedData = new sbyte[shape.length]; Debug.Assert((sizeof(sbyte) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Int16 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int16) { var typedData = new short[shape.length]; Debug.Assert((sizeof(short) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Int32 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int32) { var typedData = new int[shape.length]; Debug.Assert((sizeof(int) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Int64 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int64) { var typedData = new long[shape.length]; Debug.Assert((sizeof(long) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // UInt8 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Uint8) { var typedData = new byte[shape.length]; Debug.Assert((sizeof(byte) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // UInt16 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Uint16) { var typedData = new ushort[shape.length]; Debug.Assert((sizeof(ushort) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // UInt32 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Uint32) { var typedData = new uint[shape.length]; Debug.Assert((sizeof(uint) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // UInt64 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Uint64) { var typedData = new ulong[shape.length]; Debug.Assert((sizeof(ulong) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Bool else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Bool) { var typedData = new bool[shape.length]; Debug.Assert((sizeof(bool) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => x ? 1.0f : 0.0f).ToArray(); } else { throw new OnnxLayerImportException($"Tensor data type {(TensorProto.Types.DataType)onnxTensor.DataType} is not supported."); } } // Float32 else if ((onnxTensor.FloatData != null) && (onnxTensor.FloatData.Count != 0)) { Debug.Assert(shape.length == onnxTensor.FloatData.Count); data = new float[shape.length]; onnxTensor.FloatData.CopyTo(data, 0); } // Int32 else if ((onnxTensor.Int32Data != null) && (onnxTensor.Int32Data.Count != 0)) { Debug.Assert(shape.length == onnxTensor.Int32Data.Count); data = onnxTensor.Int32Data.Select(x => (float)x).ToArray(); } // Int64 else if ((onnxTensor.Int64Data != null) && (onnxTensor.Int64Data.Count != 0)) { Debug.Assert(shape.length == onnxTensor.Int64Data.Count); data = onnxTensor.Int64Data.Select(x => (float)x).ToArray(); } else { throw new OnnxLayerImportException("Could not read tensor data for constant tensor."); } m_Data = new Tensor(shape, new SharedArrayTensorData(data)); m_Shape = onnxShape; } }