Ejemplo n.º 1
0
        internal static Tensor Permute(Tensor inTensor, int[] permutations) // TODO: unify Permute() arguments
        {
            var padPermutationsToBarracudaRank = TensorShape.MaxRank - permutations.Length;

            if (padPermutationsToBarracudaRank > 0)
            {
                permutations = permutations.Concat(Enumerable.Range(permutations.Length, padPermutationsToBarracudaRank)).ToArray();
            }
            Debug.Assert(permutations.Length == TensorShape.MaxRank);

            // 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 tempOutStrides = new int[TensorShape.MaxRank + 1];

            tempOutStrides[8] = 1;
            for (int i = 7; i >= 0; --i)
            {
                tempOutStrides[i] = tempOutStrides[i + 1] * outTensor.shape[i];
            }

            var outStride = new int[reversePermute.Length];

            for (var i = 0; i < reversePermute.Length; ++i)
            {
                outStride[i] = tempOutStrides[reversePermute[i] + 1];
            }

            // inTensor strides
            var inStrides = new int[TensorShape.MaxRank];

            inStrides[7] = 1;
            for (int i = 6; i >= 0; --i)
            {
                inStrides[i] = inStrides[i + 1] * inTensor.shape[i + 1];
            }

            for (var it = new TensorIterator(inTensor.shape); it.IsValid(); ++it)
            {
                outTensor[it.d0 * outStride[0] + it.d1 * outStride[1] + it.d2 * outStride[2] + it.d3 * outStride[3] + it.d4 * outStride[4] + it.d5 * outStride[5] + it.d6 * outStride[6] + it.d7 * outStride[7]] = inTensor[
                    it.d0 * inStrides[0] + it.d1 * inStrides[1] + it.d2 * inStrides[2] + it.d3 * inStrides[3] + it.d4 * inStrides[4] + it.d5 * inStrides[5] + it.d6 * inStrides[6] + it.d7 * inStrides[7]];
            }

            Profiler.EndSample();
            return(outTensor);
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        // slow version - kept just for performance comparison and validation
        internal static Tensor PermuteSlow(Tensor readTensor, int[] permutations) // TODO: unify Permute() arguments
        {
            var padPermutationsToBarracudaRank = 8 - permutations.Length;

            if (padPermutationsToBarracudaRank > 0)
            {
                permutations = permutations.Concat(Enumerable.Range(permutations.Length, padPermutationsToBarracudaRank)).ToArray();
            }
            Assert.IsTrue(permutations.Length == 8);

            var outputTensor = new Tensor(ONNXLayout.Permute(readTensor.shape.ToArray(), permutations));

            Assert.IsTrue(outputTensor.length == readTensor.length);

            var inShape = readTensor.shape.ToArray();

            for (var s = 0; s < inShape[0]; ++s)
            {
                for (var n = 0; n < inShape[1]; ++n)
                {
                    for (var i0 = 0; i0 < inShape[2]; ++i0)
                    {
                        for (var i1 = 0; i1 < inShape[3]; ++i1)
                        {
                            for (var i2 = 0; i2 < inShape[4]; ++i2)
                            {
                                for (var h = 0; h < inShape[5]; ++h)
                                {
                                    for (var w = 0; w < inShape[6]; ++w)
                                    {
                                        for (var c = 0; c < inShape[7]; ++c)
                                        {
                                            var it  = new int[] { 0, s, n, i0, i1, i2, h, w, c }; // prepend with 0 to handle "new axis" -1 value in permutations
                                            var oS  = it[permutations[0] + 1];
                                            var oN  = it[permutations[1] + 1];
                                            var oI0 = it[permutations[2] + 1];
                                            var oI1 = it[permutations[3] + 1];
                                            var oI2 = it[permutations[4] + 1];
                                            var oH  = it[permutations[5] + 1];
                                            var oW  = it[permutations[6] + 1];
                                            var oC  = it[permutations[7] + 1];
                                            outputTensor[oS, oN, oI0, oI1, oI2, oH, oW, oC] = readTensor[s, n, i0, i1, i2, h, w, c];
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(outputTensor);
        }