有没有办法让.NET GC管理Cuda内存?

时间:2018-01-31 12:57:09

标签: .net f# cuda garbage-collection

我正致力于a language编译F#和Cuda。虽然我对.NET对象的内存管理没有任何问题,但Cuda内存属于非托管部分,需要手动处理。

我现在对语言唯一真正的遗憾是,当前管理内存的词法范围方式使得为其编写ML库的难度更加复杂。它将代码耦合到一个令人不舒服的程度,并迫使我CPS代码库,以便得到一些处理。我现在拥有的这种基于区域的内存管理只是一种部分解决方案,如果分配的某些部分可以由GC处理,我更喜欢它。

我是否有任何选择可以做到这一点,而无需放弃.NET作为平台并为该语言编写自己的运行时?

1 个答案:

答案 0 :(得分:4)

我们通过将所有CUDA内存包装在托管包装类中(在C#中,而不是在托管C ++中)并添加了一个SafeHandle来实现这一点。这些课程有自己的处理,但SafeHandle将负责真正的处理。顺便说一下,问题是,如果您使用的是驱动程序API或运行时API。因为下面的例子会有所不同。

只是为了给你一个线索:

    /// <summary>
    /// Abstract base class for all CUDA memories (linear, pitched, array, surface).
    /// </summary>
    public abstract class CudaMemory : CudaDeviceObject, ICudaMemory
    {
        #region IArray

        /// <summary>
        ///     Dimension of Array
        /// </summary>
        int[] IArray.Dim
        {
            get { return new[] { Width, Height, Depth }; }
        }

        #endregion

        #region ICudaMemory

        /// <summary>
        /// Returns the memory type.
        /// </summary>
        public abstract CudaMemoryType MemoryType
        {
            get;
        }

        #endregion

        #region CudaDeviceObject

        /// <summary>
        /// Holds the pointer to the safe handle
        /// </summary>
        protected internal CudaSafeHandle myDevicePtr;

        /// <summary>
        /// Holds the device pointer to the device memory.
        /// </summary>
        public override SafeHandle Handle => myDevicePtr;
.
.
.

由于CUDA对纹理,数组,内存,音调记忆,曲面等有很多独特的处理方式,而且还有“破坏”方法,我们需要创建几个SafeHandles。

数组的SafeHandle如下所示。

    /// <summary>
    /// SafeHandle to control the lifetime of the Cuda context.
    /// </summary>
    public sealed class CudaSafeArrayHandle : CudaSafeHandle
    {
        public CudaSafeArrayHandle() : base( true )
        {
        }

        protected override bool ReleaseHandle()
        {
            try
            {
                CUDA.Assert(CUDADriverAPI.cuArrayDestroy(DangerousGetHandle()));
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

内存的SafeHandle如下所示:

    /// <summary>
    /// SafeHandle to control the lifetime of the Cuda context.
    /// </summary>
    public  class CudaSafeDevicePtrLinearMemoryHandle : CudaSafeDevicePtrHandle
    {
        public CudaSafeDevicePtrLinearMemoryHandle() : base(true)
        {
        }

        protected override bool ReleaseHandle()
        {
            try
            {
                CUDA.Assert(CUDADriverAPI.cuMemFree(DangerousGetHandle()));
                return true;
            }
            catch
            {
                return false;
            }
        }
    }