예제 #1
0
        public FloatTensor Abs(bool inline = false)
// Returns a new Tensor with the smallest integer greater than or equal to each element
        {
            FloatTensor result = inline ? this : this.Copy();

            if (dataOnGpu)
            {
                result.Gpu(this.shader);
                if (inline)
                {
                    AbsGPU_(); return(this);
                }
                else
                {
                    return(AbsGPU(result));
                }
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = (float)(Math.Abs(Data [i]));
                    }
                });
            }
            return(result);
        }
예제 #2
0
        public FloatTensor Pow(FloatTensor x, bool inline = false, FloatTensor result = null)
        {
            if (!IsContiguous() || !x.IsContiguous())
            {
                throw new InvalidOperationException("All tensors must be contiguous, call Contiguous() to convert");
            }

            // Check if both tensors are compatible for sum
            SameSizeDimensionsShapeAndLocation(ref x);

            result = HookAutograd(ref result, ref x, "pow_elem", inline);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (!inline)
                {
                    return(PowElemGPU(x, result));
                }
                result.PowElemGPU_(x);
                return(this);
            }

            result.Data = data.AsParallel().Zip(x.Data.AsParallel(), (a, b) => (float)Math.Pow((double)a, b))
                          .ToArray();

            return(result);
        }
예제 #3
0
        public FloatTensor MM(FloatTensor x)
        {
            if (this.shape.Length != 2 || x.shape.Length != 2)
            {
                throw new InvalidOperationException(
                          "Cannot do MM on tensors that aren't 2 dimentional. Try calling view() to reshape");
            }

            var resultShape = new int[2];

            resultShape[0] = shape[0];
            resultShape[1] = x.shape[1];

            var result = new FloatTensor(_controller: controller, _shape: resultShape);

            if (this.dataOnGpu)
            {
                result.Gpu(shader);
            }

            result.AddMatrixMultiply(this, x);

            if (autograd)
            {
                HookAutograd(ref result, ref x, "mm");
            }

            return(result);
        }
예제 #4
0
        public FloatTensor Div(FloatTensor x, bool inline = false, FloatTensor result = null)
        {
            if (!IsContiguous() || !x.IsContiguous())
            {
                throw new InvalidOperationException("Tensor must be contiguous, call Contiguous() to convert");
            }

            // Check if both tensors are compatible for sum
            SameSizeDimensionsShapeAndLocation(ref x);

            result = HookAutograd(ref result, ref x, "div_elem", inline);

            if (dataOnGpu & x.dataOnGpu)
            {
                result.Gpu(shader);
                if (inline)
                {
                    if (autograd)
                    {
                        throw new InvalidOperationException(
                                  "Cannot call inline functions if you intend to run backprop.");
                    }
                    DivElemGPU_(x);
                    return(this);
                }
                result = DivElemGPU(x, result);
            }
            else
            {
                result.Data = data.AsParallel().Zip(x.Data.AsParallel(), (a, b) => a / b).ToArray();
            }

            return(result);
        }
예제 #5
0
        public FloatTensor Sub(FloatTensor x)
        {
            // Check if both tensors are compatible for sum
            SameSizeDimensionsShapeAndLocation(ref x);

            FloatTensor result = new FloatTensor(shape, this.shader);

            if (dataOnGpu & x.dataOnGpu)
            {
                result.Gpu();
                SubElemGPU(x, result);
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = Data [i] - x.Data [i];
                    }
                });
            }

            return(result);
        }
예제 #6
0
        public FloatTensor Add(float value, bool inline = false, FloatTensor result = null)
        {
            result = HookAutograd(ref result, value, "add_scalar", inline);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (inline)
                {
                    AddScalarGPU_(value); return(this);
                }
                else
                {
                    return(AddScalarGPU(value, result));
                }
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = value + Data [i];
                    }
                });
            }
            return(result);
        }
예제 #7
0
        public FloatTensor Pow(FloatTensor x, bool inline = true)
        {
            // Check if both tensors are compatible for sum
            SameSizeDimensionsShapeAndLocation(ref x);

            FloatTensor result = inline ? this : this.emptyTensorCopy();

            if (dataOnGpu)
            {
                result.Gpu(this.shader);
                if (inline)
                {
                    result.PowElemGPU_(x); return(this);
                }
                else
                {
                    return(PowElemGPU(x, result));
                }
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = (float)Math.Pow((double)Data [i], x.Data [i]);
                    }
                });
            }
            return(result);
        }
