internal Object GetCodeletArgumentForMemorySpace(DataRange range, DeviceMemorySpace space) { if (_disposed) { throw new ObjectDisposedException(typeof(Data).FullName); } Debug.Assert(space != null); DataRangeCopy copy = FindDataRangeCopy(range, space); return(copy.Buffer); }
public Boolean Intersects(DataRange other) { Debug.Assert(Indices.Length == other.Indices.Length); for (Int32 index = 0; index < Indices.Length; index += 1) { if (Indices[index] != null && other.Indices[index] != null && Indices[index].Value != other.Indices[index].Value) { return(false); } } return(true); }
DataRangeCopy FindDataRangeCopy(DataRange range, DeviceMemorySpace space) { DataRangeCopy copy = null; foreach (DataRangeCopy otherCopy in DataRangeCopies) { if (range == otherCopy.Range && space == otherCopy.DeviceMemorySpace) { copy = otherCopy; break; // i hate that thing } } return(copy); }
UInt64 GetRangeSize(DataRange range) { Debug.Assert(range.Indices.Length == _dimensions.Length); UInt64 result = _elementSize; for (Int32 index = 0; index < _dimensions.Length; index += 1) { if (range.Indices[index] == null) { result *= _dimensions[index]; } } return(result); }
internal void FinishTask(Task task, DataRange range, DataAccess access, DeviceMemorySpace space) { DataRangeCopy copy = FindDataRangeCopy(range, space); Debug.Assert(copy != null); if ((access & DataAccess.Write) == DataAccess.Write) { Debug.Assert(copy.WritingTask == task); copy.WritingTask = null; } else { Debug.Assert(copy.ReadingTasks.Remove(task)); } }
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); }
Boolean IsRangeValid(DataRange range) { if (range.Indices.Length != _dimensions.Length) { return(false); } for (Int32 index = 0; index < _dimensions.Length; index += 1) { DataRangeIndex value = range.Indices[index]; if (value != null && (value.Value < 0 || value.Value >= (Int64)_dimensions[index])) { return(false); } } return(true); }
List <CollapsedDimension> CollapseRange(DataRange range) { List <CollapsedDimension> result = new List <CollapsedDimension>(); Debug.Assert(range.Indices.Length == _dimensions.Length); for (Int32 index = 0; index < _dimensions.Length; index += 1) { if (range.Indices[index] != null) { result.Add(new CollapsedDimension((Int64)_dimensions[index], (Int64)range.Indices[index].Value, 1)); } else { result.Add(new CollapsedDimension((Int64)_dimensions[index])); } } // treat element size as last dimension - will be collapsed with lower one afterwards result.Add(new CollapsedDimension((Int64)_elementSize)); for (Int32 index = result.Count - 2; index >= 0; index -= 1) { CollapsedDimension lower = result[index]; CollapsedDimension higher = result[index + 1]; if (higher.IsComplete) { // higher indexes all elements if (lower.IsComplete) { // and lower too result[index] = new CollapsedDimension(lower.Length * higher.Length); } else { // but lower covers a range or single index result[index] = new CollapsedDimension(lower.Length * higher.Length, lower.IndexStart * higher.Length, lower.IndexLength * higher.Length); } result.RemoveAt(index + 1); } else if (higher.IsSingle && lower.IsSingle) { // both consist of a single index result[index] = new CollapsedDimension(lower.Length * higher.Length, lower.IndexStart * higher.Length + higher.IndexStart, 1); result.RemoveAt(index + 1); } } return(result); }
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); }