.net - .NET 中的 CUDA 全局内存释放问题

标签 .net interop idisposable cuda garbage-collection

我有一个类(参见下面的示例),它充当 CUDA 内存结构的 .NET 包装器,
使用 cudaMalloc() 分配并使用 IntPtr 类型的成员字段引用。
(该类使用 native C DLL 的 DllImport,它包装了各种 CUDA 功能。)

dispose 方法检查指针是否为 IntPtr.Zero,如果不是则调用 cudaFree()
成功释放内存(返回 CUDA 成功)
并将指针设置为 IntPtr.Zero。

Finalize方法调用dispose方法。

问题是,如果调用 Finalize 方法而之前没有调用 dispose,
然后cudaFree()函数设置一个错误代码“无效的设备指针”。

我检查过,cudaFree() 收到的地址与 cudaMalloc() 返回的地址相同,并且之前没有调用过 dispose()。

当我添加对 dispose() 的显式调用时,相同的地址已成功释放。

我发现的唯一解决方法是不从终结器调用 dispose 方法,但是,如果不总是调用 dispose(),这可能会导致内存泄漏。

有什么想法为什么会发生这种情况吗? - 我在 Windows Vista 64 位 + GeForce 8800 和 Windows XP 32 位 + Quadro FX 上的 .NET 3.5 SP1 下使用 CUDA 2.2 和 2.3 时遇到了同样的问题(不确定是哪个数字)。

class CudaEntity : IDisposable
{
    private IntPtr dataPointer;

    public CudaEntity()
    {
        // Calls cudaMalloc() via DllImport,
        // receives error code and throws expection if not 0
        // assigns value to this.dataPointer
    }

    public Dispose()
    {
        if (this.dataPointer != IntPtr.Zero)
        {
            // Calls cudaFree() via DllImport,
            // receives error code and throws expection if not 0

            this.dataPointer = IntPtr.Zero;
        }
    }

    ~CudaEntity()
    {
        Dispose();
    }
}
{
    // this code works
    var myEntity = new CudaEntity();
    myEntity.Dispose();
}
{
    // This code cause a "invalid device pointer"
    // error on finalizer's call to cudaFree()
    var myEntity = new CudaEntity();
}

最佳答案

问题是终结器是在 GC 线程上执行的,在一个线程中分配的 CUDA 资源不能在另一个线程中使用。 CUDA 编程指南的片段:

Several host threads can execute device code on the same device, but by design, a host thread can execute device code on only one device. As a consequence, multiple host threads are required to execute device code on multiple devices. Also, any CUDA resources created through the runtime in one host thread cannot be used by the runtime from another host thread.

最好的选择是使用 using 语句,它确保 Dispose() 方法始终在“ protected ”代码块的末尾被调用:

using(CudaEntity ent = new CudaEntity())
{

}

关于.net - .NET 中的 CUDA 全局内存释放问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1449789/

相关文章:

c# - 为什么C#创建对象时要选择接口(interface)类型?

c# - Javascript 更新为 asp :HiddenField isnot detected server side in IE, 但适用于 Chrome

.net - Windows Azure REST Api 背后的技术是什么?

c# - 如何使用 c# 中未注册的 dll?

c# - 应该级联应用 IDisposable 吗?

c# - 将新段落追加到 RichTextBox

.net - ListView 空标记文本

visual-c++ - 如何向我的 C# 应用程序公开 C++ 方法?

c# - 有没有办法确保在 IDisposable 类的反序列化期间发生异常时调用 Dispose()?

java - 是否应该将 Closeable 用作 .NET 的 IDisposable 的 Java 等效项?