예제 #1
0
 public DataRangeCopy(Buffer buffer, DeviceMemorySpace space, DataRange range)
 {
     Buffer            = buffer;
     DeviceMemorySpace = space;
     Range             = range;
     ReadingTasks      = new HashSet <Task>();
 }
예제 #2
0
        internal Object StartWriteBufferRange(Buffer buffer, DataRange range, CommandQueue queue)
        {
            //Console.WriteLine("StartWriteBufferRange");
            List <CollapsedDimension> collapsedDimensions = CollapseRange(range);
            EventObject eventObject;

            if (collapsedDimensions.Count == 1)
            {
                eventObject = queue.StartWriteBuffer(_hostArray, collapsedDimensions[0].IndexStart, collapsedDimensions[0].IndexLength, buffer);
            }
            else if (collapsedDimensions.Count == 2 || collapsedDimensions.Count == 3)
            {
                if (collapsedDimensions.Count == 2)
                {
                    collapsedDimensions.Insert(0, new CollapsedDimension(1));
                }
                eventObject = queue.StartWriteBufferRect(
                    _hostArray,
                    buffer,
                    new IntPtr(collapsedDimensions[2].IndexStart),
                    new IntPtr(collapsedDimensions[1].IndexStart),
                    new IntPtr(collapsedDimensions[0].IndexStart),
                    new IntPtr(collapsedDimensions[2].IndexLength),
                    new IntPtr(collapsedDimensions[1].IndexLength),
                    new IntPtr(collapsedDimensions[0].IndexLength),
                    new IntPtr(collapsedDimensions[2].Length),
                    new IntPtr(collapsedDimensions[2].Length * collapsedDimensions[1].Length)
                    );
            }
            else
            {
                // not supported yet
                throw new NotSupportedException();
            }
            queue.Flush();
            Object condition = new Object();

            DependencyManager.RegisterOperation(condition);
            eventObject.RegisterCompletionCallback(e => {
                DependencyManager.FinishOperation(condition);
                eventObject.Dispose();
            });
            //Console.WriteLine("StartWriteBufferRange finished");
            return(condition);
        }
예제 #3
0
        internal Object StartPrepareRange(Task task, DataRange range, DataAccess access, DeviceMemorySpace space)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(typeof(Data).FullName);
            }
            Debug.Assert(WaitingTasks.Count > 0);
            Debug.Assert(WaitingTasks[0].Task == task);
            if (!IsRangeValid(range))
            {
                throw new ArgumentOutOfRangeException();
            }
            List <Object> rangeConditions = new List <Object>();
            Boolean       writing         = (access & DataAccess.Write) == DataAccess.Write;
            Boolean       oneWasDirty     = false;

            foreach (DataRangeCopy copyStuckInClusore in DataRangeCopies)
            {
                DataRangeCopy copy = copyStuckInClusore;
                if (range.Intersects(copy.Range))
                {
                    List <Object> predecessorConditions = new List <Object>();
                    // must wait for all conflicting reads/writes
                    if (copy.WritingTask != null)
                    {
                        predecessorConditions.Add(copy.WritingTask);
                    }
                    if (writing)
                    {
                        foreach (Task readingTask in copy.ReadingTasks)
                        {
                            predecessorConditions.Add(readingTask);
                        }
                    }
                    Object rangeCondition = new Object();
                    DependencyManager.RegisterOperation(rangeCondition);
                    DependencyManager.RegisterContinuation(predecessorConditions, () => {
                        // all conflicting tasks in this copy finished
                        Debug.Assert(copy.WritingTask == null);
                        if (writing)
                        {
                            Debug.Assert(copy.ReadingTasks.Count == 0);
                        }
                        if (range == copy.Range && space == copy.DeviceMemorySpace)
                        {
                            // current copy will be the one used for the task
                            DependencyManager.FinishOperationLocked(rangeCondition);
                        }
                        else
                        {
                            Object copyOrDeleteCondition = null;
                            if (copy.Dirty)
                            {
                                // transfer bytes to host
                                Object readCondition  = StartReadBufferRange(copy.Buffer, copy.Range, copy.DeviceMemorySpace.CommandQueue);
                                copyOrDeleteCondition = DependencyManager.ContinueOneWith(readCondition, () => {
                                    copy.Dirty = false;
                                });
                                oneWasDirty = true;
                            }
                            if (writing)
                            {
                                copyOrDeleteCondition = DependencyManager.ContinueOneWith(copyOrDeleteCondition, () => {
                                    // copying is not necessary or is finished
                                    Debug.Assert(copy.Dirty == false);
                                    copy.Buffer.Dispose();
                                    Debug.Assert(DataRangeCopies.Remove(copy));
                                });
                            }
                            DependencyManager.RegisterOneContinuation(copyOrDeleteCondition, () => {
                                DependencyManager.FinishOperationLocked(rangeCondition);
                            });
                        }
                    });
                    rangeConditions.Add(rangeCondition);
                }
            }
            // dependencies of all conflicting ranges are in rangeConditions
            Object waitFinishedCondition = WaitingTasks[0].Condition;

            DependencyManager.RegisterContinuation(rangeConditions, () => {
                // now there should not be any conflicting ranges anymore
                // try to find the matching copy
                DataRangeCopy copy       = FindDataRangeCopy(range, space);
                Object transferCondition = null;
                if (oneWasDirty || copy == null)
                {
                    if (copy == null)
                    {
                        Buffer buffer = ComputeManager.Context.CreateBuffer(GetRangeSize(range), BufferFlags.ReadWrite);
                        copy          = new DataRangeCopy(buffer, space, range);
                        DataRangeCopies.Add(copy);
                    }
                    // transfer host data to buffer
                    transferCondition = StartWriteBufferRange(copy.Buffer, range, space.CommandQueue);
                }
                DependencyManager.RegisterOneContinuation(transferCondition, () => {
                    // range was transferred to buffer or no transfer was necessary
                    Debug.Assert(WaitingTasks.Count > 0);
                    Debug.Assert(WaitingTasks[0].Task == task);
                    Debug.Assert(copy.WritingTask == null);
                    if (writing)
                    {
                        copy.WritingTask = task;
                        copy.Dirty       = true;
                    }
                    else
                    {
                        copy.ReadingTasks.Add(task);
                    }
                    WaitingTasks.RemoveAt(0);
                    DependencyManager.FinishOperationLocked(waitFinishedCondition);
                });
            });
            return(waitFinishedCondition);
        }