我正致力于a language编译F#和Cuda。虽然我对.NET对象的内存管理没有任何问题,但Cuda内存属于非托管部分,需要手动处理。
我现在对语言唯一真正的遗憾是,当前管理内存的词法范围方式使得为其编写ML库的难度更加复杂。它将代码耦合到一个令人不舒服的程度,并迫使我CPS代码库,以便得到一些处理。我现在拥有的这种基于区域的内存管理只是一种部分解决方案,如果分配的某些部分可以由GC处理,我更喜欢它。
我是否有任何选择可以做到这一点,而无需放弃.NET作为平台并为该语言编写自己的运行时?
答案 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;
}
}
}