예제 #8
0
        public FloatTensor Floor(bool inline = false)
        {
            FloatTensor result = inline ? this : this.emptyTensorCopy();

            if (dataOnGpu)
            {
                result.Gpu(this.shader);
                if (inline)
                {
                    FloorGPU_(); return(this);
                }
                else
                {
                    return(FloorGPU(result));
                }
            }
            var nCpu = SystemInfo.processorCount;

            Parallel.For(0, nCpu, workerId =>
            {
                var max = size * (workerId + 1) / nCpu;
                for (var i = size * workerId / nCpu; i < max; i++)
                {
                    result.Data[i] = (float)(Math.Floor(this.Data[i]));
                }
            });
            return(result);
        }
예제 #9
0
        public FloatTensor Ceil(bool inline = false)
// Returns a new Tensor with the smallest integer greater than or equal to each element
        {
            FloatTensor result = inline ? this : this.emptyTensorCopy();

            if (dataOnGpu)
            {
                //TODO: Fix GPU operations. https://github.com/OpenMined/OpenMined/issues/126
                result.Gpu(this.shader);
                if (inline)
                {
                    CeilGPU_(); return(this);
                }
                else
                {
                    return(CeilGPU(result));
                }
            }

            var nCpu = SystemInfo.processorCount;

            Parallel.For(0, nCpu, workerId =>
            {
                var max = size * (workerId + 1) / nCpu;
                for (var i = size * workerId / nCpu; i < max; i++)
                {
                    result.Data[i] = (float)(Math.Ceiling(Data[i]));
                }
            });
            return(result);
        }
예제 #10
0
        public FloatTensor Add(float value, bool inline = false)
        {
            FloatTensor result = inline ? this : this.emptyTensorCopy();

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (inline)
                {
                    AddScalarGPU_(value); return(this);
                }
                else
                {
                    return(AddScalarGPU(value, result));
                }
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = value + Data [i];
                    }
                });
            }
            return(result);
        }
예제 #11
0
        public FloatTensor Acos(bool inline = false)
        {
            FloatTensor result = factory.ctrl.floatTensorFactory.Create(this.shape);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                return(AcosGPU(result));
            }
            result.Data = data.AsParallel().Select(x => (float)Math.Acos((double)x)).ToArray();

            return(result);
        }
예제 #12
0
        public FloatTensor Div(float value, bool inline = false, FloatTensor result = null)
        {
            result = HookAutograd(ref result, value, "div_scalar", inline);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (!inline)
                {
                    return(DivScalarGPU(value, result));
                }
                DivScalarGPU_(value);
                return(this);
            }
            result.Data = data.AsParallel().Select(x => x / value).ToArray();
            return(result);
        }
예제 #13
0
        public FloatTensor Neg(bool inline = false, FloatTensor result = null)
        {
            result = HookAutograd(ref result, "neg", inline);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (!inline)
                {
                    return(NegateGPU());
                }
                NegateGPU_();
                return(this);
            }
            result.Data = data.AsParallel().Select(x => - x).ToArray();
            return(result);
        }
예제 #14
0
        public FloatTensor Div(FloatTensor x, bool inline = false)
        {
            // Check if both tensors are compatible for sum
            SameSizeDimensionsShapeAndLocation(ref x);


            FloatTensor result = inline ? this : this.emptyTensorCopy();

            if (dataOnGpu & x.dataOnGpu)
            {
                result.Gpu(shader);
                if (inline)
                {
                    if (autograd)
                    {
                        throw new InvalidOperationException("Cannot call inline functions if you intend to run backprop.");
                    }
                    DivElemGPU_(x);
                    return(this);
                }
                else
                {
                    result = DivElemGPU(x, result);
                }
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = Data [i] / x.Data [i];
                    }
                });
            }

            if (autograd)
            {
                HookAutograd(ref result, ref x, "div_elem");
            }

            return(result);
        }
