diff --git a/Samples/PinnedMemoryCopy/Program.cs b/Samples/PinnedMemoryCopy/Program.cs index eee0c6bc6..60a3f0484 100644 --- a/Samples/PinnedMemoryCopy/Program.cs +++ b/Samples/PinnedMemoryCopy/Program.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU Samples -// Copyright (c) 2021-2023 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: Program.cs @@ -36,7 +36,7 @@ static void PerformPinnedCopyUsingGCHandle(Accelerator accelerator, int dataSize // Page locked buffers enable async memory transfers using var scope = accelerator.CreatePageLockFromPinned(array); - bufferOnGPU.View.CopyFromPageLockedAsync(stream, scope); + bufferOnGPU.View.CopyFrom(stream, scope.ArrayView); // // Perform other operations... @@ -66,7 +66,7 @@ static void PerformPinnedCopyUsingGCAllocateArray(Accelerator accelerator, int d // Page locked buffers enable async memory transfers using var scope = accelerator.CreatePageLockFromPinned(array); - bufferOnGPU.View.CopyFromPageLockedAsync(stream, scope); + bufferOnGPU.View.CopyFrom(stream, scope.ArrayView); // // Perform other operations... @@ -89,7 +89,7 @@ static void PerformPinnedCopyUsingAllocatePageLockedArray(Accelerator accelerato using var bufferOnGPU = accelerator.Allocate1D(array.Length); var stream = accelerator.DefaultStream; - bufferOnGPU.View.CopyFromPageLockedAsync(stream, array); + bufferOnGPU.View.CopyFrom(stream, array.ArrayView); // // Perform other operations... @@ -99,7 +99,7 @@ static void PerformPinnedCopyUsingAllocatePageLockedArray(Accelerator accelerato stream.Synchronize(); // Retrieve the results into an existing page locked array - bufferOnGPU.View.CopyToPageLockedAsync(stream, array); + bufferOnGPU.View.CopyTo(stream, array.ArrayView); // Retrieve the results into a new array // Rely on disabled (default) or automatic page locking behavior diff --git a/Src/ILGPU.Algorithms/Optimization/IOptimizer.cs b/Src/ILGPU.Algorithms/Optimization/IOptimizer.cs index ec76a876d..84aac8243 100644 --- a/Src/ILGPU.Algorithms/Optimization/IOptimizer.cs +++ b/Src/ILGPU.Algorithms/Optimization/IOptimizer.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU Algorithms -// Copyright (c) 2023 ILGPU Project +// Copyright (c) 2023-2024 ILGPU Project // www.ilgpu.net // // File: IOptimizer.cs @@ -230,7 +230,9 @@ public OptimizerRun( /// /// The data to load the particles to. public void LoadParticles(PageLockedArray2D data) => - Optimizer.Engine.PositionsView.DataView.CopyToPageLockedAsync(Stream, data); + Optimizer.Engine.PositionsView.DataView.BaseView.CopyTo( + Stream, + data.ArrayView); /// /// Loads all particle positions and converts them into a 2D array. diff --git a/Src/ILGPU.Algorithms/Optimization/OptimizationEngine.cs b/Src/ILGPU.Algorithms/Optimization/OptimizationEngine.cs index ae4327d70..a2dac98a3 100644 --- a/Src/ILGPU.Algorithms/Optimization/OptimizationEngine.cs +++ b/Src/ILGPU.Algorithms/Optimization/OptimizationEngine.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU Algorithms -// Copyright (c) 2023 ILGPU Project +// Copyright (c) 2023-2024 ILGPU Project // www.ilgpu.net // // File: OptimizationEngine.cs @@ -13,6 +13,7 @@ using ILGPU.Algorithms.Vectors; using ILGPU.Runtime; using ILGPU.Util; +using ILGPU; using System; using System.Diagnostics; using System.Numerics; @@ -396,9 +397,9 @@ public void LoadBounds( boundsElementBufferCPU[i, 1] = upperBounds[i]; } - boundsElementView.DataView.CopyFromPageLockedAsync( + boundsElementView.DataView.BaseView.CopyFrom( stream, - boundsElementBufferCPU); + boundsElementBufferCPU.ArrayView); ConvertToVectorizedView( stream, @@ -453,7 +454,7 @@ protected virtual void LoadParametersInternal( AcceleratorStream stream, ArrayView parameters) { - parameters.CopyToPageLockedAsync(stream, parametersCPU); + parameters.CopyTo(stream, parametersCPU.ArrayView); stream.Synchronize(); } @@ -528,8 +529,8 @@ protected internal double BeginOptimization( resultEvalBufferCPU[0] = bestResult; // Copy position and best result to GPU buffers - resultElementView.CopyFromPageLockedAsync(stream, resultElementBufferCPU); - resultEvalView.BaseView.CopyFromPageLockedAsync(stream, resultEvalBufferCPU); + resultElementView.CopyFrom(stream, resultElementBufferCPU.ArrayView); + resultEvalView.BaseView.CopyFrom(stream, resultEvalBufferCPU.ArrayView); // Convert our best result view ConvertToVectorizedView( @@ -613,12 +614,12 @@ protected internal OptimizationResult FetchToCPUAsync( OptimizationResultView resultView) { // Copy result to CPU to group by range of numerical values - resultView.PositionView.CopyToPageLockedAsync( + resultView.PositionView.CopyTo( stream, - resultElementBufferCPU); - resultView.ResultView.BaseView.CopyToPageLockedAsync( + resultElementBufferCPU.ArrayView); + resultView.ResultView.BaseView.CopyTo( stream, - resultEvalBufferCPU); + resultEvalBufferCPU.ArrayView); // Return the actual result return new OptimizationResult( diff --git a/Src/ILGPU.Tests/PageLockedMemory.cs b/Src/ILGPU.Tests/PageLockedMemory.cs index cebc65f55..935ead078 100644 --- a/Src/ILGPU.Tests/PageLockedMemory.cs +++ b/Src/ILGPU.Tests/PageLockedMemory.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2021-2023 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: PageLockedMemory.cs @@ -59,10 +59,10 @@ public unsafe void PinnedUsingGCHandle() using var buffer = Accelerator.Allocate1D(array.Length); using var scope = Accelerator.CreatePageLockFromPinned(array); - buffer.View.CopyFromPageLockedAsync(scope); + buffer.View.CopyFrom(scope.ArrayView); Execute(buffer.Length, buffer.View); - buffer.View.CopyToPageLockedAsync(scope); + buffer.View.CopyTo(scope.ArrayView); Accelerator.Synchronize(); Verify1D(array, expected); } @@ -81,10 +81,10 @@ public void PinnedUsingGCAllocateArray() using var buffer = Accelerator.Allocate1D(array.Length); using var scope = Accelerator.CreatePageLockFromPinned(array); - buffer.View.CopyFromPageLockedAsync(scope); + buffer.View.CopyFrom(scope.ArrayView); Execute(buffer.Length, buffer.View); - buffer.View.CopyToPageLockedAsync(scope); + buffer.View.CopyTo(scope.ArrayView); Accelerator.Synchronize(); Verify1D(array, expected); } @@ -107,14 +107,14 @@ public void Copy(long constant) using var buff = Accelerator.Allocate1D(Length); // Start copying, create the expected array in the meantime - buff.View.CopyFromPageLockedAsync(array); + buff.View.CopyFrom(array.ArrayView); var expected = Enumerable.Repeat(constant - 5, Length).ToArray(); Accelerator.Synchronize(); Execute(array.Extent.ToIntIndex(), buff.View); Accelerator.Synchronize(); - buff.View.CopyToPageLockedAsync(array); + buff.View.CopyTo(array.ArrayView); Accelerator.Synchronize(); Assert.Equal(expected.Length, array.Length); @@ -132,7 +132,7 @@ public void GetAsArrayPageLocked() array[i] = 10; using var buff = Accelerator.Allocate1D(Length); - buff.View.CopyFromPageLockedAsync(array); + buff.View.CopyFrom(array.ArrayView); var expected = new int[Length]; for (int i = 0; i < Length; i++) diff --git a/Src/ILGPU/Runtime/ArrayViewExtensions.Generated.tt b/Src/ILGPU/Runtime/ArrayViewExtensions.Generated.tt index 336dae5c5..49fbd9fd3 100644 --- a/Src/ILGPU/Runtime/ArrayViewExtensions.Generated.tt +++ b/Src/ILGPU/Runtime/ArrayViewExtensions.Generated.tt @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2016-2021 ILGPU Project +// Copyright (c) 2016-2024 ILGPU Project // www.ilgpu.net // // File: ArrayViewExtensions.Generated.tt/ArrayViewExtensions.Generated.cs @@ -712,6 +712,7 @@ namespace ILGPU.Runtime /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this <#= viewName #> source, @@ -729,6 +730,7 @@ namespace ILGPU.Runtime /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this <#= viewName #> source, @@ -746,6 +748,7 @@ namespace ILGPU.Runtime /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this <#= viewName #> target, @@ -763,6 +766,7 @@ namespace ILGPU.Runtime /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this <#= viewName #> target, @@ -792,6 +796,7 @@ namespace ILGPU.Runtime /// This method is not supported on accelerators. /// [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this <#= typeName #>.<#= strideName #>> source, @@ -812,6 +817,7 @@ namespace ILGPU.Runtime /// This method is not supported on accelerators. /// [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this <#= typeName #>.<#= strideName #>> source, @@ -832,6 +838,7 @@ namespace ILGPU.Runtime /// This method is not supported on accelerators. /// [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this <#= typeName #>.<#= strideName #>> target, @@ -855,6 +862,7 @@ namespace ILGPU.Runtime /// This method is not supported on accelerators. /// [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this <#= typeName #>.<#= strideName #>> target, @@ -915,7 +923,7 @@ namespace ILGPU.Runtime .AllocatePageLocked<#= dimension #>D(view.Extent); // Copy the data - view.CopyToPageLockedAsync(stream, result); + view.BaseView.CopyTo(stream, result.ArrayView); stream.Synchronize(); return result; diff --git a/Src/ILGPU/Runtime/ArrayViewExtensions.cs b/Src/ILGPU/Runtime/ArrayViewExtensions.cs index 853f46f9f..a6fcb514f 100644 --- a/Src/ILGPU/Runtime/ArrayViewExtensions.cs +++ b/Src/ILGPU/Runtime/ArrayViewExtensions.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2021-2023 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: ArrayViewExtensions.cs @@ -624,7 +624,10 @@ public static unsafe void CopyToCPUUnsafeAsync( using var pageLockScope = accelerator.CreatePageLockFromPinned( new IntPtr(Unsafe.AsPointer(ref cpuData)), length); - source.CopyToPageLockedAsync(stream, pageLockScope); + source.Buffer.CopyTo( + stream, + source.IndexInBytes, + pageLockScope.ArrayView.Cast()); } else { @@ -694,7 +697,10 @@ public static unsafe void CopyFromCPUUnsafeAsync( using var pageLockScope = accelerator.CreatePageLockFromPinned( new IntPtr(Unsafe.AsPointer(ref cpuData)), length); - target.CopyFromPageLockedAsync(pageLockScope); + target.Buffer.CopyFrom( + stream, + pageLockScope.ArrayView.Cast(), + target.IndexInBytes); } else { @@ -1417,6 +1423,7 @@ public static void CopyFromCPU( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] public static void CopyToPageLockedAsync( this TView source, AcceleratorStream stream, @@ -1453,6 +1460,7 @@ public static void CopyToPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] public static void CopyFromPageLockedAsync( this TView target, AcceleratorStream stream, @@ -1488,6 +1496,7 @@ public static void CopyFromPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this TView source, @@ -1509,6 +1518,7 @@ public static void CopyToPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this TView target, @@ -1531,6 +1541,7 @@ public static void CopyFromPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this TView source, @@ -1540,7 +1551,7 @@ public static void CopyToPageLockedAsync( where T : unmanaged => source.CopyToPageLockedAsync( stream, - pageLockedArray.Scope); + pageLockedArray.Scope.AsNotNull()); /// /// Copies from the page locked memory into the given target view without @@ -1553,6 +1564,7 @@ public static void CopyToPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this TView target, @@ -1562,7 +1574,7 @@ public static void CopyFromPageLockedAsync( where T : unmanaged => target.CopyFromPageLockedAsync( stream, - pageLockedArray.Scope); + pageLockedArray.Scope.AsNotNull()); /// /// Copies from the source view into the given page locked memory without @@ -1574,13 +1586,14 @@ public static void CopyFromPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyToPageLockedAsync( this TView source, PageLockedArray pageLockedArray) where TView : IContiguousArrayView where T : unmanaged => - source.CopyToPageLockedAsync(pageLockedArray.Scope); + source.CopyToPageLockedAsync(pageLockedArray.Scope.AsNotNull()); /// /// Copies from the page locked memory into the given target view without @@ -1592,13 +1605,14 @@ public static void CopyToPageLockedAsync( /// The page locked memory. /// This method is not supported on accelerators. [NotInsideKernel] + [Obsolete("Use PageLockScope.ArrayView instead")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyFromPageLockedAsync( this TView target, PageLockedArray pageLockedArray) where TView : IContiguousArrayView where T : unmanaged => - target.CopyFromPageLockedAsync(pageLockedArray.Scope); + target.CopyFromPageLockedAsync(pageLockedArray.Scope.AsNotNull()); #endregion @@ -1678,7 +1692,7 @@ public static PageLockedArray1D GetAsPageLocked( var result = accelerator.AllocatePageLocked1D( view.Length, uninitialized: true); - view.CopyToPageLockedAsync(stream, result); + view.CopyTo(stream, result.ArrayView); stream.Synchronize(); return result; } diff --git a/Src/ILGPU/Runtime/Cuda/CudaPageLockScope.cs b/Src/ILGPU/Runtime/Cuda/CudaPageLockScope.cs index e00b813a6..5cc987884 100644 --- a/Src/ILGPU/Runtime/Cuda/CudaPageLockScope.cs +++ b/Src/ILGPU/Runtime/Cuda/CudaPageLockScope.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2021 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: CudaPageLockScope.cs @@ -32,14 +32,31 @@ internal CudaPageLockScope( CudaAccelerator accelerator, IntPtr hostPtr, long numElements) - : base(accelerator, numElements) + : base( + accelerator, + GetAddrOfLockedObject(accelerator, hostPtr, numElements), + numElements) + { + HostPtr = hostPtr; + } + + /// + /// Registers the page lock. + /// + /// The associated accelerator. + /// The host buffer pointer to page lock. + /// The number of elements in the buffer. + /// The page locked address. + private static IntPtr GetAddrOfLockedObject( + CudaAccelerator accelerator, + IntPtr hostPtr, + long numElements) { if (!accelerator.Device.SupportsMappingHostMemory) { throw new NotSupportedException( RuntimeErrorMessages.NotSupportedPageLock); } - HostPtr = hostPtr; bool supportsHostPointer = accelerator .Device @@ -51,17 +68,18 @@ internal CudaPageLockScope( flags |= MemHostRegisterFlags.CU_MEMHOSTREGISTER_DEVICEMAP; // Perform the memory registration. + var lengthInBytes = numElements * Interop.SizeOf(); CudaException.ThrowIfFailed( CurrentAPI.MemHostRegister( hostPtr, - new IntPtr(LengthInBytes), + new IntPtr(lengthInBytes), flags)); // Check whether we have to determine the actual device pointer or are able // to reuse the host pointer for all operations. if (supportsHostPointer) { - AddrOfLockedObject = hostPtr; + return hostPtr; } else { @@ -70,7 +88,7 @@ internal CudaPageLockScope( out IntPtr devicePtr, hostPtr, 0)); - AddrOfLockedObject = devicePtr; + return devicePtr; } } @@ -80,9 +98,12 @@ internal CudaPageLockScope( private IntPtr HostPtr { get; } /// - protected override void DisposeAcceleratorObject(bool disposing) => + protected override void DisposeAcceleratorObject(bool disposing) + { CudaException.VerifyDisposed( disposing, CurrentAPI.MemHostUnregister(HostPtr)); + base.DisposeAcceleratorObject(disposing); + } } } diff --git a/Src/ILGPU/Runtime/PageLockScope.cs b/Src/ILGPU/Runtime/PageLockScope.cs index cdc83b76b..1ad1e6170 100644 --- a/Src/ILGPU/Runtime/PageLockScope.cs +++ b/Src/ILGPU/Runtime/PageLockScope.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2021 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: PageLockScope.cs @@ -9,6 +9,7 @@ // Source License. See LICENSE.txt for details. // --------------------------------------------------------------------------------------- +using ILGPU.Runtime.CPU; using System; namespace ILGPU.Runtime @@ -23,17 +24,36 @@ public abstract class PageLockScope : AcceleratorObject /// Constructs a page lock scope for the accelerator. /// /// The associated accelerator. + /// The address of page locked object. /// The number of elements. - protected PageLockScope(Accelerator accelerator, long numElements) + protected PageLockScope( + Accelerator accelerator, + IntPtr addrOfLockedObject, + long numElements) : base(accelerator) { + AddrOfLockedObject = addrOfLockedObject; Length = numElements; + + if (Length > 0) + { + MemoryBuffer = CPUMemoryBuffer.Create( + accelerator, + AddrOfLockedObject, + Length, + Interop.SizeOf()); + ArrayView = MemoryBuffer.AsArrayView(0L, MemoryBuffer.Length); + } + else + { + ArrayView = ArrayView.Empty; + } } /// /// Returns the address of page locked object. /// - public IntPtr AddrOfLockedObject { get; protected set; } + public IntPtr AddrOfLockedObject { get; } /// /// Returns the number of elements. @@ -44,6 +64,27 @@ protected PageLockScope(Accelerator accelerator, long numElements) /// Returns the length of the page locked memory in bytes. /// public long LengthInBytes => Length * Interop.SizeOf(); + + /// + /// Returns the memory buffer wrapper of the .Net array. + /// + private MemoryBuffer? MemoryBuffer { get; set; } + + /// + /// Returns the array view of the underlying .Net array. + /// + public ArrayView ArrayView { get; private set; } + + /// + protected override void DisposeAcceleratorObject(bool disposing) + { + if (disposing) + { + MemoryBuffer?.Dispose(); + MemoryBuffer = null; + ArrayView = ArrayView.Empty; + } + } } /// @@ -62,12 +103,7 @@ public NullPageLockScope( Accelerator accelerator, IntPtr hostPtr, long numElements) - : base(accelerator, numElements) - { - AddrOfLockedObject = hostPtr; - } - - /// - protected override void DisposeAcceleratorObject(bool disposing) { } + : base(accelerator, hostPtr, numElements) + { } } } diff --git a/Src/ILGPU/Runtime/PageLockedArrays.cs b/Src/ILGPU/Runtime/PageLockedArrays.cs index c6daab184..e68dd5316 100644 --- a/Src/ILGPU/Runtime/PageLockedArrays.cs +++ b/Src/ILGPU/Runtime/PageLockedArrays.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2021-2023 ILGPU Project +// Copyright (c) 2021-2024 ILGPU Project // www.ilgpu.net // // File: PageLockedArrays.cs @@ -10,7 +10,6 @@ // --------------------------------------------------------------------------------------- using ILGPU.Resources; -using ILGPU.Runtime.CPU; using ILGPU.Util; using System; using System.Diagnostics; @@ -34,17 +33,10 @@ public abstract class PageLockedArray : DisposeBase /// public abstract Span Span { get; } - /// - /// Returns the memory buffer wrapper of the .Net array. - /// - protected internal MemoryBuffer MemoryBuffer { get; private set; } = - Utilities.InitNotNullable(); - /// /// Returns the page locking scope that includes the underlying array. /// - protected internal PageLockScope Scope { get; private set; } = - Utilities.InitNotNullable>(); + protected internal PageLockScope? Scope { get; private set; } /// /// Returns the array view of the underlying .Net array. @@ -76,13 +68,8 @@ protected unsafe void Initialize( if (accelerator != null && length > 0L) { - MemoryBuffer = CPUMemoryBuffer.Create( - accelerator, - ptr, - length, - Interop.SizeOf()); - ArrayView = MemoryBuffer.AsArrayView(0L, MemoryBuffer.Length); Scope = accelerator.CreatePageLockFromPinned(ptr, length); + ArrayView = Scope.ArrayView; } } @@ -105,8 +92,9 @@ protected override void Dispose(bool disposing) { if (disposing) { - MemoryBuffer?.Dispose(); Scope?.Dispose(); + Scope = null; + ArrayView = ArrayView.Empty; } base.Dispose(disposing); }