コード例 #1
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #2
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
 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);
 }
コード例 #3
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #4
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #5
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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));
            }
        }
コード例 #6
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #7
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
 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);
 }
コード例 #8
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #9
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }
コード例 #10
0
ファイル: Data.cs プロジェクト: zonnonproject/compiler
        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);
        }