예제 #15
0
        public FloatTensor Sin(bool inline = false)
        {
            FloatTensor result = factory.ctrl.floatTensorFactory.Create(shape);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (inline)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    return(SinGPU(result));
                }
            }
            result.Data = data.AsParallel().Select(x => (float)Math.Sin((double)x)).ToArray();
            return(result);
        }
예제 #16
0
        public FloatTensor View(int[] new_shape, bool inline = false)
        {
            var newSize = 1;

            for (var i = 0; i < new_shape.Length; i++)
            {
                newSize *= new_shape[i];
            }

            var result = this;

            if (newSize != size)
            {
                return(result);
            }
            if (dataOnGpu)
            {
                if (inline)
                {
                    shape = new_shape;

                    shapeBuffer.Release();
                    shapeBuffer = new ComputeBuffer(shape.Length, sizeof(int));
                    shapeBuffer.SetData(shape);
                }
                else
                {
                    result = new FloatTensor(_controller: controller, _shape: new_shape, _shader: this.shader);
                    result.Gpu(shader);
                    CopyBuffer(dataBuffer, result.DataBuffer);
                }
            }
            else if (inline)
            {
                shape = new_shape;
            }
            else
            {
                result = new FloatTensor(_controller: controller, _data: data, _shape: new_shape, _shader: shader);
            }
            return(result);
        }
예제 #17
0
        public FloatTensor Sin(bool inline = false)
        {
            FloatTensor result = factory.ctrl.floatTensorFactory.Create(shape);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                int kernel_id = shader.FindKernel("SinInt");

                shader.SetBuffer(kernel_id, "SinIntData", this.DataBuffer);
                shader.SetBuffer(kernel_id, "SinIntDataResult", result.DataBuffer);
                shader.Dispatch(kernel_id, this.size, 1, 1);
                return(result);
            }
            if (inline)
            {
                throw new NotImplementedException();
            }
            result.Data = data.AsParallel().Select(x => (float)Math.Sin((double)x)).ToArray();
            return(result);
        }
예제 #18
0
        public FloatTensor Add(float value)
        {
            var result = new FloatTensor(shape, this.shader, false);

            if (dataOnGpu)
            {
                result.Gpu();
                return(AddScalarGPU(value, result));
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = value + Data [i];
                    }
                });
            }
            return(result);
        }
예제 #19
0
        public FloatTensor Abs()
        // Returns a new Tensor with the smallest integer greater than or equal to each element
        {
            var result = new FloatTensor(shape, this.shader, dataOnGpu);

            if (dataOnGpu)
            {
                result.Gpu();
                return(AbsGPU(result));
            }
            else
            {
                var nCpu = SystemInfo.processorCount;
                Parallel.For(0, nCpu, workerId => {
                    var max = size * (workerId + 1) / nCpu;
                    for (var i = size * workerId / nCpu; i < max; i++)
                    {
                        result.Data [i] = (float)(Math.Abs(Data [i]));
                    }
                });
            }
            return(result);
        }
예제 #20
0
        public FloatTensor Pow(float value, bool inline = false, FloatTensor result = null)
        {
            if (inline & autograd)
            {
                throw new InvalidOperationException("Cannot call inline functions if you intend to run backprop.");
            }

            result = HookAutograd(ref result, value, "pow_scalar", inline);

            if (dataOnGpu)
            {
                result.Gpu(shader);
                if (!inline)
                {
                    return(PowScalarGPU(value, result));
                }
                PowScalarGPU_(value);
                return(this);
            }

            result.Data = data.AsParallel().Select(x => (float)Math.Pow((double)x, value)).ToArray();

            return(result);
        }
