public DataRangeCopy(Buffer buffer, DeviceMemorySpace space, DataRange range) { Buffer = buffer; DeviceMemorySpace = space; Range = range; ReadingTasks = new HashSet <Task>(); }
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); }
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); }