internal DateTime GetAvailabilityTime(DataRange range, DataAccess access, DeviceMemorySpace memorySpace) { if (_disposed) { throw new ObjectDisposedException(typeof(Data).FullName); } Debug.Assert(memorySpace != null); if (!IsRangeValid(range)) { throw new ArgumentOutOfRangeException(); } Boolean transfer = false; DateTime result = DateTime.Now; foreach (DataRangeCopy copy in DataRangeCopies) { if (range.Intersects(copy.Range)) { DateTime rangeLastFinishTime = DateTime.Now; // maintain consistency if (copy.WritingTask != null) { rangeLastFinishTime = Max(rangeLastFinishTime, copy.WritingTask.ScheduledTaskInfo.FinishTime); } if ((access & DataAccess.Write) == DataAccess.Write) { // task will be writing, so we also have to wait for reading tasks foreach (Task task in copy.ReadingTasks) { rangeLastFinishTime = Max(rangeLastFinishTime, task.ScheduledTaskInfo.FinishTime); } } if ((range != copy.Range || memorySpace != copy.DeviceMemorySpace) && copy.Dirty) { // copy is dirty, needs to transfer this copy to the host rangeLastFinishTime += TimeSpan.FromSeconds(GetRangeSize(copy.Range) / copy.DeviceMemorySpace.HostTransferSpeed); transfer = true; } result = Max(result, rangeLastFinishTime); } } if (transfer) { // host data was modified, transfer fresh bytes to the range result += TimeSpan.FromSeconds(GetRangeSize(range) / memorySpace.HostTransferSpeed); } return(result); }
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); }