예제 #21
0
        // hook autograd two parents
        public FloatTensor HookAutograd(ref FloatTensor result, ref FloatTensor x, string creation_op, bool inline = false, int[] resultShape = null)
        {
            if (inline)
            {
                return(this);
            }

            // checks to see if the input has been seen previously. If so, then it assumes
            // that we should just use the previous computation graph instead of initializing
            // a new result. The assumption here is that if the same tensors are used to perform
            // the same operation, then they should output to the same memory instead of allocating
            // new memory.
            bool autograd_pre_initialized = false;

            if (result == null)
            {
                bool child_pre_initialized = false;
                int  child_index           = 0;
                if (this.children_indices.Count > 0)
                {
                    // iterate through children
                    for (int i = 0; i < this.children_indices.Count; i++)
                    {
                        FloatTensor temp = factory.Get(children_indices[i]);

                        // if a child was created using the same op as the one currently being called
                        // and the child was also created using the same tensor as x
                        // then it's exactly the same operation and we can re-use variables.
                        if (temp.creation_op == creation_op && temp.creators.Contains(x.id))
                        {
                            child_pre_initialized = true;
                            child_index           = children_indices[i];
                        }
                    }
                }

                if (child_pre_initialized)
                {
                    //Debug.Log("Id:" + this.id + " Children:" + this.children_indices.Count);
                    autograd_pre_initialized = true;
                    result = factory.Get(child_index);
                    result.Zero_();
                    //Debug.Log("Graph:148:Fetching Tensor:" + result.id + " with creation_op:" + result.creation_op + " called under creation op:" + creation_op);
                }
                else
                {
                    if (resultShape != null)
                    {
                        // initializes an empty tensor with new shape
                        result = factory.Create(
                            _shape: resultShape,
                            _dataOnGpu: dataOnGpu,
                            _autograd: x.autograd && autograd,
                            _keepgrads: keepgrads,
                            _creation_op: creation_op);
                        //Debug.Log("Graph:187:Creating Tensor:" + result.id + " with creation_op:" + result.creation_op);
                    }
                    else
                    {
                        // initializes an empty tensor with identical shape
                        result = factory.Create(
                            _shape: this.shape,
                            _data: data,
                            _dataBuffer: dataBuffer,
                            _shapeBuffer: shapeBuffer,
                            _shader: shader,
                            _copyData: true,
                            _dataOnGpu: dataOnGpu,
                            _autograd: x.autograd && autograd,                             // if either tensor doesn't have gradients
                            _keepgrads: keepgrads,                                         // neither does the result. This might not end up being
                            _creation_op: creation_op);                                    // a good decision in the long run. We'll see.
                        //Debug.Log("Graph:202:Creating Tensor:" + result.id + " with creation_op:" + result.creation_op);
                    }


                    // this is sortof a backup check. In theory, the result tensor should have been
                    // initialized correctly.
                    if (this.dataOnGpu)
                    {
                        result.Gpu(shader);
                    }
                }
            }

            if (autograd_pre_initialized)
            {
                this.ResetAutogradCounts();
                result.ResetAutogradCounts();
                x.ResetAutogradCounts();
            }
            else
            {
                result.InitGraph();
                result.creators.Add(this.id);
                result.creators.Add(x.id);
                result.creation_op = creation_op;

                children_indices.Add(result.Id);
                children_counts.Add(0);

                x.children_indices.Add(result.Id);
                x.children_counts.Add(0);

                this.sibling = x.id;
            }


            return(result);
        }
예제 #22
0
        public FloatTensor HookGraph(ref FloatTensor result,
                                     string creation_op,
                                     bool inline,
                                     float scalar_input          = -1,
                                     FloatTensor[] tensor_inputs = null,
                                     int[] resultShape           = null,
                                     float[] resultData          = null,
                                     IntTensor[] indices         = null)
        {
            // no dynamic graph for inline operations
            if (inline)
            {
                return(this);
            }

            bool autograd_pre_initialized = false;

            // if we don't override with a result tensor being passed in, let's first look to see if we can reuse one
            // from a previous operation - if not - we'll create our own.
            if (result == null)
            {
                bool child_pre_initialized = false;
                int  child_index           = 0;


                // iterate through all children to see if any were created using the same parameters and creation_op
                // as is currently being requested
                for (int i = 0; i < this.children_indices.Count; i++)
                {
                    FloatTensor child = factory.Get(children_indices[i]);

                    if (child.creation_op == creation_op)
                    {
                        // if this creation_op requires no parameters - then we only have to match
                        // on the creation_op itself - which we have already done.
                        if (scalar_input == -1 && (tensor_inputs == null || tensor_inputs.Length == 0))
                        {
                            child_pre_initialized = true;
                            child_index           = children_indices[i];
                            break;
                        }

                        // since there are paremeters - now this child must match all parameters exactly
                        bool keep_looking = false;

                        if (scalar_input != -1)
                        {
                            if (child.creators.Count > 1)
                            {
                                if (factory.Get(child.creators[1]).data[0] != scalar_input)
                                {
                                    keep_looking = true;
                                }
                            }
                        }

                        if (tensor_inputs != null && tensor_inputs.Length >= 1)
                        {
                            foreach (FloatTensor tensor in tensor_inputs)
                            {
                                if (!child.creators.Contains(tensor.id))
                                {
                                    keep_looking = true;
                                }
                            }
                        }

                        if (keep_looking)
                        {
                            continue;
                        }

                        // found a child that matches all parameters
                        child_pre_initialized = true;
                        child_index           = children_indices[i];
                        break;
                    }
                }

                if (child_pre_initialized)
                {
                    autograd_pre_initialized = true;
                    result = factory.Get(child_index);
                    result.Zero_();
                }
                else
                {
                    bool resultAutograd = autograd;

                    if (tensor_inputs != null)
                    {
                        foreach (FloatTensor tensor in tensor_inputs)
                        {
                            resultAutograd = tensor.autograd && resultAutograd;
                        }
                    }

                    if (resultShape == null)
                    {
                        resultShape = this.shape;

                        if (resultData == null)
                        {
                            resultData = this.data;
                        }
                    }
                    else
                    {
                        // if shape is passed in - initialize a new dataset with that shape
                        resultData = null;
                    }

                    result = factory.Create(
                        _shape: resultShape,
                        _data: resultData,
                        _dataBuffer: dataBuffer,
                        _shapeBuffer: shapeBuffer,
                        _shader: shader,
                        _copyData: true,
                        _dataOnGpu: dataOnGpu,
                        _autograd: resultAutograd,                 // if either tensor doesn't have gradients
                        _keepgrads: keepgrads,                     // neither does the result. This might not end up being
                        _creation_op: creation_op);                // a good decision in the long run. We'll see.

                    if (this.dataOnGpu)
                    {
                        result.Gpu(shader);
                    }
                }
            }
            if (autograd_pre_initialized)
            {
                this.ResetAutogradCounts();
                result.ResetAutogradCounts();

                if (tensor_inputs != null)
                {
                    foreach (FloatTensor tensor in tensor_inputs)
                    {
                        tensor.ResetAutogradCounts();
                    }
                }
            }
            else
            {
                result.InitGraph();
                result.creators.Add(this.id);
                result.creation_op = creation_op;

                children_indices.Add(result.Id);
                children_counts.Add(0);

                // hook autograd one parents - one scalar
                if (scalar_input != -1)
                {
                    result.creators.Add(factory.Create(
                                            _shape: new int[] { 1 },
                                            _data: new float[] { scalar_input },
                                            _dataBuffer: dataBuffer,
                                            _shapeBuffer: shapeBuffer,
                                            _shader: shader,
                                            _copyData: true,
                                            _dataOnGpu: dataOnGpu,
                                            _autograd: autograd,
                                            _keepgrads: keepgrads,
                                            _creation_op: creation_op).id);
                }

                // hook autograd - two parents
                if (tensor_inputs != null)
                {
                    foreach (FloatTensor tensor in tensor_inputs)
                    {
                        result.creators.Add(tensor.id);
                        tensor.children_indices.Add(result.Id);
                        tensor.children_counts.Add(0);
                    }
                }


                // special storage for the graph so that we can know which indices of the parent to
                // backprop into. note that int_creators are expected to be non-differentiable and so we do
                // not backprop into them directly
                if (indices != null && indices.Length > 0)
                {
                    if (result.int_creators.Count == 0)
                    {
                        foreach (IntTensor ind in indices)
                        {
                            result.int_creators.Add(ind.Id);
                        }
                    }
                    else if (result.int_creators.Count == indices.Length)
                    {
                        // TODO: after dynamic graph works for IntTensor you should be able to simply check to see if
                        // the ids are the same - but at the time of writing we always creating new IntTensors so that
                        // wouldn't work yet.
                    }
                    else
                    {
                        throw new Exception("Something is wrong... int_creators already existed but had the wrong length");
                    }
                }

                // TODO: this is just used so that eventually if any inline operation was run on "indices" to change it
                // (before backpropagating), we could trigger a warning that backprop will be broken.
                //indices.children_indices.Add(result.id);
            }
            return(result);
        }